diff --git a/Dockerfile b/Dockerfile index 69aefe9..8e5a3e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM alpine:3 ENV PSU_AUTH_TOKEN="" \ PSU_CONFIG="" \ - PSU_CONFIG_LIST_KEYS="" \ + PSU_CONFIG_LIST_FORMAT="" \ PSU_ENDPOINT_GROUP_LIST_FORMAT="" \ PSU_ENDPOINT_LIST_FORMAT="" \ PSU_INSECURE="" \ diff --git a/cmd/config.go b/cmd/config.go index af80b55..4aa57fe 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -1,112 +1,15 @@ package cmd import ( - "fmt" - "os" - - "github.com/greenled/portainer-stack-utils/common" - "github.com/mitchellh/go-homedir" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/spf13/viper" ) // configCmd represents the config command var configCmd = &cobra.Command{ - Use: "config KEY [VALUE]", - Short: "Get and set configuration options", - Example: "psu config user admin", - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - // Check if it's a valid key - var keyExists bool - for _, key := range viper.AllKeys() { - if key == args[0] { - keyExists = true - break - } - } - if !keyExists { - logrus.WithFields(logrus.Fields{ - "key": args[0], - "suggestions": "Try looking up the available configuration keys: psu config ls --keys", - }).Fatal("Unknown configuration key") - } - - if len(args) == 1 { - // Get config - value, configGettingErr := getConfig(args[0]) - common.CheckError(configGettingErr) - fmt.Println(value) - } else { - // Set config - configSettingErr := setConfig(args[0], args[1]) - common.CheckError(configSettingErr) - } - }, + Use: "config", + Short: "Manage configs", } func init() { rootCmd.AddCommand(configCmd) } - -func loadCofig() (*viper.Viper, error) { - // Set config file name - var configFile string - if viper.ConfigFileUsed() != "" { - // Use config file from viper - configFile = viper.ConfigFileUsed() - } else { - // Find home directory - home, err := homedir.Dir() - if err != nil { - return &viper.Viper{}, err - } - - // Use $HOME/.psu.yaml - configFile = fmt.Sprintf("%s%s.psu.yaml", home, string(os.PathSeparator)) - } - newViper := viper.New() - newViper.SetConfigFile(configFile) - - // Read config from file - if configReadingErr := newViper.ReadInConfig(); configReadingErr != nil { - logrus.WithFields(logrus.Fields{ - "file": configFile, - }).Warn("Could not read configuration from file. Expect all configuration values to be unset.") - } - - return newViper, nil -} - -func getConfig(key string) (interface{}, error) { - newViper, configLoadingErr := loadCofig() - if configLoadingErr != nil { - return nil, configLoadingErr - } - - return newViper.Get(key), nil -} - -func setConfig(key string, value string) error { - newViper, configLoadingErr := loadCofig() - if configLoadingErr != nil { - return configLoadingErr - } - - newViper.Set(key, value) - - // Make sure the config file exists - _, fileCreationErr := os.Create(newViper.ConfigFileUsed()) - if fileCreationErr != nil { - return fileCreationErr - } - - // Write te config file - configWritingErr := newViper.WriteConfig() - if configWritingErr != nil { - return configWritingErr - } - - return nil -} diff --git a/cmd/configGet.go b/cmd/configGet.go new file mode 100644 index 0000000..a0c6744 --- /dev/null +++ b/cmd/configGet.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "fmt" + + "github.com/greenled/portainer-stack-utils/common" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +// configGetCmd represents the config get command +var configGetCmd = &cobra.Command{ + Use: "get KEY", + Short: "Get config", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + keyExists := common.CheckConfigKeyExists(args[0]) + if !keyExists { + logrus.WithFields(logrus.Fields{ + "key": args[0], + "suggestions": "Try looking up the available configuration keys: psu config ls", + }).Fatal("Unknown configuration key") + } + + // Get config + value, configGettingErr := getConfig(args[0]) + common.CheckError(configGettingErr) + fmt.Println(value) + }, +} + +func init() { + configCmd.AddCommand(configGetCmd) +} + +func getConfig(key string) (value interface{}, err error) { + newViper, err := common.LoadCofig() + if err != nil { + return + } + value = newViper.Get(key) + + return +} diff --git a/cmd/configList.go b/cmd/configList.go index ecd3eed..bae7d8e 100644 --- a/cmd/configList.go +++ b/cmd/configList.go @@ -2,7 +2,12 @@ package cmd import ( "fmt" + "os" "sort" + "strings" + "text/template" + + "github.com/greenled/portainer-stack-utils/common" "github.com/spf13/viper" @@ -21,14 +26,48 @@ var configListCmd = &cobra.Command{ return keys[i] < keys[j] }) + // Create config objects + var configs []config for _, key := range keys { - if viper.GetBool("config.list.keys") { - // List config key - fmt.Println(key) - } else { - // List config key and value - fmt.Printf("%s: %v\n", key, viper.Get(key)) + envvar := strings.Replace(key, "-", "_", -1) + envvar = strings.Replace(envvar, ".", "_", -1) + envvar = strings.ToUpper(envvar) + envvar = "PSU_" + envvar + configs = append(configs, config{ + Key: key, + EnvironmentVariable: envvar, + CurrentValue: viper.Get(key), + }) + } + + if viper.GetString("config.list.format") != "" { + // Print configs with a custom format + template, templateParsingErr := template.New("configTpl").Parse(viper.GetString("config.list.format")) + common.CheckError(templateParsingErr) + for _, c := range configs { + templateExecutionErr := template.Execute(os.Stdout, c) + common.CheckError(templateExecutionErr) + fmt.Println() } + } else { + // Print configs with a table format + writer, err := common.NewTabWriter([]string{ + "KEY", + "ENV VAR", + "CURRENT VALUE", + }) + common.CheckError(err) + for _, c := range configs { + _, err := fmt.Fprintln(writer, fmt.Sprintf( + "%s\t%s\t%v", + c.Key, + c.EnvironmentVariable, + c.CurrentValue, + )) + common.CheckError(err) + } + flushErr := writer.Flush() + common.CheckError(flushErr) } }, } @@ -36,6 +75,12 @@ var configListCmd = &cobra.Command{ func init() { configCmd.AddCommand(configListCmd) - configListCmd.Flags().Bool("keys", false, "Only list keys.") - viper.BindPFlag("config.list.keys", configListCmd.Flags().Lookup("keys")) + configListCmd.Flags().String("format", "", "Format output using a Go template.") + viper.BindPFlag("config.list.format", configListCmd.Flags().Lookup("format")) +} + +type config struct { + Key string + EnvironmentVariable string + CurrentValue interface{} } diff --git a/cmd/configSet.go b/cmd/configSet.go new file mode 100644 index 0000000..7a7f7ed --- /dev/null +++ b/cmd/configSet.go @@ -0,0 +1,55 @@ +package cmd + +import ( + "os" + + "github.com/sirupsen/logrus" + + "github.com/greenled/portainer-stack-utils/common" + + "github.com/spf13/cobra" +) + +// configSetCmd represents the config set command +var configSetCmd = &cobra.Command{ + Use: "set KEY VALUE", + Short: "Set config", + Args: cobra.ExactArgs(2), + Run: func(cmd *cobra.Command, args []string) { + keyExists := common.CheckConfigKeyExists(args[0]) + if !keyExists { + logrus.WithFields(logrus.Fields{ + "key": args[0], + "suggestions": "Try looking up the available configuration keys: psu config ls", + }).Fatal("Unknown configuration key") + } + + // Set config + configSettingErr := setConfig(args[0], args[1]) + common.CheckError(configSettingErr) + }, +} + +func init() { + configCmd.AddCommand(configSetCmd) +} + +func setConfig(key string, value string) (err error) { + newViper, err := common.LoadCofig() + if err != nil { + return + } + + newViper.Set(key, value) + + // Make sure the config file exists + _, err = os.Create(newViper.ConfigFileUsed()) + if err != nil { + return + } + + // Write te config file + err = newViper.WriteConfig() + + return +} diff --git a/common/configs.go b/common/configs.go new file mode 100644 index 0000000..59a2348 --- /dev/null +++ b/common/configs.go @@ -0,0 +1,45 @@ +package common + +import ( + "fmt" + "os" + + "github.com/mitchellh/go-homedir" + "github.com/spf13/viper" +) + +func LoadCofig() (v *viper.Viper, err error) { + // Set config file name + var configFile string + if viper.ConfigFileUsed() != "" { + // Use config file from viper + configFile = viper.ConfigFileUsed() + } else { + // Find home directory + var home string + home, err = homedir.Dir() + if err != nil { + return + } + + // Use $HOME/.psu.yaml + configFile = fmt.Sprintf("%s%s.psu.yaml", home, string(os.PathSeparator)) + } + v = viper.New() + v.SetConfigFile(configFile) + + // Read config from file + err = v.ReadInConfig() + + return +} + +func CheckConfigKeyExists(key string) (keyExists bool) { + for _, k := range viper.AllKeys() { + if k == key { + keyExists = true + break + } + } + return +}