Rename configs to settings

This commit is contained in:
Juan Carlos Mejías Rodríguez 2019-11-27 02:23:53 -05:00
parent 796c16166e
commit 8d0bd7bc41
14 changed files with 210 additions and 210 deletions

View File

@ -18,7 +18,7 @@ PSU_KEY=value
... ...
``` ```
With configurations (if applicable): With settings (if applicable):
```yaml ```yaml
key: value key: value

View File

@ -12,9 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- A Custom User-Agent header is sent on requests to the Portainer server to identify the client. - A Custom User-Agent header is sent on requests to the Portainer server to identify the client.
- Supported platforms and architectures linux 32/64 bit, darwin 32/64 bit, windows 32/64 bit, and arm7 32/64 bit. - Supported platforms and architectures linux 32/64 bit, darwin 32/64 bit, windows 32/64 bit, and arm7 32/64 bit.
- `completion` command to print Bash completion script. - `completion` command to print Bash completion script.
- `config set` command to set configuration options. - `setting set` command to set configuration options.
- `config get` command to get configuration options. - `setting get` command to get configuration options.
- `config list|ls` command to print configuration options. - `setting list|ls` command to print configuration options.
- `--format` flag to select output format from "table", "json" or a custom Go template. Defaults to "table". - `--format` flag to select output format from "table", "json" or a custom Go template. Defaults to "table".
- `container access` command to set access control for containers. - `container access` command to set access control for containers.
- `--admins` flag to limit access to administrators. - `--admins` flag to limit access to administrators.
@ -70,7 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `--public` flag to give access to all users. - `--public` flag to give access to all users.
- `-h, --help` flags on each command to print its help. - `-h, --help` flags on each command to print its help.
- `-A, --auth-token` global flag to set Portainer auth token. - `-A, --auth-token` global flag to set Portainer auth token.
- `--config` global flag to set the path to a configuration file. Supported file formats are JSON, TOML, YAML, HCL, envfile and Java properties config files. Defaults to "$HOME/.psu.yaml". - `--settings` global flag to set the path to a configuration file. Supported file formats are JSON, TOML, YAML, HCL, envfile and Java properties config files. Defaults to "$HOME/.psu.yaml".
- `-h, --help` global flag to print global help. - `-h, --help` global flag to print global help.
- `--log-format` global flag to set log format from "text" and "json". Defaults to "text". - `--log-format` global flag to set log format from "text" and "json". Defaults to "text".
- `-v, --log-level` global flag to set log level from "panic", "faltal", "error", "warning", "info", "debug" and "trace". Defaults to "info". - `-v, --log-level` global flag to set log level from "panic", "faltal", "error", "warning", "info", "debug" and "trace". Defaults to "info".

View File

@ -1,8 +1,6 @@
FROM alpine:3.10 FROM alpine:3.10
ENV PSU_AUTH_TOKEN="" ENV PSU_AUTH_TOKEN=""
ENV PSU_CONFIG=""
ENV PSU_CONFIG_LIST_FORMAT=""
ENV PSU_CONTAINER_ACCESS_ADMINS="" ENV PSU_CONTAINER_ACCESS_ADMINS=""
ENV PSU_CONTAINER_ACCESS_ENDPOINT="" ENV PSU_CONTAINER_ACCESS_ENDPOINT=""
ENV PSU_CONTAINER_ACCESS_PRIVATE="" ENV PSU_CONTAINER_ACCESS_PRIVATE=""
@ -30,6 +28,8 @@ ENV PSU_SERVICE_ACCESS_ADMINS=""
ENV PSU_SERVICE_ACCESS_ENDPOINT="" ENV PSU_SERVICE_ACCESS_ENDPOINT=""
ENV PSU_SERVICE_ACCESS_PRIVATE="" ENV PSU_SERVICE_ACCESS_PRIVATE=""
ENV PSU_SERVICE_ACCESS_PUBLIC="" ENV PSU_SERVICE_ACCESS_PUBLIC=""
ENV PSU_SETTING_LIST_FORMAT=""
ENV PSU_SETTINGS_FILE=""
ENV PSU_STACK_ACCESS_ADMINS="" ENV PSU_STACK_ACCESS_ADMINS=""
ENV PSU_STACK_ACCESS_ENDPOINT="" ENV PSU_STACK_ACCESS_ENDPOINT=""
ENV PSU_STACK_ACCESS_PRIVATE="" ENV PSU_STACK_ACCESS_PRIVATE=""

View File

@ -1,15 +0,0 @@
package cmd
import (
"github.com/spf13/cobra"
)
// configCmd represents the config command
var configCmd = &cobra.Command{
Use: "config",
Short: "Manage configs",
}
func init() {
rootCmd.AddCommand(configCmd)
}

