package main import "log" import "fmt" import "os" import "time" import "os/user" import "runtime" import "runtime/debug" import "github.com/golang/protobuf/jsonpb" // import "github.com/golang/protobuf/proto" import "git.wit.com/wit/gui" import pb "git.wit.com/wit/witProtobuf" import "github.com/gobuffalo/packr" import "github.com/davecgh/go-spew/spew" // will try to get this hosts FQDN import "github.com/Showmax/go-fqdn" var GITCOMMIT string // this is passed in as an ldflag var GOVERSION string // this is passed in as an ldflag var BUILDTIME string // this is passed in as an ldflag var pbC *pb.Config // reminder to use this for JSON // https://github.com/tidwall/gjson // value := gjson.Get(json, "name.last") // println(value.String()) // value := gjson.Get(json, friends.#[last=="Murphy"].first) // use mergo to merge structs // import "github.com/imdario/mergo" // mergo.Merge(&dest, src) // always sorted slice (new project) // https://github.com/yaa110/sslice // several smart slice functions (new project. April 2019) // https://github.com/elliotchance/pie func onExit(err error) { log.Println("Sleep for 1 second") time.Sleep(1 * 1000 * 1000 * 1000) filename := pbC.Filename if (filename == "") { log.Println("NOT SAVING CONFIG FILE") } else { marshaler := &jsonpb.Marshaler{} stuff, _ := marshaler.MarshalToString(pbC) log.Println(stuff) // TODO: Fix this log.Println("FIXME: NOT SAVING CONFIG FILE AS:", filename) /* f, err := os.Create(filename + ".yaml") if err == nil { // DumpTo(f, "yaml") } f, err = os.Create(filename) if err == nil { // DumpTo(f, "json") } */ } if (err != nil) { panic(err) } os.Exit(0) } var packrBox packr.Box func main() { // This puts all the files in that directory in the binary // This directory includes the default config file if there is not already one packrBox = packr.NewBox("./resources") defaultConfig, _ := packrBox.FindString("cloud.json") pbC = pb.MakeDefaultConfig() spew.Dump(pbC) // This will parse the command line and config file parseConfig(defaultConfig) for key, foo := range pbC.Accounts { log.Println("account = ", key, foo) } gui.Data.Config = pbC // onExit(nil) initChannel() go processEvents() go gorillaDial("v000185.testing.com.customers.wprod.wit.com:9000") go watchGUI() user, err := user.Current() if err != nil { onExit(err) } gui.Data.Width = int(pbC.Width) gui.Data.Height = int(pbC.Height) // TODO: figure out the hostname the right way hostname := fqdn.Get() log.Println("fqdn.Get() = ", hostname) gui.Data.Hostname = hostname gui.Data.IPv6 = "2604:bbc0:3:3:0:10:0:1004" gui.Data.Version = "v0.7" gui.Data.GitCommit = GITCOMMIT gui.Data.GoVersion = GOVERSION gui.Data.Buildtime = BUILDTIME gui.Data.MouseClick = mainButtonClick gui.Data.HomeDir = user.HomeDir // Set output debugging level gui.Data.Debug = pbC.Debugging gui.Data.DebugTable = pbC.Debugtable log.Println("gui.Data.Debug = ", gui.Data.Debug) log.Println("gui.Data.DebugTable = ", gui.Data.DebugTable) // Current User log.Println("Hi " + user.Name + " (id: " + user.Uid + ")") log.Println("Username: " + user.Username) log.Println("Home Dir: " + user.HomeDir) // Get "Real" User under sudo. // More Info: https://stackoverflow.com/q/29733575/402585 log.Println("Real User: " + os.Getenv("SUDO_USER")) // make this the main loop in an attempt to figure out the crashes // do not change this until the GUI is stable gui.GoMainWindow() } func mainButtonClick(b *gui.ButtonMap) { log.Println("mainButtonClick() b =", b) if (b == nil) { log.Println("main() BACK IN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?") log.Println("main() BACK IN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?") log.Println("main() BACK IN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?") } else { gui.Data.Current = b.Account log.Println("mainButtonClick() setting current account = ", b.Account) log.Println("main() BACK IN CONTROL PANEL CODE (button b.Name =", b.Name, ")") log.Println("\tb.Name", b.Name) log.Println("\tb.Note", b.Note) // log.Println("\tb.AccNick", b.AccNick) if (b.Note == "BACK") { gui.Data.State = "splash" } else if (b.Note == "QUIT") { onExit(nil) } else if (b.Note == "CREATE") { log.Println("TRY TO ADD A NEW VIRTUAL MACHINE") log.Println("\tTRIGGER CREATE VM") gui.Data.State = "CREATE" // gui.Data.AccNick = b.AccNick } else if (b.Note == "CONFIG") { log.Println("TRY TO LOAD DEFAULT CONFIG") defaultConfig, _ := packrBox.FindString("protobuf-config.json") log.Println("defaultConfig =", defaultConfig) log.Println("NEED TO UNMARSHAL THIS HERE") log.Println("NEED TO UNMARSHAL THIS HERE") log.Println("NEED TO UNMARSHAL THIS HERE") var newpb *pb.Config err := jsonpb.UnmarshalString(defaultConfig, newpb) log.Println("ATTEMTED TO UNMARSHAL err =", err) spew.Dump(newpb) gui.Data.State = "done" } else if (b.Note == "DEBUG") { log.Println("debug.PrintStack() (SHOULD BE JUST THIS goroutine)") debug.PrintStack() log.Println("ATTEMPT FULL STACK DUMP") buf := make([]byte, 1<<16) runtime.Stack(buf, true) log.Printf("%s", buf) log.Println("FINISHED FULL STACK DUMP") } else if (b.Note == "ADD") { log.Println("\tSHOULD ADD ACCOUNT HERE") /* if (gui.Data.AccNick != "") { log.Println("\tADDING ACCOUNT HERE") log.Println("\tADDING ACCOUNT HERE") log.Println("\tADDING ACCOUNT HERE") log.Println("\tData.AccNick = ", gui.Data.AccNick) log.Println("\tData.AccUser = ", gui.Data.AccUser) log.Println("\tData.AccPass = ", gui.Data.AccPass) config.Set("accounts." + gui.Data.AccNick + ".username", gui.Data.AccUser) config.Set("accounts." + gui.Data.AccNick + ".password", gui.Data.AccPass) config.Set("accounts." + gui.Data.AccNick + ".hostname", "v000185.testing.com.customers.wprod.wit.com") } */ } else if (b.Note == "LOGIN") { log.Println("\tTRIGGER LOGIN ACCOUNT") gui.Data.State = "SEND LOGIN" gui.Data.AccNick = b.AccNick count := 0 for { log.Println("Sleep() in buttonClick() gui.Data.State =", gui.Data.State) time.Sleep(200 * time.Millisecond) if (gui.Data.State == "NEW PROTOBUF") { if (currentMessage == nil) { gui.SocketError() gui.Data.State = "done" } else { log.Println("LOGIN currentMessage =", currentMessage) if (currentMessage.Type == pb.Event_OK) { log.Println("LOGIN WAS OK!") log.Println("LOGIN WAS OK!") log.Println("LOGIN WAS OK!") msg := "On account " + gui.Data.AccNick + "\n" gui.ErrorWindow("Login OK", msg) } if (currentMessage.Type == pb.Event_FAIL) { log.Println("LOGIN FAILED") log.Println("LOGIN FAILED") log.Println("LOGIN FAILED") msg := "On account " + gui.Data.AccNick + "\n" msg += "pb.Comment = " + currentMessage.Comment + "\n" msg += "pb.Id = " + fmt.Sprintf("%d", currentMessage.Id) + "\n" msg += "pb.Email = " + currentMessage.Email + "\n" msg += "pb.Username = " + currentMessage.Username + "\n" gui.ErrorWindow("Login Failed", msg) } currentMessage = nil gui.Data.State = "done" } return } count += 1 if (count > 10) { log.Println("ERROR: waited too long for a resposne") currentMessage = nil gui.Data.State = "done" return } } } else if (b.Note == "SHOW") { log.Println("\tTRIGGER DISPLAY ACCOUNT") gui.Data.State = "SEND WEBSOCKET" gui.Data.AccNick = b.AccNick count := 0 for { log.Println("Sleep() in buttonClick() gui.Data.State =", gui.Data.State) time.Sleep(200 * time.Millisecond) if (gui.Data.State == "NEW PROTOBUF") { if (currentMessage == nil) { gui.SocketError() gui.Data.State = "done" } else { count := countVMS(currentMessage) log.Println("SHOW VMS currentMessage =", currentMessage) log.Println("SHOW VMS count =", count) if (count != 0) { name := "Virtual Machines (" + b.AccNick + ")" mh := gui.AddVmsTab(name, count) ReadReceivedData(currentMessage, mh) } currentMessage = nil gui.Data.State = "done" } return } count += 1 if (count > 10) { log.Println("ERROR: waited too long for a resposne") currentMessage = nil gui.Data.State = "done" return } } } } if (gui.Data.State == "splash") { gui.ShowAccountQuestionTab() gui.Data.State = "account1" return } else if (gui.Data.State == "account1") { gui.ShowAccountTab() gui.Data.State = "main" } else if (gui.Data.State == "main") { gui.ShowMainTab() gui.Data.State = "done" } else if (gui.Data.State == "QUIT") { onExit(nil) } } func getToken() string { if (gui.Data.Current == nil) { log.Println("gui.Data.Current == nil") return "" } log.Println("gui.Data.Current.Token = ", gui.Data.Current.Token) return gui.Data.Current.Token } // this watches the GUI primarily to process protobuf's func watchGUI() { count := 0 // This is how you marshal into JSON from a Protobuf event := pb.MakeGetEvent() if (gui.Data.Current == nil) { log.Println("gui.Data.Current == nil") } else { event.Token = gui.Data.Current.Token } // event.Token = config.String("accounts." + gui.Data.AccNick + ".token") marshaler := &jsonpb.Marshaler{} stuff, _ := marshaler.MarshalToString(event) log.Println(stuff) // also: // var j *bytes.Buffer // marshaler.Marshal(j, event) // w.Write(j.Bytes()) for { if (count > 10) { log.Println("Sleep() in watchGUI() gui.Data.State =", gui.Data.State) count = 0 } count += 1 time.Sleep(200 * time.Millisecond) if (gui.Data.State == "SEND WEBSOCKET") { log.Println("\tTRIGGERING WEBSOCKET HERE on AccNick =", gui.Data.AccNick) log.Println("\tTRIGGERING WEBSOCKET HERE on AccNick =", gui.Data.AccNick) log.Println("\tTRIGGERING WEBSOCKET HERE on AccNick =", gui.Data.AccNick) event := pb.MakeGetEvent() event.Token = getToken() log.Println("\tTRIGGERING WEBSOCKET HERE with event.Token =", event.Token) gorillaSendProtobuf(event) gui.Data.State = "READ PROTOBUF" } if (gui.Data.State == "SEND LOGIN") { log.Println("\tTRIGGERING LOGIN HERE on AccNick =", gui.Data.AccNick) log.Println("\tTRIGGERING LOGIN HERE on AccNick =", gui.Data.AccNick) log.Println("\tTRIGGERING LOGIN HERE on AccNick =", gui.Data.AccNick) event := pb.MakeLoginEvent() event.Token = getToken() event.Username = gui.Data.Current.Username log.Println("\tTRIGGERING LOGIN HERE with event.Token =", event.Token) gorillaSendProtobuf(event) gui.Data.State = "READ PROTOBUF" } if (gui.Data.State == "CREATE") { log.Println("\tTRIGGERING CREATE HERE") event := pb.MakeAddVmEvent() event.Username = gui.Data.Current.Username event.Token = gui.Data.Current.Token log.Println("\tTRIGGERING LOGIN HERE with event.Token =", event.Token) spew.Dump(event) gorillaSendProtobuf(event) log.Println("\tEVENT SENT TO GORILLA WEBSOCKET") gui.Data.State = "READ PROTOBUF" } if (gui.Data.State == "kill") { log.Println("gui.State = kill") log.Println("gui.State = kill") log.Println("gui.State = kill") os.Exit(0) } if (gui.Data.State == "splash") { for key, _ := range pbC.Accounts { log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Nick = ", pbC.Accounts[key].Nick) log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Username = ", pbC.Accounts[key].Username) log.Println("SETTING gui.State = main") gui.Data.State = "main"; } } } }