cloud-control-panel/config.go

335 lines
8.8 KiB
Go

package main
/*
This simply parses the command line arguments using the default golang
package called 'flag'. This can be used as a simple template to parse
command line arguments in other programs.
It puts everything in a 'config' Protobuf which I think is a good
wrapper around the 'flags' package and doesn't need a whole mess of
global variables
*/
import "log"
import "os"
import "os/user"
import "flag"
import "fmt"
import "runtime"
// import "runtime/debug"
import "io/ioutil"
import "strings"
import "reflect"
import "bytes"
// import "sys"
import "github.com/golang/protobuf/jsonpb"
import pb "git.wit.com/wit/witProtobuf"
import "git.wit.com/wit/shell"
import "github.com/davecgh/go-spew/spew"
var config *pb.Config
// This loads the config file and marshals it into the
// config protocol buffer definition.
// Then it is very easy to pass all the config options
// around and the re-write that JSON file when the GUI
// exits
func loadConfigFile() {
// look up the user information
user, err := user.Current()
if err != nil {
onExit(err)
}
spew.Dump(user)
filename := ""
// TODO: confirm this is correct for MacOS and Windows
if runtime.GOOS == "linux" {
log.Println("loadConfigFile() OS: Linux")
filename = user.HomeDir + "/.config/cloud-control-panel.json"
} else if runtime.GOOS == "windows" {
log.Println("loadConfigFile() OS: Windows")
filename = user.HomeDir + "\\cloud-control-panel.json"
} else {
log.Println("loadConfigFile() OS: " + runtime.GOOS)
filename = user.HomeDir + "/.cloud-control-panel.json"
}
tmp := loadConfigFromFilename(filename)
config = &tmp
config.Filename = filename
}
var customUsage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
fmt.Println("")
fmt.Println("EXAMPLES:")
fmt.Println("")
fmt.Println(os.Args[0] + " --hostname test.hostname.wit.com")
fmt.Println("")
}
var defaultconfig *bool
func parseFlags() {
var hostname string
// always override the debugging flag from the command line
var debug *bool
var debugtable *bool
flag.StringVar (&hostname, "hostname", "localhost", "Your full hostname")
height := flag.Int ("height", 0, "Height of the Window")
width := flag.Int ("width", 0, "Width of the Window")
debug = flag.Bool("debug", false, "Enable debugging")
defaultconfig = flag.Bool("defaultconfig", false, "Use the default config file")
debugtable = flag.Bool("debugtable", false, "Enable GUI table debugging")
// Set the output if something fails to stdout rather than stderr
flag.CommandLine.SetOutput(os.Stdout)
flag.Usage = customUsage
flag.Parse()
if flag.Parsed() {
log.Println("flag.Parse() worked")
} else {
log.Println("flag.Parse() failed")
onExit(nil)
}
if (*width > 100) {
log.Println("ENABLE width =", int32(*width))
config.Width = int32(*width)
}
if (*height > 100) {
log.Println("ENABLE height =", int32(*height))
config.Height = int32(*height)
}
if (hostname == "") {
config.Hostname = hostname
}
// never allow these to be set in the config file
config.Debug = *debug
config.Debugtable = *debugtable
}
// Convert a Protobuf to JSON
func PBtoJSON() string {
// this makes a sample protobuf
c := pb.MakeDefaultConfig()
marshaler := &jsonpb.Marshaler{}
stuff, _ := marshaler.MarshalToString(c)
log.Println(stuff)
return stuff
}
func writeToFile(filename string, a string) {
f, _ := os.Create(filename)
f.WriteString(a)
f.Close()
}
func saveConfig() {
filename := config.Filename
if (filename == "") {
log.Println("NOT SAVING CONFIG FILE")
} else {
marshaler := &jsonpb.Marshaler{}
stuff, _ := marshaler.MarshalToString(config)
log.Println(stuff)
writeToFile(filename, stuff)
}
}
// will load the default config from within the go binary
func loadConfigFromFilename(filename string) pb.Config {
sets := pb.Config{}
b, err := ioutil.ReadFile(filename)
if err != nil {
log.Println("ioutil.ReadFile() ERROR =", err)
// This probably means this is the first time the user is opening this
sets.Errors += 1
sets.Crash = "err"
sets.Counter = 1
sets.Width = 500
sets.Height = 500
return sets
}
log.Println("ioutil.ReadFile() b =", b)
err = jsonpb.Unmarshal(strings.NewReader(string(b)), &sets)
if err != nil {
log.Println("jsonpb.Unmarshal() ERROR =", err)
}
spew.Dump(sets)
return sets
}
// will load the default config from within the go binary
func loadDefaultConfig() *pb.Config {
log.Println("TRY TO LOAD DEFAULT CONFIG")
// defaultConfig, _ := packrBox.FindString("protobuf-config.json")
b, err := packrBox.FindString("cloud-control-panel.json")
log.Println("b =", b)
log.Println("err =", err)
// var newpb *pb.Config
sets := pb.Config{}
err = jsonpb.Unmarshal(strings.NewReader(string(b)), &sets)
if err != nil {
log.Println("jsonpb.Unmarshal() ERROR =", err)
}
spew.Dump(sets)
return &sets
}
//
// This is what you call from main()
//
func parseConfig() {
// first load the config file
loadConfigFile()
// override the config file from the command line
parseFlags()
log.Println("config.width", config.Width)
log.Println("config.height", config.Height)
log.Println("config.debug", config.Debug)
// check that the config parsing worked
for key, foo := range config.Accounts {
log.Println("account = ", key, foo)
log.Println("Accounts[key] = ", config.Accounts[key])
}
if (config.Accounts == nil) {
log.Println("loadConfigFile() config.Accounts == nil")
log.Println("If debugging is on, should load default config here")
if (*defaultconfig == true) {
log.Println("Debugging is on, loading debug config accounts")
tmp := loadDefaultConfig()
config.Accounts = tmp.Accounts
log.Println("loadConfigFile() config.Accounts =", config.Accounts)
}
}
_, version, _ := shell.Run("cat VERSION")
version = fmt.Sprintf("%s", strings.Trim(version, "\n"))
// version, _ := ioutil.ReadFile("VERSION")
// version = fmt.Sprintf("%s", version.String())
perl(version)
log.Println("VERSION =", version)
log.Println("len(VERSION) =", len(version))
_, tagref, _ := shell.Run("cat .git/refs/tags/v" + version)
perl(tagref)
tagref = strings.TrimSpace(tagref)
log.Println("VERSION git tag ref =", tagref)
_, currentRef, _ := shell.Run("git rev-list -1 HEAD")
config.Gitref = chomp(currentRef)
_, goversion, _ := shell.Run("go version")
config.Goversion = chomp(goversion)
config.Dirty = false
if (tagref == config.Gitref) {
log.Println("setting config.Dirty = false")
config.Dirty = false
} else {
log.Println("setting config.Dirty = true")
config.Dirty = true
}
buf, _ := wget("https://mirrors.wit.com/cloud/control-panel/VERSION")
upstream := chompBytesBuffer(buf)
_, epoch, _ := shell.Run("git log -1 --format=%at v" + version)
// epoch = chomp(epoch)
if (! config.Dirty) {
// See if a newer version of this control panel exists
// if (epoch > time.Date().Unix())
}
log.Println("epoch =", epoch)
log.Println("version =", version)
log.Println("upstream =", upstream)
log.Println("tagref =", tagref)
log.Println("config.Gitref =", config.Gitref)
log.Println("config.Goversion =", config.Goversion)
log.Println("config.Dirty =", config.Dirty)
log.Println("runtime.Version =", runtime.Version())
log.Println("runtime Number of CPUs =", runtime.NumCPU())
log.Println("runtime Number of GoRoutines =", runtime.NumGoroutine())
log.Println("runtime.GOARCH =", runtime.GOARCH)
stackSlice := make([]byte, 12512)
s := runtime.Stack(stackSlice, false)
fmt.Printf("\n%s", stackSlice[0:s])
// blah := runtime.Stack()
spew.Dump(s)
// bi, biok := debug.ReadBuildInfo()
// log.Println("debug.BuildInfo() ok =", biok)
// spew.Dump(bi.Path)
// spew.Dump(bi.Main)
// log.Println("debug.BuildInfo.Path =", bi.Path)
errChan <- "hello"
errChan <- "hello"
errChan <- "hello"
errChan <- fmt.Errorf("mainMouseClick() got b = nil")
errChan <- "hello"
// my pid (cross platform) p, err := os.FindProcess(os.Getpid())
// send signal (cross platform) return p.Signal(syscall.SIGTERM)
// for {}
// os.Exit(0)
}
func chompBytesBuffer(buf *bytes.Buffer) string {
var bytesSplice []byte
bytesSplice = buf.Bytes()
return chomp(string(bytesSplice))
}
// TODO: fix this to chomp \n \r NULL \t and ' '
func chomp(s string) string {
// var bytesBuffer bytes.Buffer
// var bytesSplice []byte
// byteSlice := bytesBuffer.Bytes()
// b := bytes.Trim(byteSlice, "\x00") // removes NULL
s = strings.Trim(s, "\x00")
s = strings.Trim(s, "\n")
s = strings.Trim(s, "\n")
s = strings.TrimSuffix(s, "\r")
s = strings.TrimSuffix(s, "\n")
s = strings.TrimSpace(s) // this is like 'chomp' in perl
s = strings.TrimSuffix(s, "\n") // this is like 'chomp' in perl
return s
}
func perl(a ...interface{}) {
log.Println("reflect.TypeOf(a) =", reflect.TypeOf(a))
}