View File

@ -1,44 +0,0 @@
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
}

View File

@ -1,55 +0,0 @@
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
}

View File

@ -35,8 +35,8 @@ var loginCmd = &cobra.Command{
} }
// Save auth token // Save auth token
configSettingErr := setConfig("auth-token", authToken) settingErr := setSetting("auth-token", authToken)
common.CheckError(configSettingErr) common.CheckError(settingErr)
}, },
} }

View File

@ -14,7 +14,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var cfgFile string var settingsFile string
// rootCmd represents the base command when called without any subcommands // rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
@ -33,12 +33,12 @@ func Execute() {
} }
func init() { func init() {
cobra.OnInitialize(initConfig, initLogger) cobra.OnInitialize(initSettings, initLogger)
rootCmd.SetVersionTemplate("{{ version }}\n") rootCmd.SetVersionTemplate("{{ version }}\n")
cobra.AddTemplateFunc("version", version.BuildVersionString) cobra.AddTemplateFunc("version", version.BuildVersionString)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "Config file. (default \"$HOME/.psu.yaml)\"") rootCmd.PersistentFlags().StringVar(&settingsFile, "settings-file", "", "Settings file. (default \"$HOME/.psu.yaml)\"")
rootCmd.PersistentFlags().StringP("log-level", "v", "info", "Log level. One of trace, debug, info, warning, error, fatal or panic.") rootCmd.PersistentFlags().StringP("log-level", "v", "info", "Log level. One of trace, debug, info, warning, error, fatal or panic.")
rootCmd.PersistentFlags().String("log-format", "text", "Log format. One of text or json.") rootCmd.PersistentFlags().String("log-format", "text", "Log format. One of text or json.")
rootCmd.PersistentFlags().BoolP("insecure", "i", false, "Skip Portainer SSL certificate verification.") rootCmd.PersistentFlags().BoolP("insecure", "i", false, "Skip Portainer SSL certificate verification.")
@ -47,7 +47,7 @@ func init() {
rootCmd.PersistentFlags().StringP("password", "p", "", "Portainer password.") rootCmd.PersistentFlags().StringP("password", "p", "", "Portainer password.")
rootCmd.PersistentFlags().StringP("auth-token", "A", "", "Portainer auth token.") rootCmd.PersistentFlags().StringP("auth-token", "A", "", "Portainer auth token.")
rootCmd.PersistentFlags().DurationP("timeout", "t", 0, "Waiting time before aborting (like 100ms, 30s, 1h20m).") rootCmd.PersistentFlags().DurationP("timeout", "t", 0, "Waiting time before aborting (like 100ms, 30s, 1h20m).")
viper.BindPFlag("config", rootCmd.PersistentFlags().Lookup("config")) viper.BindPFlag("settings-file", rootCmd.PersistentFlags().Lookup("settings-file"))
viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level")) viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level"))
viper.BindPFlag("log-format", rootCmd.PersistentFlags().Lookup("log-format")) viper.BindPFlag("log-format", rootCmd.PersistentFlags().Lookup("log-format"))
viper.BindPFlag("insecure", rootCmd.PersistentFlags().Lookup("insecure")) viper.BindPFlag("insecure", rootCmd.PersistentFlags().Lookup("insecure"))
@ -58,11 +58,11 @@ func init() {
viper.BindPFlag("auth-token", rootCmd.PersistentFlags().Lookup("auth-token")) viper.BindPFlag("auth-token", rootCmd.PersistentFlags().Lookup("auth-token"))
} }
// initConfig reads in config file and ENV variables if set. // initSettings reads in setting file and ENV variables if set.
func initConfig() { func initSettings() {
if cfgFile != "" { if settingsFile != "" {
// Use config file from the flag. // Use setting file from the flag.
viper.SetConfigFile(cfgFile) viper.SetConfigFile(settingsFile)
} else { } else {
// Find home directory. // Find home directory.
home, err := homedir.Dir() home, err := homedir.Dir()
@ -71,7 +71,7 @@ func initConfig() {
os.Exit(1) os.Exit(1)
} }
// Search config in home directory with name ".psu" (without extension). // Search settings file in home directory with name ".psu" (without extension).
viper.AddConfigPath(home) viper.AddConfigPath(home)
viper.SetConfigName(".psu") viper.SetConfigName(".psu")
} }
@ -82,7 +82,7 @@ func initConfig() {
replacer := strings.NewReplacer("-", "_", ".", "_") replacer := strings.NewReplacer("-", "_", ".", "_")
viper.SetEnvKeyReplacer(replacer) viper.SetEnvKeyReplacer(replacer)
// If a config file is found, read it in. // If a setting file is found, read it in.
viper.ReadInConfig() viper.ReadInConfig()
} }

