From 78f7f0c8a463608c3ad7209e77fd7776977eb0e8 Mon Sep 17 00:00:00 2001 From: Jesse S Date: Tue, 6 Feb 2024 13:44:42 -0800 Subject: [PATCH] Tools 2752 conf support (#34) * feat: TOOLS-2752 support astools.conf and astools.yaml --- .github/workflows/mac-artifact.yml | 2 +- cmd/generate.go | 13 +- cmd/root.go | 38 +++--- cmd/root_test.go | 186 ++++++++++++++++++++++++----- go.mod | 22 +++- go.sum | 63 +++++++--- 6 files changed, 252 insertions(+), 72 deletions(-) diff --git a/.github/workflows/mac-artifact.yml b/.github/workflows/mac-artifact.yml index 8a7241e..a3151d0 100644 --- a/.github/workflows/mac-artifact.yml +++ b/.github/workflows/mac-artifact.yml @@ -81,7 +81,7 @@ jobs: working-directory: ${{ steps.working-dir.outputs.value }} run: | sudo make install - asconfig --version 2>&1 | grep "asconfig" + asconfig --version 2>&1 | grep "Aerospike Config" - uses: actions/upload-artifact@v3 with: name: ${{ steps.system-info.outputs.platform }}-${{ runner.arch }}-${{ runner.os }}-${{ steps.system-info.outputs.release }}-asconfig diff --git a/cmd/generate.go b/cmd/generate.go index 3303f3e..58b3afd 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -8,7 +8,7 @@ import ( "github.com/aerospike/aerospike-management-lib/asconfig" "github.com/aerospike/aerospike-management-lib/info" "github.com/aerospike/asconfig/conf" - "github.com/aerospike/tools-common-go/client" + "github.com/aerospike/tools-common-go/config" "github.com/aerospike/tools-common-go/flags" "github.com/spf13/cobra" ) @@ -50,9 +50,7 @@ func newGenerateCmd() *cobra.Command { logger.Debugf("Generating config from Aerospike node") - asCommonConfig := client.NewDefaultAerospikeHostConfig() - - flags.SetAerospikeConf(asCommonConfig, asCommonFlags) + asCommonConfig := aerospikeFlags.NewAerospikeConfig() asPolicy, err := asCommonConfig.NewClientPolicy() if err != nil { @@ -143,9 +141,10 @@ func newGenerateCmd() *cobra.Command { } res.Version = VERSION - res.Flags().AddFlagSet( - flags.SetAerospikeFlags(asCommonFlags, flags.DefaultWrapHelpString), - ) + asFlagSet := aerospikeFlags.NewFlagSet(flags.DefaultWrapHelpString) + res.Flags().AddFlagSet(asFlagSet) + config.BindPFlags(asFlagSet, "cluster") + res.Flags().StringP("output", "o", os.Stdout.Name(), flags.DefaultWrapHelpString("File path to write output to")) res.Flags().StringP("format", "F", "conf", flags.DefaultWrapHelpString("The format of the destination file(s). Valid options are: yaml, yml, and conf.")) diff --git a/cmd/root.go b/cmd/root.go index 64d5d01..9bcb62e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,6 +7,8 @@ import ( "strings" "github.com/aerospike/asconfig/log" + "github.com/aerospike/tools-common-go/config" + "github.com/aerospike/tools-common-go/flags" "github.com/aerospike/asconfig/schema" @@ -17,27 +19,34 @@ import ( "github.com/spf13/cobra" ) -// Replaced at compile time -var ( - VERSION = "development" -) - // rootCmd represents the base command when called without any subcommands var rootCmd = newRootCmd() var ( + VERSION = "development" // Replaced at compile time errInvalidLogLevel = fmt.Errorf("Invalid log-level flag") + aerospikeFlags = flags.NewDefaultAerospikeFlags() + cfFileFlags = flags.NewConfFileFlags() ) // newRootCmd is the root command constructor. It is useful for producing copies of rootCmd for testing. func newRootCmd() *cobra.Command { - res := &cobra.Command{ + rootCmd := &cobra.Command{ Use: "asconfig", Short: "Manage Aerospike configuration", Long: "Asconfig is used to manage Aerospike configuration.", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { var multiErr error + cfgFile, err := config.InitConfig(cfFileFlags.File, cfFileFlags.Instance, cmd.Flags()) + if err != nil { + multiErr = errors.Join(multiErr, err) + } + + if cfgFile != "" { + logger.Infof("Using config file: %s", cfgFile) + } + lvl, err := cmd.Flags().GetString("log-level") if err != nil { multiErr = fmt.Errorf("%w, %w", multiErr, err) @@ -54,24 +63,23 @@ func newRootCmd() *cobra.Command { }, } - res.Version = VERSION - res.SetVersionTemplate("asconfig\n{{printf \"Version %s\" .Version}}\n") + rootCmd.Version = VERSION logLevelUsage := fmt.Sprintf("Set the logging detail level. Valid levels are: %v", log.GetLogLevels()) - res.PersistentFlags().StringP("log-level", "l", "info", logLevelUsage) - res.PersistentFlags().BoolP("version", "V", false, "Version for asconfig.") - res.PersistentFlags().BoolP("help", "u", false, "Display help information") + rootCmd.PersistentFlags().StringP("log-level", "l", "info", logLevelUsage) + rootCmd.PersistentFlags().AddFlagSet(cfFileFlags.NewFlagSet(flags.DefaultWrapHelpString)) + flags.SetupRoot(rootCmd, "Aerospike Config") - res.SilenceErrors = true - res.SilenceUsage = true + rootCmd.SilenceErrors = true + rootCmd.SilenceUsage = true - res.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { + rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { logger.Error(err) cmd.Println(cmd.UsageString()) return errors.Join(err, ErrSilent) }) - return res + return rootCmd } // Execute adds all child commands to the root command and sets flags appropriately. diff --git a/cmd/root_test.go b/cmd/root_test.go index 2e2cfd8..7982ab0 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -2,45 +2,169 @@ package cmd import ( "errors" + "os" "testing" + + "github.com/aerospike/tools-common-go/config" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/stretchr/testify/suite" ) -type preTestRoot struct { - flags []string - arguments []string - expectedErrors []error +func TestPersistentPreRunRootFlags(t *testing.T) { + var testCases = []struct { + flags []string + arguments []string + expectedErrors []error + }{ + { + flags: []string{"-l", "info"}, + arguments: []string{}, + expectedErrors: []error{nil}, + }, + { + flags: []string{"-l", "panic"}, + arguments: []string{}, + expectedErrors: []error{nil}, + }, + { + flags: []string{"--log-level", "bad_level"}, + arguments: []string{}, + expectedErrors: []error{ + errInvalidLogLevel, + }, + }, + } + cmd := newRootCmd() + + for _, tc := range testCases { + t.Run(tc.flags[0], func(t *testing.T) { + cmd.ParseFlags(tc.flags) + err := cmd.PersistentPreRunE(cmd, tc.arguments) + for _, expectedErr := range tc.expectedErrors { + if !errors.Is(err, expectedErr) { + t.Errorf("%v\n actual err: %v\n is not expected err: %v", tc.flags, err, expectedErr) + } + } + }) + } } -var preTestsRoot = []preTestRoot{ - { - flags: []string{"-l", "info"}, - arguments: []string{}, - expectedErrors: []error{nil}, - }, - { - flags: []string{"-l", "panic"}, - arguments: []string{}, - expectedErrors: []error{nil}, - }, - { - flags: []string{"--log-level", "bad_level"}, - arguments: []string{}, - expectedErrors: []error{ - errInvalidLogLevel, - }, - }, +const tomlConfigTxt = ` +[group1] +str1 = "localhost:3000" +int1 = 3000 +bool1 = true + +[group2] +str2 = "localhost:4000" +int2 = 4000 +bool2 = false +` + +const yamlConfigTxt = ` +group1: + str1: "localhost:3000" + int1: 3000 + bool1: true + +group2: + str2: "localhost:4000" + int2: 4000 + bool2: false +` + +type RootTest struct { + suite.Suite } -func TestPersistentPreRunRoot(t *testing.T) { - cmd := newRootCmd() +func (suite *RootTest) TestPersistentPreRunRootInitConfig() { + testCases := []struct { + configFile string + configFileTxt string + }{ + { + configFile: "test.conf", + configFileTxt: tomlConfigTxt, + }, + { + configFile: "test.yaml", + configFileTxt: yamlConfigTxt, + }, + } - for _, test := range preTestsRoot { - cmd.ParseFlags(test.flags) - err := cmd.PersistentPreRunE(cmd, test.arguments) - for _, expectedErr := range test.expectedErrors { - if !errors.Is(err, expectedErr) { - t.Errorf("%v\n actual err: %v\n is not expected err: %v", test.flags, err, expectedErr) - } + createCmd := func() (*cobra.Command, *pflag.FlagSet, *pflag.FlagSet) { + rootCmd := newRootCmd() + subCmd := &cobra.Command{ + Use: "sub", + Run: func(cmd *cobra.Command, args []string) {}, } + flagSet1 := &pflag.FlagSet{} + flagSet2 := &pflag.FlagSet{} + + rootCmd.AddCommand(subCmd) + flagSet1.String("str1", "str1", "string flag") + flagSet1.Int("int1", 0, "int flag") + flagSet1.Bool("bool1", false, "bool flag") + flagSet2.String("str2", "str2", "string flag") + flagSet2.Int("int2", 0, "int flag") + flagSet2.Bool("bool2", false, "bool flag") + config.BindPFlags(flagSet1, "group1") + config.BindPFlags(flagSet2, "group2") + subCmd.PersistentFlags().AddFlagSet(flagSet1) + subCmd.PersistentFlags().AddFlagSet(flagSet2) + + return rootCmd, flagSet1, flagSet2 } + + for _, tc := range testCases { + suite.T().Run(tc.configFile, func(t *testing.T) { + config.Reset() + + rootCmd, flagSet1, flagSet2 := createCmd() + + err := os.WriteFile(tc.configFile, []byte(tc.configFileTxt), 0600) + if err != nil { + t.Fatalf("unable to write %s: %v", tc.configFile, err) + } + + defer os.Remove(tc.configFile) + + rootCmd.SetArgs([]string{"sub", "--config-file", tc.configFile}) + err = rootCmd.Execute() + + if err != nil { + suite.FailNow("unexpected error", err) + } + + str1, err := flagSet1.GetString("str1") + suite.NoError(err) + suite.Equal("localhost:3000", str1) + + int1, err := flagSet1.GetInt("int1") + suite.NoError(err) + suite.Equal(3000, int1) + + bool1, err := flagSet1.GetBool("bool1") + suite.NoError(err) + suite.Equal(true, bool1) + + str2, err := flagSet2.GetString("str2") + suite.NoError(err) + suite.Equal("localhost:4000", str2) + + int2, err := flagSet2.GetInt("int2") + suite.NoError(err) + suite.Equal(4000, int2) + + bool2, err := flagSet2.GetBool("bool2") + suite.NoError(err) + suite.Equal(false, bool2) + + }) + } +} + +func TestRunTestSuite(t *testing.T) { + suite.Run(t, new(RootTest)) } diff --git a/go.mod b/go.mod index 28da503..cf06c23 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/aerospike/aerospike-client-go/v6 v6.14.1 github.com/aerospike/aerospike-management-lib v1.2.1-0.20240131023930-e7454a7e0866 - github.com/aerospike/tools-common-go v0.0.0-20240126183151-d9f720a5507f + github.com/aerospike/tools-common-go v0.0.0-20240202003831-d9386330f03a github.com/bombsimon/logrusr/v4 v4.1.0 github.com/docker/docker v24.0.7+incompatible github.com/go-logr/logr v1.4.1 @@ -13,28 +13,45 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 + github.com/stretchr/testify v1.8.4 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/sync v0.6.0 // indirect @@ -44,4 +61,5 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect google.golang.org/grpc v1.60.1 // indirect google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index feb8043..019b045 100644 --- a/go.sum +++ b/go.sum @@ -6,15 +6,15 @@ github.com/aerospike/aerospike-client-go/v6 v6.14.1 h1:1DB9rgbPcCSjR7QS+2CL4MM4a github.com/aerospike/aerospike-client-go/v6 v6.14.1/go.mod h1:/0Wm81GhMqem+9flWcpazPKoRfjFeG6WrQdXGiMNi0A= github.com/aerospike/aerospike-management-lib v1.2.1-0.20240131023930-e7454a7e0866 h1:h7rAmIJG/z+pq5hQ2Zi0xHbgG3pNdea/hSH4l5ay9FE= github.com/aerospike/aerospike-management-lib v1.2.1-0.20240131023930-e7454a7e0866/go.mod h1:NwegUX6or8xmwVMIueBmGTW7lfKlZ9XDQoCuhnQKMCA= -github.com/aerospike/tools-common-go v0.0.0-20240126183151-d9f720a5507f h1:GzMQfBG2KyZ8reYhrYqPnGDMWbxiuaQjnzrs7Y9gRQY= -github.com/aerospike/tools-common-go v0.0.0-20240126183151-d9f720a5507f/go.mod h1:JaDR4z9G/GsYx7N33UBmKY0Bm0QlKpCzX23Kub1FOVo= +github.com/aerospike/tools-common-go v0.0.0-20240202003831-d9386330f03a h1:kM92Cw+B0o4al4fKUwz5DpV1MHSq7JlcLtbHinuiODE= +github.com/aerospike/tools-common-go v0.0.0-20240202003831-d9386330f03a/go.mod h1:vUWN5pPNk1P9fGmW0bvmLCdIV6CqEA8iCyhxb8t3MTE= github.com/bombsimon/logrusr/v4 v4.1.0 h1:uZNPbwusB0eUXlO8hIUwStE6Lr5bLN6IgYgG+75kuh4= github.com/bombsimon/logrusr/v4 v4.1.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhOR03TRc6im0l8= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= @@ -27,6 +27,9 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +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/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -38,17 +41,18 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= @@ -57,26 +61,47 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 h1:wSmWgpuccqS2IOfmYrbRiUgv+g37W5suLLLxwwniTSc= github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494/go.mod h1:yipyliwI08eQ6XwDm1fEwKPdF/xdbkiHtrU+1Hg+vc4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= 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= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -88,10 +113,16 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= 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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= @@ -138,9 +169,9 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=