diff --git a/go.mod b/go.mod index fc3e96b..103df33 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/shirou/gopsutil/v3 v3.24.4 // indirect + github.com/shoenig/go-m1cpu v0.1.7 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect go.bug.st/serial v1.6.2 golang.org/x/sys v0.20.0 // indirect diff --git a/go.sum b/go.sum index 8d970de..06c2e8e 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,12 @@ github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRB github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/go-m1cpu v0.1.7 h1:C76Yd0ObKR82W4vhfjZiCp0HxcSZ8Nqd84v+HZ0qyI0= +github.com/shoenig/go-m1cpu v0.1.7/go.mod h1:KkDOw6m3ZJQAPHbrzkZki4hnx+pDRR1Lo+ldA56wD5w= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk= +github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/lib/config.go b/lib/config.go index 354079d..853d2ff 100644 --- a/lib/config.go +++ b/lib/config.go @@ -251,6 +251,12 @@ func GetConfig() (*ConfigSettings, error) { config = defaultConfig() } } + if config.IPort == nil { + config.IPort = make(map[string]ConfigPort) + } + if config.HubCreds == nil { + config.HubCreds = make(map[string]ConfigCreds) + } return config, nil } @@ -278,6 +284,12 @@ func ConfigRead() error { return fmt.Errorf("can't parse %s: %s", configPath, err) } config = &newConfig + if config.IPort == nil { + config.IPort = make(map[string]ConfigPort) + } + if config.HubCreds == nil { + config.HubCreds = make(map[string]ConfigCreds) + } return nil } @@ -378,8 +390,6 @@ func FlagParse(notecardFlags bool, notehubFlags bool) (err error) { if err := config.Write(); err != nil { return fmt.Errorf("could not write config file: %w", err) } - fmt.Printf("configuration file saved\n\n") - config.Print() } // Override, just for this session, with env vars diff --git a/notehub/main.go b/notehub/main.go index a53813d..9ef6101 100644 --- a/notehub/main.go +++ b/notehub/main.go @@ -100,6 +100,16 @@ func getFlagGroups() []lib.FlagGroup { } } +// withCreds validates credentials and then calls the provided function +func withCreds(credentials *lib.ConfigCreds, fn func() error) error { + if err := credentials.Validate(); err != nil { + config, _ := lib.GetConfig() + fmt.Printf("invalid credentials for %s: %s\n", config.Hub, err) + return fmt.Errorf("please use 'notehub -signin' or 'notehub -signin-token' to sign into Notehub") + } + return fn() +} + // Main entry point func main() { @@ -162,14 +172,14 @@ func main() { // Parse these flags and also the note tool config flags err := lib.FlagParse(false, true) if err != nil { - fmt.Printf("%s\n", err) + fmt.Printf("flags: %s\n", err) os.Exit(exitFail) } // after flags are parsed, get the resulting configuration config, err := lib.GetConfig() if err != nil { - fmt.Printf("%s\n", err) + fmt.Printf("config: %s\n", err) os.Exit(exitFail) } @@ -184,7 +194,7 @@ func main() { if flagSignIn { err = authSignIn() if err != nil { - fmt.Printf("%s\n", err) + fmt.Printf("sign-in: %s\n", err) os.Exit(exitFail) } } @@ -193,7 +203,7 @@ func main() { if flagSignInToken != "" { err = authSignInToken(flagSignInToken) if err != nil { - fmt.Printf("%s\n", err) + fmt.Printf("sign-in-token: %s\n", err) os.Exit(exitFail) } } @@ -204,7 +214,7 @@ func main() { // Process the sign-out if flagSignOut { if err := config.RemoveDefaultCredentials(); err != nil { - fmt.Printf("%s\n", err) + fmt.Printf("sign-out: %s\n", err) os.Exit(exitFail) } os.Exit(exitOk) @@ -222,11 +232,6 @@ func main() { } // Past this point, we need valid credentials, so validate them here - if err := credentials.Validate(); err != nil { - fmt.Printf("invalid credentials for %s: %s\n\n", config.Hub, err) - fmt.Printf("please use 'notehub -signin' or 'notehub -signin-token' to sign into Notehub\n") - os.Exit(exitFail) - } // See if we did something didSomething := false @@ -261,10 +266,19 @@ func main() { } // Process requests + if err == nil && flagVersion { + didSomething = true + fmt.Printf("Notehub CLI Version: %s\n", version) + } + if flagReq != "" || flagUpload != "" { - var rsp []byte - rsp, err = reqHubV0JSON(flagVerbose, lib.ConfigAPIHub(), []byte(flagReq), flagUpload, flagType, flagTags, flagNotes, flagOverwrite, flagJson, nil) - if err == nil { + didSomething = true + err = withCreds(credentials, func() (err error) { + var rsp []byte + rsp, err = reqHubV0JSON(flagVerbose, lib.ConfigAPIHub(), []byte(flagReq), flagUpload, flagType, flagTags, flagNotes, flagOverwrite, flagJson, nil) + if err != nil { + return err + } if flagOut == "" { if flagPretty { var rspo map[string]interface{} @@ -279,103 +293,115 @@ func main() { fmt.Printf("%s", rsp) } } else { - outfile, err2 := os.Create(flagOut) - if err2 != nil { - fmt.Printf("Can't create output file: %s\n", err) - os.Exit(exitFail) + var outfile *os.File + outfile, err = os.Create(flagOut) + if err != nil { + return err } outfile.Write(rsp) outfile.Close() } - didSomething = true - } + return nil + }) } // Explore the contents of the device if err == nil && flagExplore && flagScope == "" { - err = explore(flagReserved, flagVerbose, flagPretty) didSomething = true + err = withCreds(credentials, func() error { + return explore(flagReserved, flagVerbose, flagPretty) + }) } // Enter trace mode if err == nil && flagTrace { - err = trace() - didSomething = true - } - - if err == nil && flagVersion { - fmt.Printf("Notehub CLI Version: %s\n", version) didSomething = true + err = withCreds(credentials, func() error { + return trace() + }) } // Determine the scope of a later request var scopeDevices, scopeFleets []string var appMetadata AppMetadata if err == nil && flagScope != "" { - appMetadata, scopeDevices, scopeFleets, err = appGetScope(flagScope, flagVerbose) didSomething = true - if err == nil { - if len(scopeDevices) != 0 && len(scopeFleets) != 0 { - err = fmt.Errorf("'from' scope may include devices or fleets but not both") - fmt.Printf("%d devices and %d fleets\n%v\n%v\n", len(scopeDevices), len(scopeFleets), scopeDevices, scopeFleets) - } - if len(scopeDevices) == 0 && len(scopeFleets) == 0 { - err = fmt.Errorf("no devices or fleets found within the specified scope") + err = withCreds(credentials, func() (err error) { + appMetadata, scopeDevices, scopeFleets, err = appGetScope(flagScope, flagVerbose) + if err == nil { + if len(scopeDevices) != 0 && len(scopeFleets) != 0 { + err = fmt.Errorf("'from' scope may include devices or fleets but not both") + fmt.Printf("%d devices and %d fleets\n%v\n%v\n", len(scopeDevices), len(scopeFleets), scopeDevices, scopeFleets) + } + if len(scopeDevices) == 0 && len(scopeFleets) == 0 { + err = fmt.Errorf("no devices or fleets found within the specified scope") + } } - } + return err + }) } // Provision devices before doing get or set if err == nil && flagProvision { - if flagScope == "" { - err = fmt.Errorf("use -scope to specify device(s) to be provisioned") - } else { + didSomething = true + err = withCreds(credentials, func() error { + if flagScope == "" { + return fmt.Errorf("use -scope to specify device(s) to be provisioned") + } if flagProduct == "" { - err = fmt.Errorf("productUID must be specified") - } else { - if len(scopeDevices) != 0 { - err = varsProvisionDevices(appMetadata, scopeDevices, flagProduct, flagSn, flagVerbose) - } else { - err = fmt.Errorf("no devices to provision") - } + return fmt.Errorf("productUID must be specified") } - } + if len(scopeDevices) != 0 { + return varsProvisionDevices(appMetadata, scopeDevices, flagProduct, flagSn, flagVerbose) + } + return fmt.Errorf("no devices to provision") + }) } // Perform VarsGet actions based on scope if err == nil && flagScope != "" && flagVarsGet { - var vars map[string]Vars - var varsJSON []byte - if len(scopeDevices) != 0 { - vars, err = varsGetFromDevices(appMetadata, scopeDevices, flagVerbose) - } else if len(scopeFleets) != 0 { - vars, err = varsGetFromFleets(appMetadata, scopeFleets, flagVerbose) - } - if err == nil { + didSomething = true + err = withCreds(credentials, func() (err error) { + var vars map[string]Vars + var varsJSON []byte + if len(scopeDevices) != 0 { + vars, err = varsGetFromDevices(appMetadata, scopeDevices, flagVerbose) + } else if len(scopeFleets) != 0 { + vars, err = varsGetFromFleets(appMetadata, scopeFleets, flagVerbose) + } + if err != nil { + return err + } if flagPretty { varsJSON, err = note.JSONMarshalIndent(vars, "", " ") } else { varsJSON, err = note.JSONMarshal(vars) } - if err == nil { - fmt.Printf("%s\n", varsJSON) + if err != nil { + return err } - } + fmt.Printf("%s\n", varsJSON) + return nil + }) } // Perform VarsSet actions based on scope if err == nil && flagScope != "" && flagVarsSet != "" { - template := Vars{} - if strings.HasPrefix(flagVarsSet, "@") { - var templateJSON []byte - templateJSON, err = os.ReadFile(strings.TrimPrefix(flagVarsSet, "@")) - if err == nil { - err = note.JSONUnmarshal(templateJSON, &template) + didSomething = true + err = withCreds(credentials, func() (err error) { + template := Vars{} + if strings.HasPrefix(flagVarsSet, "@") { + var templateJSON []byte + templateJSON, err = os.ReadFile(strings.TrimPrefix(flagVarsSet, "@")) + if err == nil { + err = note.JSONUnmarshal(templateJSON, &template) + } + } else { + err = note.JSONUnmarshal([]byte(flagVarsSet), &template) + } + if err != nil { + return err } - } else { - err = note.JSONUnmarshal([]byte(flagVarsSet), &template) - } - if err == nil { var vars map[string]Vars var varsJSON []byte if len(scopeDevices) != 0 { @@ -383,48 +409,60 @@ func main() { } else if len(scopeFleets) != 0 { vars, err = varsSetFromFleets(appMetadata, scopeFleets, template, flagVerbose) } - if err == nil { - if flagPretty { - varsJSON, err = note.JSONMarshalIndent(vars, "", " ") - } else { - varsJSON, err = note.JSONMarshal(vars) - } - if err == nil { - fmt.Printf("%s\n", varsJSON) - } + if err != nil { + return err } - } + if flagPretty { + varsJSON, err = note.JSONMarshalIndent(vars, "", " ") + } else { + varsJSON, err = note.JSONMarshal(vars) + } + if err != nil { + return err + } + fmt.Printf("%s\n", varsJSON) + return nil + }) } // Explore the contents of the device if err == nil && len(scopeDevices) != 0 && flagExplore { didSomething = true - for _, deviceUID := range scopeDevices { - flagDevice = deviceUID - err = explore(flagReserved, flagVerbose, flagPretty) - if err != nil { - break + err = withCreds(credentials, func() (err error) { + for _, deviceUID := range scopeDevices { + flagDevice = deviceUID + err = explore(flagReserved, flagVerbose, flagPretty) + if err != nil { + return err + } } - } + return nil + }) } // If we didn't do anything and we're just asking about an app, do it if err == nil && !didSomething && (flagApp != "" || flagProduct != "") { - appMetadata, err = appGetMetadata(flagVerbose, flagVarsGet) - if err == nil { + didSomething = true + err = withCreds(credentials, func() (err error) { + appMetadata, err = appGetMetadata(flagVerbose, flagVarsGet) + if err != nil { + return err + } var metaJSON []byte if flagPretty { metaJSON, err = note.JSONMarshalIndent(appMetadata, "", " ") } else { metaJSON, err = note.JSONMarshal(appMetadata) } - if err == nil { - fmt.Printf("%s\n", metaJSON) + if err != nil { + return err } - } + fmt.Printf("%s\n", metaJSON) + return nil + }) } - // Success + // Exit if err != nil { fmt.Printf("%s\n", err) os.Exit(exitFail)