15
cmd/setting.go Normal file
View File

@ -0,0 +1,15 @@
package cmd
import (
"github.com/spf13/cobra"
)
// settingCmd represents the config command
var settingCmd = &cobra.Command{
Use: "setting",
Short: "Manage settings",
}
func init() {
rootCmd.AddCommand(settingCmd)
}

44
cmd/settingGet.go Normal file
View File

@ -0,0 +1,44 @@
package cmd
import (
"fmt"
"github.com/greenled/portainer-stack-utils/common"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// settingGetCmd represents the setting get command
var settingGetCmd = &cobra.Command{
Use: "get <key>",
Short: "Get setting",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
keyExists := common.CheckSettingKeyExists(args[0])
if !keyExists {
logrus.WithFields(logrus.Fields{
"key": args[0],
"suggestions": "try looking up the available setting keys: psu setting ls",
}).Fatal("unknown setting key")
}
// Get setting
value, err := getSetting(args[0])
common.CheckError(err)
fmt.Println(value)
},
}
func init() {
settingCmd.AddCommand(settingGetCmd)
}
func getSetting(key string) (value interface{}, err error) {
newViper, err := common.LoadSettings()
if err != nil {
return
}
value = newViper.Get(key)
return
}

View File

@ -15,56 +15,56 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// configListCmd represents the list command // settingListCmd represents the setting list command
var configListCmd = &cobra.Command{ var settingListCmd = &cobra.Command{
Use: "list", Use: "list",
Short: "List configs", Short: "List settings",
Aliases: []string{"ls"}, Aliases: []string{"ls"},
Example: ` Print configs in a table format: Example: ` Print settings in a table format:
psu config ls psu setting ls
Print available config keys: Print available setting keys:
psu config ls --format "{{ .Key }}" psu setting ls --format "{{ .Key }}"
Print configs in a yaml|properties format: Print settings in a yaml|properties format:
psu config ls --format "{{ .Key }}:{{ if .CurrentValue }} {{ .CurrentValue }}{{ end }}" psu setting ls --format "{{ .Key }}:{{ if .CurrentValue }} {{ .CurrentValue }}{{ end }}"
Print available environment variables: Print available environment variables:
psu config ls --format "{{ .EnvironmentVariable }}" psu setting ls --format "{{ .EnvironmentVariable }}"
Print configs in a dotenv format: Print settings in a dotenv format:
psu config ls --format "{{ .EnvironmentVariable }}={{ if .CurrentValue }}{{ .CurrentValue }}{{ end }}"`, psu setting ls --format "{{ .EnvironmentVariable }}={{ if .CurrentValue }}{{ .CurrentValue }}{{ end }}"`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Get alphabetically ordered list of config keys // Get alphabetically ordered list of setting keys
keys := viper.AllKeys() keys := viper.AllKeys()
sort.Slice(keys, func(i, j int) bool { sort.Slice(keys, func(i, j int) bool {
return keys[i] < keys[j] return keys[i] < keys[j]
}) })
// Create config objects // Create setting objects
var configs []config var settings []setting
for _, key := range keys { for _, key := range keys {
envvar := strings.Replace(key, "-", "_", -1) envvar := strings.Replace(key, "-", "_", -1)
envvar = strings.Replace(envvar, ".", "_", -1) envvar = strings.Replace(envvar, ".", "_", -1)
envvar = strings.ToUpper(envvar) envvar = strings.ToUpper(envvar)
envvar = "PSU_" + envvar envvar = "PSU_" + envvar
configs = append(configs, config{ settings = append(settings, setting{
Key: key, Key: key,
EnvironmentVariable: envvar, EnvironmentVariable: envvar,
CurrentValue: viper.Get(key), CurrentValue: viper.Get(key),
}) })
} }
switch viper.GetString("config.list.format") { switch viper.GetString("setting.list.format") {
case "table": case "table":
// Print configs in a table format // Print settings in a table format
writer, err := common.NewTabWriter([]string{ writer, err := common.NewTabWriter([]string{
"KEY", "KEY",
"ENV VAR", "ENV VAR",
"CURRENT VALUE", "CURRENT VALUE",
}) })
common.CheckError(err) common.CheckError(err)
for _, c := range configs { for _, c := range settings {
_, err := fmt.Fprintln(writer, fmt.Sprintf( _, err := fmt.Fprintln(writer, fmt.Sprintf(
"%s\t%s\t%v", "%s\t%s\t%v",
c.Key, c.Key,
@ -76,15 +76,15 @@ var configListCmd = &cobra.Command{
flushErr := writer.Flush() flushErr := writer.Flush()
common.CheckError(flushErr) common.CheckError(flushErr)
case "json": case "json":
// Print configs in a json format // Print settings in a json format
statusJSONBytes, err := json.Marshal(configs) statusJSONBytes, err := json.Marshal(settings)
common.CheckError(err) common.CheckError(err)
fmt.Println(string(statusJSONBytes)) fmt.Println(string(statusJSONBytes))
default: default:
// Print configs in a custom format // Print settings in a custom format
template, templateParsingErr := template.New("configTpl").Parse(viper.GetString("config.list.format")) template, templateParsingErr := template.New("settingTpl").Parse(viper.GetString("setting.list.format"))
common.CheckError(templateParsingErr) common.CheckError(templateParsingErr)
for _, c := range configs { for _, c := range settings {
templateExecutionErr := template.Execute(os.Stdout, c) templateExecutionErr := template.Execute(os.Stdout, c)
common.CheckError(templateExecutionErr) common.CheckError(templateExecutionErr)
fmt.Println() fmt.Println()
@ -94,15 +94,15 @@ var configListCmd = &cobra.Command{
} }
func init() { func init() {
configCmd.AddCommand(configListCmd) settingCmd.AddCommand(settingListCmd)
configListCmd.Flags().String("format", "table", `Output format. Can be "table", "json" or a Go template.`) settingListCmd.Flags().String("format", "table", `Output format. Can be "table", "json" or a Go template.`)
viper.BindPFlag("config.list.format", configListCmd.Flags().Lookup("format")) viper.BindPFlag("setting.list.format", settingListCmd.Flags().Lookup("format"))
configListCmd.SetUsageTemplate(configListCmd.UsageTemplate() + common.GetFormatHelp(config{})) settingListCmd.SetUsageTemplate(settingListCmd.UsageTemplate() + common.GetFormatHelp(setting{}))
} }
type config struct { type setting struct {
Key string Key string
EnvironmentVariable string EnvironmentVariable string
CurrentValue interface{} CurrentValue interface{}

55
cmd/settingSet.go Normal file
View File

@ -0,0 +1,55 @@
package cmd
import (
"os"
"github.com/sirupsen/logrus"
"github.com/greenled/portainer-stack-utils/common"
"github.com/spf13/cobra"
)
// settingSetCmd represents the setting set command
var settingSetCmd = &cobra.Command{
Use: "set <key> <value>",
Short: "Set setting",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
keyExists := common.CheckSettingKeyExists(args[0])
if !keyExists {
logrus.WithFields(logrus.Fields{
"key": args[0],
"suggestions": "try looking up the available setting keys: psu setting ls",
}).Fatal("unknown setting key")
}
// Set setting
err := setSetting(args[0], args[1])
common.CheckError(err)
},
}
func init() {
settingCmd.AddCommand(settingSetCmd)
}
func setSetting(key string, value string) (err error) {
newViper, err := common.LoadSettings()
if err != nil {
return
}
newViper.Set(key, value)
// Make sure the setting file exists
_, err = os.Create(newViper.ConfigFileUsed())
if err != nil {
return
}
// Write te setting file
err = newViper.WriteConfig()
return
}

View File

@ -1,47 +0,0 @@
package common
import (
"fmt"
"os"
"github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
)
// LoadCofig loads the configuration file currently used by viper into a new viper instance
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
}
// CheckConfigKeyExists checks a given configuration key exists in the default viper
func CheckConfigKeyExists(key string) (keyExists bool) {
for _, k := range viper.AllKeys() {
if k == key {
keyExists = true
break
}
}
return
}

47
common/settings.go Normal file
View File

@ -0,0 +1,47 @@
package common
import (
"fmt"
"os"
"github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
)
// LoadSettings loads the settings file currently used by viper into a new viper instance
func LoadSettings() (v *viper.Viper, err error) {
// Set settings file name
var settingsFile string
if viper.ConfigFileUsed() != "" {
// Use settings file from viper
settingsFile = viper.ConfigFileUsed()
} else {
// Find home directory
var home string
home, err = homedir.Dir()
if err != nil {
return
}
// Use $HOME/.psu.yaml
settingsFile = fmt.Sprintf("%s%s.psu.yaml", home, string(os.PathSeparator))
}
v = viper.New()
v.SetConfigFile(settingsFile)
// Read settings from file
err = v.ReadInConfig()
return
}
// CheckSettingKeyExists checks a given setting key exists in the default viper
func CheckSettingKeyExists(key string) (keyExists bool) {
for _, k := range viper.AllKeys() {
if k == key {
keyExists = true
break
}
}
return
}