diff --git a/cmd/config/get.go b/cmd/config/get.go index 01478e30..e8e0c52b 100644 --- a/cmd/config/get.go +++ b/cmd/config/get.go @@ -3,7 +3,6 @@ package config import ( "github.com/pingidentity/pingcli/cmd/common" config_internal "github.com/pingidentity/pingcli/internal/commands/config" - "github.com/pingidentity/pingcli/internal/configuration/options" "github.com/pingidentity/pingcli/internal/logger" "github.com/spf13/cobra" ) @@ -32,8 +31,6 @@ func NewConfigGetCommand() *cobra.Command { Use: "get [flags] key", } - cmd.Flags().AddFlag(options.ConfigGetProfileOption.Flag) - return cmd } diff --git a/cmd/config/list_profiles.go b/cmd/config/list_profiles.go index 7a6dad7f..fd48ce43 100644 --- a/cmd/config/list_profiles.go +++ b/cmd/config/list_profiles.go @@ -30,7 +30,10 @@ func configListProfilesRunE(cmd *cobra.Command, args []string) error { l := logger.Get() l.Debug().Msgf("Config list-profiles Subcommand Called.") - config_internal.RunInternalConfigListProfiles() + err := config_internal.RunInternalConfigListProfiles() + if err != nil { + return err + } return nil } diff --git a/cmd/config/set.go b/cmd/config/set.go index badd90b4..dea15f8b 100644 --- a/cmd/config/set.go +++ b/cmd/config/set.go @@ -3,7 +3,6 @@ package config import ( "github.com/pingidentity/pingcli/cmd/common" config_internal "github.com/pingidentity/pingcli/internal/commands/config" - "github.com/pingidentity/pingcli/internal/configuration/options" "github.com/pingidentity/pingcli/internal/logger" "github.com/spf13/cobra" ) @@ -29,8 +28,6 @@ func NewConfigSetCommand() *cobra.Command { Use: "set [flags] key=value", } - cmd.Flags().AddFlag(options.ConfigSetProfileOption.Flag) - return cmd } func configSetRunE(cmd *cobra.Command, args []string) error { diff --git a/cmd/config/set_test.go b/cmd/config/set_test.go index 18c9e8ba..60e14721 100644 --- a/cmd/config/set_test.go +++ b/cmd/config/set_test.go @@ -60,7 +60,7 @@ func TestConfigSetCmd_CheckViperConfig(t *testing.T) { testutils.CheckExpectedError(t, err, nil) mainViper := profiles.GetMainConfig().ViperInstance() - profileViperKey := profiles.GetMainConfig().ActiveProfile().Name() + "." + viperKey + profileViperKey := "default." + viperKey viperNewValue := mainViper.GetString(profileViperKey) if viperNewValue != viperNewUUID { diff --git a/cmd/config/unset.go b/cmd/config/unset.go index b94ac693..3cff854f 100644 --- a/cmd/config/unset.go +++ b/cmd/config/unset.go @@ -3,7 +3,6 @@ package config import ( "github.com/pingidentity/pingcli/cmd/common" config_internal "github.com/pingidentity/pingcli/internal/commands/config" - "github.com/pingidentity/pingcli/internal/configuration/options" "github.com/pingidentity/pingcli/internal/logger" "github.com/spf13/cobra" ) @@ -29,8 +28,6 @@ func NewConfigUnsetCommand() *cobra.Command { Use: "unset [flags] key", } - cmd.Flags().AddFlag(options.ConfigUnsetProfileOption.Flag) - return cmd } func configUnsetRunE(cmd *cobra.Command, args []string) error { diff --git a/cmd/config/unset_test.go b/cmd/config/unset_test.go index 24d13eb5..cdbe716e 100644 --- a/cmd/config/unset_test.go +++ b/cmd/config/unset_test.go @@ -46,7 +46,7 @@ func TestConfigUnsetCmd_CheckViperConfig(t *testing.T) { testutils.CheckExpectedError(t, err, nil) mainViper := profiles.GetMainConfig().ViperInstance() - profileViperKey := profiles.GetMainConfig().ActiveProfile().Name() + "." + viperKey + profileViperKey := "default." + viperKey viperNewValue := mainViper.GetString(profileViperKey) if viperOldValue == viperNewValue { t.Errorf("Expected viper configuration value to be updated. Old: %s, New: %s", viperOldValue, viperNewValue) diff --git a/cmd/request/request_test.go b/cmd/request/request_test.go index 6da7efd9..c9af9fa5 100644 --- a/cmd/request/request_test.go +++ b/cmd/request/request_test.go @@ -40,7 +40,7 @@ func TestRequestCmd_Execute(t *testing.T) { // Capture response json body captureGroupName := "BodyJSON" - re := regexp.MustCompile(fmt.Sprintf(`(?s)^.*response: (?P<%s>\{.*\}).*status: .*$`, captureGroupName)) + re := regexp.MustCompile(fmt.Sprintf(`(?s)^.*response:\s+(?P<%s>\{.*\}).*$`, captureGroupName)) matchData := re.FindSubmatch(pipeReaderOut) for index, name := range re.SubexpNames() { diff --git a/cmd/root.go b/cmd/root.go index 7eb159e0..4addbda3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -150,21 +150,9 @@ func initMainViper(cfgFile string) { loadMainViperConfig(cfgFile) } - // For each profile, if a viper key from an option doesn't exist, set it to the default value - for _, pName := range profiles.GetMainConfig().ProfileNames() { - subViper := profiles.GetMainConfig().ViperInstance().Sub(pName) - for _, opt := range options.Options() { - if opt.ViperKey == "" || opt.ViperKey == options.RootActiveProfileOption.ViperKey { - continue - } - if !subViper.IsSet(opt.ViperKey) { - subViper.Set(opt.ViperKey, opt.DefaultValue) - } - } - err := profiles.GetMainConfig().SaveProfile(pName, subViper) - if err != nil { - output.SystemError(fmt.Sprintf("Failed to save profile '%s': %v", pName, err), nil) - } + err := profiles.GetMainConfig().DefaultMissingViperKeys() + if err != nil { + output.SystemError(err.Error(), nil) } } diff --git a/go.mod b/go.mod index bc35b16f..e12a4c3a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.23.2 require ( github.com/fatih/color v1.18.0 - github.com/golangci/golangci-lint v1.61.0 + github.com/golangci/golangci-lint v1.62.0 github.com/hashicorp/go-uuid v1.0.3 github.com/manifoldco/promptui v0.9.0 github.com/patrickcping/pingone-go-sdk-v2 v0.12.3 @@ -62,7 +62,7 @@ require ( github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.5 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/ghostiam/protogetter v0.3.8 // indirect github.com/go-critic/go-critic v0.11.5 // indirect @@ -78,6 +78,7 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect + github.com/golangci/go-printf-func-name v0.1.0 // indirect github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 // indirect github.com/golangci/misspell v0.6.0 // indirect github.com/golangci/modinfo v0.3.4 // indirect @@ -96,7 +97,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jgautheron/goconst v1.7.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect github.com/jjti/go-spancheck v0.6.2 // indirect github.com/julz/importas v0.1.0 // indirect github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect @@ -106,11 +106,10 @@ require ( github.com/kulti/thelper v0.6.3 // indirect github.com/kunwardeep/paralleltest v1.0.10 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect - github.com/lasiar/canonicalheader v1.1.1 // indirect + github.com/lasiar/canonicalheader v1.1.2 // indirect github.com/ldez/gomoddirectives v0.2.4 // indirect github.com/ldez/tagliatelle v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect - github.com/lufeee/execinquery v1.2.1 // indirect github.com/macabu/inamedparam v0.1.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/maratori/testableexamples v1.0.0 // indirect @@ -119,7 +118,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mgechev/revive v1.4.0 // indirect + github.com/mgechev/revive v1.5.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect @@ -127,7 +126,7 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.17.0 // indirect + github.com/nunnatsa/ginkgolinter v0.18.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/patrickcping/pingone-go-sdk-v2/authorize v0.6.0 // indirect github.com/patrickcping/pingone-go-sdk-v2/credentials v0.9.0 // indirect @@ -144,7 +143,9 @@ require ( github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect + github.com/raeperd/recvcheck v0.1.2 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/ryancurrah/gomodguard v1.3.5 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sagikazarmark/locafero v0.6.0 // indirect @@ -177,24 +178,25 @@ require ( github.com/ultraware/funlen v0.1.0 // indirect github.com/ultraware/whitespace v0.1.1 // indirect github.com/uudashr/gocognit v1.1.3 // indirect + github.com/uudashr/iface v1.2.0 // indirect github.com/xen0n/gosmopolitan v1.2.2 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.12.2 // indirect + go-simpler.org/musttag v0.13.0 // indirect go-simpler.org/sloglint v0.7.2 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect - golang.org/x/exp/typeparams v0.0.0-20241009180824-f66d83c29e7c // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.27.0 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 52895351..0424f265 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6 github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghostiam/protogetter v0.3.8 h1:LYcXbYvybUyTIxN2Mj9h6rHrDZBDwZloPoKctWrFyJY= @@ -143,10 +143,12 @@ github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= +github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9 h1:/1322Qns6BtQxUZDTAT4SdcoxknUki7IAoK4SAXr8ME= github.com/golangci/gofmt v0.0.0-20240816233607-d8596aa466a9/go.mod h1:Oesb/0uFAyWoaw1U1qS5zyjCg5NP9C9iwjnI4tIsXEE= -github.com/golangci/golangci-lint v1.61.0 h1:VvbOLaRVWmyxCnUIMTbf1kDsaJbTzH20FAMXTAlQGu8= -github.com/golangci/golangci-lint v1.61.0/go.mod h1:e4lztIrJJgLPhWvFPDkhiMwEFRrWlmFbrZea3FsJyN8= +github.com/golangci/golangci-lint v1.62.0 h1:/G0g+bi1BhmGJqLdNQkKBWjcim8HjOPc4tsKuHDOhcI= +github.com/golangci/golangci-lint v1.62.0/go.mod h1:jtoOhQcKTz8B6dGNFyfQV3WZkQk+YvBDewDtNpiAJts= github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA= @@ -195,8 +197,6 @@ github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5 github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk= github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= @@ -221,16 +221,14 @@ github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCT github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/lasiar/canonicalheader v1.1.1 h1:wC+dY9ZfiqiPwAexUApFush/csSPXeIi4QqyxXmng8I= -github.com/lasiar/canonicalheader v1.1.1/go.mod h1:cXkb3Dlk6XXy+8MVQnF23CYKWlyA7kfQhSw2CcZtZb0= +github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= +github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= github.com/ldez/gomoddirectives v0.2.4 h1:j3YjBIjEBbqZ0NKtBNzr8rtMHTOrLPeiwTkfUJZ3alg= github.com/ldez/gomoddirectives v0.2.4/go.mod h1:oWu9i62VcQDYp9EQ0ONTfqLNh+mDLWWDO+SO0qSQw5g= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= -github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -254,8 +252,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mgechev/revive v1.4.0 h1:+6LDNE1XKsUCkpuDOMrzjOsXqiQOZ/jPlscLyA6mMXw= -github.com/mgechev/revive v1.4.0/go.mod h1:uzGR6feiCiJi4oND58/KMt/lEnR5vmjzRYPZiR0sQRQ= +github.com/mgechev/revive v1.5.0 h1:oaSmjA7rP8+HyoRuCgC531VHwnLH1AlJdjj+1AnQceQ= +github.com/mgechev/revive v1.5.0/go.mod h1:L6T3H8EoerRO86c7WuGpvohIUmiploGiyoYbtIWFmV8= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -270,8 +268,8 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.17.0 h1:9cvAxodbajOdYkszkj/qZTBgWB3/BUyV/PpPoVzwXnE= -github.com/nunnatsa/ginkgolinter v0.17.0/go.mod h1:vPrWafSULmjMGCMsfGA908if95VnHQNAahvSBOjTuWs= +github.com/nunnatsa/ginkgolinter v0.18.2 h1:b2yZTU30JabiqGnmcJtFVXLBXyAj2Dmy7ZwPUbYphyc= +github.com/nunnatsa/ginkgolinter v0.18.2/go.mod h1:Mp5o0Yc8+cBJEmcu3QAzk6QxT0HgbWO7Ofb28zrJ/Vs= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= @@ -331,11 +329,13 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/raeperd/recvcheck v0.1.2 h1:SjdquRsRXJc26eSonWIo8b7IMtKD3OAT2Lb5G3ZX1+4= +github.com/raeperd/recvcheck v0.1.2/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -426,6 +426,8 @@ github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/ github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= +github.com/uudashr/iface v1.2.0 h1:ECJjh5q/1Zmnv/2yFpWV6H3oMg5+Mo+vL0aqw9Gjazo= +github.com/uudashr/iface v1.2.0/go.mod h1:Ux/7d/rAF3owK4m53cTVXL4YoVHKNqnoOeQHn2xrlp0= github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= @@ -444,8 +446,8 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.12.2 h1:J7lRc2ysXOq7eM8rwaTYnNrHd5JwjppzB6mScysB2Cs= -go-simpler.org/musttag v0.12.2/go.mod h1:uN1DVIasMTQKk6XSik7yrJoEysGtR2GRqvWnI9S7TYM= +go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= +go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= @@ -462,12 +464,12 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20241009180824-f66d83c29e7c h1:F/15/6p7LyGUSoP0GE5CB/U9+TNEER1foNOP5sWLLnI= -golang.org/x/exp/typeparams v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f h1:WTyX8eCCyfdqiPYkRGm0MqElSfYFH3yR1+rl/mct9sA= +golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -479,8 +481,8 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -497,10 +499,10 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -510,8 +512,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -538,8 +540,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -558,11 +560,10 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= @@ -582,8 +583,8 @@ golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/commands/config/add_profile_internal.go b/internal/commands/config/add_profile_internal.go index 7d2ecb33..f964ef9d 100644 --- a/internal/commands/config/add_profile_internal.go +++ b/internal/commands/config/add_profile_internal.go @@ -42,6 +42,11 @@ func RunInternalConfigAddProfile(rc io.ReadCloser) (err error) { output.Success(fmt.Sprintf("Profile '%s' set as active.", newProfileName), nil) } + err = profiles.GetMainConfig().DefaultMissingViperKeys() + if err != nil { + return fmt.Errorf("failed to add profile: %v", err) + } + return nil } diff --git a/internal/commands/config/get_internal.go b/internal/commands/config/get_internal.go index c6412c8c..18056ca3 100644 --- a/internal/commands/config/get_internal.go +++ b/internal/commands/config/get_internal.go @@ -30,10 +30,10 @@ func RunInternalConfigGet(viperKey string) (err error) { } func readConfigGetOptions() (pName string, err error) { - if !options.ConfigGetProfileOption.Flag.Changed { + if !options.RootProfileOption.Flag.Changed { pName, err = profiles.GetOptionValue(options.RootActiveProfileOption) } else { - pName, err = profiles.GetOptionValue(options.ConfigGetProfileOption) + pName, err = profiles.GetOptionValue(options.RootProfileOption) } if err != nil { diff --git a/internal/commands/config/get_internal_test.go b/internal/commands/config/get_internal_test.go index 942ce504..ddc5ef02 100644 --- a/internal/commands/config/get_internal_test.go +++ b/internal/commands/config/get_internal_test.go @@ -36,8 +36,8 @@ func Test_RunInternalConfigGet_DifferentProfile(t *testing.T) { profileName = customtypes.String("production") ) - options.ConfigGetProfileOption.Flag.Changed = true - options.ConfigGetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName err := RunInternalConfigGet("service") if err != nil { @@ -53,8 +53,8 @@ func Test_RunInternalConfigGet_InvalidProfileName(t *testing.T) { profileName = customtypes.String("invalid") ) - options.ConfigGetProfileOption.Flag.Changed = true - options.ConfigGetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName expectedErrorPattern := `^failed to get configuration: invalid profile name: '.*' profile does not exist$` err := RunInternalConfigGet("service") diff --git a/internal/commands/config/list_profiles_internal.go b/internal/commands/config/list_profiles_internal.go index 3a768adc..164f8281 100644 --- a/internal/commands/config/list_profiles_internal.go +++ b/internal/commands/config/list_profiles_internal.go @@ -1,17 +1,23 @@ package config_internal import ( + "strings" + "github.com/fatih/color" + "github.com/pingidentity/pingcli/internal/configuration/options" "github.com/pingidentity/pingcli/internal/logger" "github.com/pingidentity/pingcli/internal/output" "github.com/pingidentity/pingcli/internal/profiles" ) -func RunInternalConfigListProfiles() { +func RunInternalConfigListProfiles() (err error) { l := logger.Get() profileNames := profiles.GetMainConfig().ProfileNames() - activeProfile := profiles.GetMainConfig().ActiveProfile().Name() + activeProfileName, err := profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil { + return err + } listStr := "Profiles:\n" @@ -20,7 +26,7 @@ func RunInternalConfigListProfiles() { activeFmt := color.New(color.Bold, color.FgGreen).SprintFunc() for _, profileName := range profileNames { - if profileName == activeProfile { + if strings.EqualFold(profileName, activeProfileName) { listStr += "- " + profileName + activeFmt(" (active)") + " \n" } else { listStr += "- " + profileName + "\n" @@ -38,4 +44,6 @@ func RunInternalConfigListProfiles() { } output.Message(listStr, nil) + + return nil } diff --git a/internal/commands/config/list_profiles_internal_test.go b/internal/commands/config/list_profiles_internal_test.go index d7b67cac..6f214b15 100644 --- a/internal/commands/config/list_profiles_internal_test.go +++ b/internal/commands/config/list_profiles_internal_test.go @@ -3,6 +3,7 @@ package config_internal import ( "testing" + "github.com/pingidentity/pingcli/internal/testing/testutils" "github.com/pingidentity/pingcli/internal/testing/testutils_viper" ) @@ -10,5 +11,6 @@ import ( func Test_RunInternalConfigListProfiles(t *testing.T) { testutils_viper.InitVipers(t) - RunInternalConfigListProfiles() + err := RunInternalConfigListProfiles() + testutils.CheckExpectedError(t, err, nil) } diff --git a/internal/commands/config/set_internal.go b/internal/commands/config/set_internal.go index f32feaa3..4c6e4a7a 100644 --- a/internal/commands/config/set_internal.go +++ b/internal/commands/config/set_internal.go @@ -27,12 +27,11 @@ func RunInternalConfigSet(kvPair string) (err error) { return fmt.Errorf("failed to set configuration: value for key '%s' is empty. Use 'pingcli config unset %s' to unset the key", vKey, vKey) } - if err = profiles.GetMainConfig().ValidateExistingProfileName(pName); err != nil { + subViper, err := profiles.GetMainConfig().GetProfileViper(pName) + if err != nil { return fmt.Errorf("failed to set configuration: %v", err) } - subViper := profiles.GetMainConfig().ViperInstance().Sub(pName) - opt, err := configuration.OptionFromViperKey(vKey) if err != nil { return fmt.Errorf("failed to set configuration: %v", err) @@ -51,8 +50,7 @@ func RunInternalConfigSet(kvPair string) (err error) { return fmt.Errorf("failed to set configuration: %v", err) } - output.Success("Configuration set successfully", nil) - output.Message(yamlStr, nil) + output.Success("Configuration set successfully", map[string]interface{}{"Profile YAML": yamlStr}) return nil } @@ -70,10 +68,10 @@ func readConfigSetOptions(kvPair string) (pName string, vKey string, vValue stri } func readConfigSetProfileName() (pName string, err error) { - if !options.ConfigSetProfileOption.Flag.Changed { + if !options.RootProfileOption.Flag.Changed { pName, err = profiles.GetOptionValue(options.RootActiveProfileOption) } else { - pName, err = profiles.GetOptionValue(options.ConfigSetProfileOption) + pName, err = profiles.GetOptionValue(options.RootProfileOption) } if err != nil { diff --git a/internal/commands/config/set_internal_test.go b/internal/commands/config/set_internal_test.go index 4b9314ff..3d6da9d6 100644 --- a/internal/commands/config/set_internal_test.go +++ b/internal/commands/config/set_internal_test.go @@ -45,8 +45,8 @@ func Test_RunInternalConfigSet_NonExistentProfileName(t *testing.T) { profileName = customtypes.String("non-existent") ) - options.ConfigSetProfileOption.Flag.Changed = true - options.ConfigSetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName expectedErrorPattern := `^failed to set configuration: invalid profile name: '.*' profile does not exist$` err := RunInternalConfigSet("noColor=true") @@ -61,8 +61,8 @@ func Test_RunInternalConfigSet_DifferentProfile(t *testing.T) { profileName = customtypes.String("production") ) - options.ConfigSetProfileOption.Flag.Changed = true - options.ConfigSetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName err := RunInternalConfigSet("noColor=true") if err != nil { @@ -78,8 +78,8 @@ func Test_RunInternalConfigSet_InvalidProfileName(t *testing.T) { profileName = customtypes.String("*&%*&") ) - options.ConfigSetProfileOption.Flag.Changed = true - options.ConfigSetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName expectedErrorPattern := `^failed to set configuration: invalid profile name: '.*'\. name must contain only alphanumeric characters, underscores, and dashes$` err := RunInternalConfigSet("noColor=true") diff --git a/internal/commands/config/unset_internal.go b/internal/commands/config/unset_internal.go index 3898ceb1..1fe4ee7d 100644 --- a/internal/commands/config/unset_internal.go +++ b/internal/commands/config/unset_internal.go @@ -19,12 +19,11 @@ func RunInternalConfigUnset(viperKey string) (err error) { return fmt.Errorf("failed to unset configuration: %v", err) } - if err = profiles.GetMainConfig().ValidateExistingProfileName(pName); err != nil { + subViper, err := profiles.GetMainConfig().GetProfileViper(pName) + if err != nil { return fmt.Errorf("failed to unset configuration: %v", err) } - subViper := profiles.GetMainConfig().ViperInstance().Sub(pName) - opt, err := configuration.OptionFromViperKey(viperKey) if err != nil { return fmt.Errorf("failed to unset configuration: %v", err) @@ -41,17 +40,16 @@ func RunInternalConfigUnset(viperKey string) (err error) { return fmt.Errorf("failed to unset configuration: %v", err) } - output.Success("Configuration unset successfully", nil) - output.Message(yamlStr, nil) + output.Success("Configuration unset successfully", map[string]interface{}{"Profile YAML": yamlStr}) return nil } func readConfigUnsetOptions() (pName string, err error) { - if !options.ConfigUnsetProfileOption.Flag.Changed { + if !options.RootProfileOption.Flag.Changed { pName, err = profiles.GetOptionValue(options.RootActiveProfileOption) } else { - pName, err = profiles.GetOptionValue(options.ConfigUnsetProfileOption) + pName, err = profiles.GetOptionValue(options.RootProfileOption) } if err != nil { diff --git a/internal/commands/config/unset_internal_test.go b/internal/commands/config/unset_internal_test.go index 8a6d60d9..2dab8f94 100644 --- a/internal/commands/config/unset_internal_test.go +++ b/internal/commands/config/unset_internal_test.go @@ -36,8 +36,8 @@ func Test_RunInternalConfigUnset_DifferentProfile(t *testing.T) { profileName = customtypes.String("production") ) - options.ConfigUnsetProfileOption.Flag.Changed = true - options.ConfigUnsetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName err := RunInternalConfigUnset("noColor") if err != nil { @@ -53,8 +53,8 @@ func Test_RunInternalConfigUnset_InvalidProfileName(t *testing.T) { profileName = customtypes.String("invalid") ) - options.ConfigUnsetProfileOption.Flag.Changed = true - options.ConfigUnsetProfileOption.CobraParamValue = &profileName + options.RootProfileOption.Flag.Changed = true + options.RootProfileOption.CobraParamValue = &profileName expectedErrorPattern := `^failed to unset configuration: invalid profile name: '.*' profile does not exist$` err := RunInternalConfigUnset("noColor") diff --git a/internal/commands/request/request_internal.go b/internal/commands/request/request_internal.go index 7156eed1..b39662c5 100644 --- a/internal/commands/request/request_internal.go +++ b/internal/commands/request/request_internal.go @@ -242,15 +242,30 @@ func pingoneAuth() (accessToken string, err error) { return "", err } - // Store access token and expiry - profileViper := profiles.GetMainConfig().ActiveProfile().ViperInstance() - profileViper.Set(options.RequestAccessTokenOption.ViperKey, pingoneAuthResponse.AccessToken) - currentTime := time.Now().Unix() tokenExpiry := currentTime + pingoneAuthResponse.ExpiresIn - profileViper.Set(options.RequestAccessTokenExpiryOption.ViperKey, tokenExpiry) - err = profiles.GetMainConfig().SaveProfile(profiles.GetMainConfig().ActiveProfile().Name(), profileViper) + // Store access token and expiry + pName, err := profiles.GetOptionValue(options.RootProfileOption) + if err != nil { + return "", err + } + + if pName == "" { + pName, err = profiles.GetOptionValue(options.RootActiveProfileOption) + if err != nil { + return "", err + } + } + + subViper, err := profiles.GetMainConfig().GetProfileViper(pName) + if err != nil { + return "", err + } + + subViper.Set(options.RequestAccessTokenOption.ViperKey, pingoneAuthResponse.AccessToken) + subViper.Set(options.RequestAccessTokenExpiryOption.ViperKey, tokenExpiry) + err = profiles.GetMainConfig().SaveProfile(pName, subViper) if err != nil { return "", err } diff --git a/internal/configuration/config/get.go b/internal/configuration/config/get.go deleted file mode 100644 index 49ede6ef..00000000 --- a/internal/configuration/config/get.go +++ /dev/null @@ -1,33 +0,0 @@ -package configuration_config - -import ( - "github.com/pingidentity/pingcli/internal/configuration/options" - "github.com/pingidentity/pingcli/internal/customtypes" - "github.com/spf13/pflag" -) - -func InitConfigGetOptions() { - initGetProfileOption() -} - -func initGetProfileOption() { - cobraParamName := "profile-name" - cobraValue := new(customtypes.String) - defaultValue := customtypes.String("") - - options.ConfigGetProfileOption = options.Option{ - CobraParamName: cobraParamName, - CobraParamValue: cobraValue, - DefaultValue: &defaultValue, - EnvVar: "", // No environment variable - Flag: &pflag.Flag{ - Name: cobraParamName, - Shorthand: "p", - Usage: "The name of the configuration profile used to get the configuration value from. " + - "(default The active profile)", - Value: cobraValue, - }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key - } -} diff --git a/internal/configuration/config/set.go b/internal/configuration/config/set.go deleted file mode 100644 index 722260c1..00000000 --- a/internal/configuration/config/set.go +++ /dev/null @@ -1,33 +0,0 @@ -package configuration_config - -import ( - "github.com/pingidentity/pingcli/internal/configuration/options" - "github.com/pingidentity/pingcli/internal/customtypes" - "github.com/spf13/pflag" -) - -func InitConfigSetOptions() { - initSetProfileOption() -} - -func initSetProfileOption() { - cobraParamName := "profile-name" - cobraValue := new(customtypes.String) - defaultValue := customtypes.String("") - - options.ConfigSetProfileOption = options.Option{ - CobraParamName: cobraParamName, - CobraParamValue: cobraValue, - DefaultValue: &defaultValue, - EnvVar: "", // No environment variable - Flag: &pflag.Flag{ - Name: cobraParamName, - Shorthand: "p", - Usage: "The name of the configuration profile used to set the configuration value to. " + - "(default The active profile)", - Value: cobraValue, - }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key - } -} diff --git a/internal/configuration/config/unset.go b/internal/configuration/config/unset.go deleted file mode 100644 index 08bcb27f..00000000 --- a/internal/configuration/config/unset.go +++ /dev/null @@ -1,33 +0,0 @@ -package configuration_config - -import ( - "github.com/pingidentity/pingcli/internal/configuration/options" - "github.com/pingidentity/pingcli/internal/customtypes" - "github.com/spf13/pflag" -) - -func InitConfigUnsetOptions() { - initUnsetProfileOption() -} - -func initUnsetProfileOption() { - cobraParamName := "profile-name" - cobraValue := new(customtypes.String) - defaultValue := customtypes.String("") - - options.ConfigUnsetProfileOption = options.Option{ - CobraParamName: cobraParamName, - CobraParamValue: cobraValue, - DefaultValue: &defaultValue, - EnvVar: "", // No environment variable - Flag: &pflag.Flag{ - Name: cobraParamName, - Shorthand: "p", - Usage: "The name of the configuration profile to unset a configuration value from. " + - "(default The active profile)", - Value: cobraValue, - }, - Type: options.ENUM_STRING, - ViperKey: "", // No viper key - } -} diff --git a/internal/configuration/configuration.go b/internal/configuration/configuration.go index acd21aa9..fd9ad30f 100644 --- a/internal/configuration/configuration.go +++ b/internal/configuration/configuration.go @@ -28,7 +28,7 @@ func ViperKeys() (keys []string) { func ValidateViperKey(viperKey string) error { validKeys := ViperKeys() for _, vKey := range validKeys { - if vKey == viperKey { + if strings.EqualFold(vKey, viperKey) { return nil } } @@ -83,9 +83,6 @@ func OptionFromViperKey(viperKey string) (opt options.Option, err error) { func InitAllOptions() { configuration_config.InitConfigAddProfileOptions() configuration_config.InitConfigDeleteProfileOptions() - configuration_config.InitConfigSetOptions() - configuration_config.InitConfigGetOptions() - configuration_config.InitConfigUnsetOptions() configuration_platform.InitPlatformExportOptions() diff --git a/internal/configuration/options/options.go b/internal/configuration/options/options.go index b19e10f5..0cc98e6d 100644 --- a/internal/configuration/options/options.go +++ b/internal/configuration/options/options.go @@ -71,9 +71,6 @@ func Options() []Option { ConfigAddProfileNameOption, ConfigAddProfileSetActiveOption, ConfigDeleteAutoAcceptOption, - ConfigGetProfileOption, - ConfigSetProfileOption, - ConfigUnsetProfileOption, RequestDataOption, RequestHTTPMethodOption, @@ -116,12 +113,6 @@ var ( ConfigAddProfileSetActiveOption Option ConfigDeleteAutoAcceptOption Option - - ConfigGetProfileOption Option - - ConfigSetProfileOption Option - - ConfigUnsetProfileOption Option ) // 'pingcli platform export' command options diff --git a/internal/connector/pingone/platform/resources/pingone_notification_template_content_test.go b/internal/connector/pingone/platform/resources/pingone_notification_template_content_test.go index f14960d1..16b3befb 100644 --- a/internal/connector/pingone/platform/resources/pingone_notification_template_content_test.go +++ b/internal/connector/pingone/platform/resources/pingone_notification_template_content_test.go @@ -10,6 +10,9 @@ import ( ) func TestNotificationTemplateContentExport(t *testing.T) { + // TODO: Remove the skipNow following completion of https://github.com/pingidentity/pingcli/issues/29 + t.SkipNow() + // Get initialized apiClient and resource PingOneClientInfo := testutils.GetPingOneClientInfo(t) resource := resources.NotificationTemplateContent(PingOneClientInfo) diff --git a/internal/output/output.go b/internal/output/output.go index d4fa46d3..78b54f57 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -89,9 +89,7 @@ Please raise an issue at https://github.com/pingidentity/pingcli`, print(systemMsg, fields, boldRed, l.Fatal) } -func print(message string, - fields map[string]interface{}, - colorFunc func(format string, a ...interface{}) string, +func print(message string, fields map[string]interface{}, colorFunc func(format string, a ...interface{}) string, logEventFunc func() *zerolog.Event) { SetColorize() @@ -113,24 +111,19 @@ func print(message string, } -func printText(message string, - fields map[string]interface{}, - colorFunc func(format string, a ...interface{}) string, +func printText(message string, fields map[string]interface{}, colorFunc func(format string, a ...interface{}) string, logEventFunc func() *zerolog.Event) { l := logger.Get() - if fields != nil { - fmt.Println(cyan("Additional Information:")) - for k, v := range fields { - switch typedValue := v.(type) { - // If the value is a json.RawMessage, print it as a string - case json.RawMessage: - fmt.Println(cyan("%s: %s", k, typedValue)) - l.Info().Msg(cyan("%s: %s", k, typedValue)) - default: - fmt.Println(cyan("%s: %v", k, v)) - l.Info().Msg(cyan("%s: %v", k, v)) - } + for k, v := range fields { + switch typedValue := v.(type) { + // If the value is a json.RawMessage, print it as a string + case json.RawMessage: + fmt.Println(cyan("%s: \n%s", k, typedValue)) + l.Info().Msg(cyan("%s: %s", k, typedValue)) + default: + fmt.Println(cyan("%s: \n%v", k, v)) + l.Info().Msg(cyan("%s: %v", k, v)) } } @@ -138,11 +131,15 @@ func printText(message string, logEventFunc().Msg(colorFunc(message)) } -func printJson(message string, - fields map[string]interface{}, - logEventFunc func() *zerolog.Event) { +func printJson(message string, fields map[string]interface{}, logEventFunc func() *zerolog.Event) { l := logger.Get() + if fields == nil { + fields = map[string]interface{}{ + "message": message, + } + } + if fields["message"] == nil { fields["message"] = message } diff --git a/internal/profiles/validate.go b/internal/profiles/validate.go index 4d56bab7..43574190 100644 --- a/internal/profiles/validate.go +++ b/internal/profiles/validate.go @@ -11,24 +11,31 @@ import ( "github.com/spf13/viper" ) -func Validate() error { +func Validate() (err error) { // Get a slice of all profile names configured in the config.yaml file profileNames := GetMainConfig().ProfileNames() // Validate profile names - if err := validateProfileNames(profileNames); err != nil { + if err = validateProfileNames(profileNames); err != nil { return err } // Make sure selected active profile is in the configuration file - activeProfile := GetMainConfig().ActiveProfile().Name() - if !slices.Contains(profileNames, activeProfile) { - return fmt.Errorf("failed to validate Ping CLI configuration: active profile '%s' not found in configuration file %s", activeProfile, GetMainConfig().ViperInstance().ConfigFileUsed()) + activeProfileName, err := GetOptionValue(options.RootActiveProfileOption) + if err != nil { + return fmt.Errorf("failed to validate Ping CLI configuration: %v", err) + } + if !slices.Contains(profileNames, activeProfileName) { + return fmt.Errorf("failed to validate Ping CLI configuration: active profile '%s' not found in configuration "+ + "file %s", activeProfileName, GetMainConfig().ViperInstance().ConfigFileUsed()) } - // for each profile key, set the profile based on mainViper.Sub() and validate the profile + // for each profile key, validate the profile viper for _, pName := range profileNames { - subViper := GetMainConfig().ViperInstance().Sub(pName) + subViper, err := GetMainConfig().GetProfileViper(pName) + if err != nil { + return fmt.Errorf("failed to validate Ping CLI configuration: %v", err) + } if err := validateProfileKeys(pName, subViper); err != nil { return fmt.Errorf("failed to validate Ping CLI configuration: %v", err) diff --git a/internal/profiles/viper.go b/internal/profiles/viper.go index f653e91e..6a5dba11 100644 --- a/internal/profiles/viper.go +++ b/internal/profiles/viper.go @@ -22,14 +22,8 @@ import ( "gopkg.in/yaml.v3" ) -type ActiveProfile struct { - name string - viperInstance *viper.Viper -} - type MainConfig struct { viperInstance *viper.Viper - activeProfile *ActiveProfile } var ( @@ -40,7 +34,6 @@ var ( func NewMainConfig() (newMainViper *MainConfig) { newMainViper = &MainConfig{ viperInstance: viper.New(), - activeProfile: nil, } return newMainViper @@ -55,10 +48,6 @@ func (m MainConfig) ViperInstance() *viper.Viper { return m.viperInstance } -func (m MainConfig) ActiveProfile() *ActiveProfile { - return m.activeProfile -} - func (m *MainConfig) ChangeActiveProfile(pName string) (err error) { if err = m.ValidateExistingProfileName(pName); err != nil { return err @@ -80,11 +69,6 @@ func (m *MainConfig) ChangeActiveProfile(pName string) (err error) { return err } - m.activeProfile = &ActiveProfile{ - name: pName, - viperInstance: m.ViperInstance().Sub(pName), - } - return nil } @@ -103,7 +87,10 @@ func (m MainConfig) ChangeProfileName(oldPName, newPName string) (err error) { return err } - subViper := m.ViperInstance().Sub(oldPName) + subViper, err := m.GetProfileViper(oldPName) + if err != nil { + return err + } if err = m.DeleteProfile(oldPName); err != nil { return err @@ -121,7 +108,11 @@ func (m MainConfig) ChangeProfileDescription(pName, description string) (err err return err } - subViper := m.ViperInstance().Sub(pName) + subViper, err := m.GetProfileViper(pName) + if err != nil { + return err + } + subViper.Set(options.ProfileDescriptionOption.ViperKey, description) if err = m.SaveProfile(pName, subViper); err != nil { @@ -131,6 +122,19 @@ func (m MainConfig) ChangeProfileDescription(pName, description string) (err err return nil } +func (m MainConfig) GetProfileViper(pName string) (subViper *viper.Viper, err error) { + if err = m.ValidateExistingProfileName(pName); err != nil { + return nil, err + } + + subViper = m.ViperInstance().Sub(pName) + if subViper == nil { + return nil, fmt.Errorf("failed to get profile viper: profile '%s' does not exist", pName) + } + + return subViper, nil +} + // Viper gives no built-in delete or unset method for keys // Using this "workaround" described here: https://github.com/spf13/viper/issues/632 func (m MainConfig) DeleteProfile(pName string) (err error) { @@ -138,7 +142,12 @@ func (m MainConfig) DeleteProfile(pName string) (err error) { return err } - if pName == m.ActiveProfile().Name() { + activeProfileName, err := GetOptionValue(options.RootActiveProfileOption) + if err != nil { + return err + } + + if strings.EqualFold(activeProfileName, pName) { return fmt.Errorf("'%s' is the active profile and cannot be deleted", pName) } @@ -278,7 +287,10 @@ func (m MainConfig) ProfileToString(pName string) (yamlStr string, err error) { return "", err } - subViper := m.ViperInstance().Sub(pName) + subViper, err := m.GetProfileViper(pName) + if err != nil { + return "", err + } yaml, err := yaml.Marshal(subViper.AllSettings()) if err != nil { @@ -293,7 +305,10 @@ func (m MainConfig) ProfileViperValue(pName, viperKey string) (yamlStr string, e return "", err } - subViper := m.ViperInstance().Sub(pName) + subViper, err := m.GetProfileViper(pName) + if err != nil { + return "", err + } if !subViper.IsSet(viperKey) { return "", fmt.Errorf("configuration key '%s' is not set in profile '%s'", viperKey, pName) @@ -307,83 +322,123 @@ func (m MainConfig) ProfileViperValue(pName, viperKey string) (yamlStr string, e return string(yaml), nil } -func (a ActiveProfile) ViperInstance() *viper.Viper { - return a.viperInstance -} +func (m MainConfig) DefaultMissingViperKeys() (err error) { + // For each profile, if a viper key from an option doesn't exist, set it to the default value + for _, pName := range m.ProfileNames() { + subViper, err := m.GetProfileViper(pName) + if err != nil { + return err + } -func (a ActiveProfile) Name() string { - return a.name + for _, opt := range options.Options() { + if opt.ViperKey == "" || opt.ViperKey == options.RootActiveProfileOption.ViperKey { + continue + } + if !subViper.IsSet(opt.ViperKey) { + subViper.Set(opt.ViperKey, opt.DefaultValue) + } + } + err = m.SaveProfile(pName, subViper) + if err != nil { + return fmt.Errorf("Failed to save profile '%s': %v", pName, err) + } + } + + return nil } func GetOptionValue(opt options.Option) (pFlagValue string, err error) { - if opt.CobraParamValue != nil && opt.Flag.Changed { - pFlagValue = opt.CobraParamValue.String() - return pFlagValue, nil + // 1st priority: cobra param flag value + cobraParamValue, ok := cobraParamValueFromOption(opt) + if ok { + return cobraParamValue, nil } + // 2nd priority: environment variable value pFlagValue = os.Getenv(opt.EnvVar) if pFlagValue != "" { return pFlagValue, nil } - mainConfig := GetMainConfig() - if opt.ViperKey != "" && mainConfig != nil { - var vValue any + // 3rd priority: viper value + viperValue, ok, err := viperValueFromOption(opt) + if err != nil { + return "", err + } + if ok { + return viperValue, nil + } - mainViperInstance := mainConfig.ViperInstance() - // This recursive call is safe, as options.RootProfileOption.ViperKey is not set - definedProfileName, err := GetOptionValue(options.RootProfileOption) - if err != nil { - return "", err - } + // 4th priority: default value + if opt.DefaultValue != nil { + pFlagValue = opt.DefaultValue.String() + return pFlagValue, nil + } - // 3 Cases: - // - 1) Viper Key is the ActiveProfile Key, get value from main viper instance - // - 2) --profile flag has been set, get value from set profile viper instance - // - 3) no --profile flag set, get value from active profile viper instance defined in main viper instance + // This is a error, as it means the option is not configured internally to contain one of the 4 values above. + // This should never happen, as all options should at least have a default value. + return "", fmt.Errorf("failed to get option value: no value found: %v", opt) +} +func cobraParamValueFromOption(opt options.Option) (value string, ok bool) { + if opt.CobraParamValue != nil && opt.Flag.Changed { + return opt.CobraParamValue.String(), true + } + + return "", false +} + +func viperValueFromOption(opt options.Option) (value string, ok bool, err error) { + mainConfig := GetMainConfig() + if opt.ViperKey != "" && mainConfig != nil { + var ( + vValue any + mainViperInstance = mainConfig.ViperInstance() + ) + + // Case 1: Viper Key is the ActiveProfile Key, get value from main viper instance if opt.ViperKey == options.RootActiveProfileOption.ViperKey && mainViperInstance != nil { - // Case 1 vValue = mainViperInstance.Get(opt.ViperKey) - } else if definedProfileName != "" { - // Case 2 - profileViperInstance := mainViperInstance.Sub(definedProfileName) - if profileViperInstance != nil { - vValue = profileViperInstance.Get(opt.ViperKey) - } } else { - // Case 3 - activeProfile := mainConfig.ActiveProfile() - if activeProfile != nil { - profileViperInstance := activeProfile.ViperInstance() - if profileViperInstance != nil { - vValue = profileViperInstance.Get(opt.ViperKey) + // Case 2: --profile flag has been set, get value from set profile viper instance + // Case 3: no --profile flag set, get value from active profile viper instance defined in main viper instance + // This recursive call is safe, as options.RootProfileOption.ViperKey is not set + pName, err := GetOptionValue(options.RootProfileOption) + if err != nil { + return "", false, err + } + if pName == "" { + pName, err = GetOptionValue(options.RootActiveProfileOption) + if err != nil { + return "", false, err } } + + subViper, err := mainConfig.GetProfileViper(pName) + if err != nil { + return "", false, err + } + + vValue = subViper.Get(opt.ViperKey) } switch typedValue := vValue.(type) { case nil: - // Do nothing + return "", false, nil case string: - return typedValue, nil + return typedValue, true, nil case []string: - return strings.Join(typedValue, ","), nil + return strings.Join(typedValue, ","), true, nil case []any: strSlice := []string{} for _, v := range typedValue { strSlice = append(strSlice, fmt.Sprintf("%v", v)) } - return strings.Join(strSlice, ","), nil + return strings.Join(strSlice, ","), true, nil default: - return fmt.Sprintf("%v", typedValue), nil + return fmt.Sprintf("%v", typedValue), true, nil } } - if opt.DefaultValue != nil { - pFlagValue = opt.DefaultValue.String() - return pFlagValue, nil - } - - return pFlagValue, fmt.Errorf("failed to get option value: no value found: %v", opt) + return "", false, nil }