cloud-control-panel/main.go

225 lines
6.0 KiB
Go

package main
import "log"
import "os"
import "time"
import "reflect"
// import "os/signal"
// import "syscall"
// import "runtime"
// import "fmt"
// this is the king of dns libraries
import "github.com/miekg/dns"
import "git.wit.com/wit/gui"
import pb "git.wit.com/wit/witProtobuf"
import "git.wit.com/jcarr/dnssecsocket"
import "git.wit.com/wit/shell"
import "github.com/gobuffalo/packr"
import "github.com/davecgh/go-spew/spew"
// var GITCOMMIT string // this is passed in as an ldflag
var State string // used as a State machine
var sigChan chan os.Signal
var errChan chan interface{}
type myButtonInfo struct {
Account *pb.Account // associated with what account?
Accounts []*pb.Account // associated with what account?
VM *pb.Event_VM // associated with which VM?
Custom func (*gui.GuiButton)
ADD func (*gui.GuiButton)
Name string
Action string
}
// 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
// look into this for dns if possible
// https://en.wikipedia.org/wiki/DNSCrypt
// https://en.wikipedia.org/wiki/DNS_over_HTTPS
// DNS over TLS plugin for coredns
// uses protobuf's and gRPC in pb/dns.proto
// https://github.com/coredns/coredns/tree/master/plugin/tls
// https://github.com/coredns/coredns/blob/master/pb/dns.proto
// cross platform openvpn that may work for IPv6
// https://github.com/mysteriumnetwork/go-openvpnwe
// i18n with 'po' file support
// https://github.com/leonelquinteros/gotext
// a good example of using interface{}
// https://github.com/Jeffail/tunny
// details on the correct use of LockOSThread:
// https://github.com/golang/go/wiki/LockOSThread
func onExit(err error) {
log.Println("Sleep for 1 second")
time.Sleep(1 * 1000 * 1000 * 1000)
// save the protobuf.Config as a JSON config file
saveConfig()
if (err != nil) {
panic(err)
}
os.Exit(0)
}
var packrBox packr.Box
func lookupAAAA(hostname string) string {
// lookup the IP address from DNS
dnsRR := dnssecsocket.Dnstrace(hostname, "AAAA")
spew.Dump(dnsRR)
if (dnsRR == nil) {
return "BROKEN"
}
ipaddr := dns.Field(dnsRR, 1)
log.Println("ipaddr", ipaddr)
return ipaddr
}
func main() {
go handleErrors()
// 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")
// This will parse the command line and config file
// This uses a protobuf definition and then Marshal's
// and unmarshal's that into a JSON config file
// that is human readable and editable. This is the easy way
// to pass around a configuration structure throughout a
// golang application IMHO
parseConfig()
// this checks to see if there is a newer upstream version
upgrade()
for key, foo := range config.Accounts {
log.Println("FOUND ACCOUNT = ", key, foo)
}
initChannel()
go processEvents()
v185AAAA := lookupAAAA("v000185.testing.com.customers.wprod.wit.com")
log.Println("v185AAA = ", v185AAAA)
go gorillaDial("ccp.wit.com:9000")
// go gorillaDial("stackapi-ccp.stackapi.customers.wit.com:9000")
go gui.WatchGUI()
// use this to discover what the OS thinks it's hostname is
// seems to be cross platform (?)
// Windows: WMIC computersystem where caption='current_pc_name' rename new_pc_name
hostname := fqdnGet()
log.Println("fqdnGet() = ", hostname)
config.Hostname = hostname
// this is a recursive dig for the AAAA record
// TODO: check for dns hijacking
ipAAAA := lookupAAAA(hostname)
config.IPv6 = ipAAAA
gui.Data.MouseClick = mainMouseClick
gui.Config.Width = int(config.Width)
gui.Config.Height = int(config.Height)
// Set output debugging level
gui.Config.Debug = config.Debug
gui.Config.DebugTable = config.Debugtable
log.Println("gui.Config.Debug = ", gui.Config.Debug)
log.Println("gui.Config.DebugTable = ", gui.Config.DebugTable)
// 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.StartNewWindow(false, "Splash", gui.Yaxis, showSplashBox)
if (os.Getenv("DISPLAY") == "") {
log.Println("gui.StartNewWindow() END DISPLAY =", os.Getenv("DISPLAY"))
log.Println("gui.StartNewWindow() Probably this died because your DISPLAY is not set")
}
log.Println("gui.StartNewWindow() END")
}
//
// This is GO language concept for 'recover' to keep an app from completely crashing
//
// Doing this can sometimes avoid a panic() on things like:
// panic: runtime error: slice bounds out of range
//
// In debugging mode, always panic() and never try to recover()
//
func r() {
if (gui.Config.Debug == false) {
if r := recover(); r != nil {
log.Println("recover() SOMETHING IS REALLY BROKEN r =", r)
log.Println("recover() SOMETHING IS REALLY BROKEN r =", r)
log.Println("recover() SOMETHING IS REALLY BROKEN r =", r)
panic("something")
}
}
}
func init() {
log.Println("init() WAS HERE")
log.Println("init() WAS HERE")
log.Println("init() WAS HERE")
errChan = make(chan interface{}, 3)
shell.InitCallback(handleShell) // asks for all the shell errors to be sent here
/*
sigChan = make(chan os.Signal, 3)
if runtime.GOOS != "windows" {
log.Println("loadConfigFile() OS: Windows")
signal.Notify(sigChan, syscall.SIGUSR1)
}
*/
}
// get's sent the return values and errors from git.wit.com/wit/shell/
func handleShell(err interface{}, ret int) {
log.Println("handleShell() shell.Run() END Returned ", ret)
errChan <- err
}
func handleErrors() {
for val := range errChan {
log.Println("handleErrors() val =", val)
log.Println("handleErrors() reflect.TypeOf(val) =", reflect.TypeOf(val))
log.Printf("handleErrors() val type T = %T\n", val)
}
}
// trap signals
/*
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
*/