From 0bed25dddd80c542b5a94b10a128fa3200bbd07a Mon Sep 17 00:00:00 2001 From: peusebiu Date: Mon, 15 Jan 2024 13:10:56 +0200 Subject: [PATCH] feat(config): handle config files with no explicit extension (#2147) Signed-off-by: Petu Eusebiu --- pkg/cli/server/root.go | 42 +++++++++++++++++++++++++++++++++---- pkg/cli/server/root_test.go | 40 +++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/pkg/cli/server/root.go b/pkg/cli/server/root.go index 2a4e8d42..4060d58d 100644 --- a/pkg/cli/server/root.go +++ b/pkg/cli/server/root.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path" + "path/filepath" "regexp" "strconv" "strings" @@ -23,6 +24,7 @@ import ( "zotregistry.io/zot/pkg/api" "zotregistry.io/zot/pkg/api/config" "zotregistry.io/zot/pkg/api/constants" + "zotregistry.io/zot/pkg/common" extconf "zotregistry.io/zot/pkg/extensions/config" "zotregistry.io/zot/pkg/extensions/monitoring" zlog "zotregistry.io/zot/pkg/log" @@ -738,12 +740,44 @@ func LoadConfiguration(config *config.Config, configPath string) error { // we need another key delimiter. viperInstance := viper.NewWithOptions(viper.KeyDelimiter("::")) - viperInstance.SetConfigFile(configPath) + ext := filepath.Ext(configPath) + ext = strings.Replace(ext, ".", "", 1) - if err := viperInstance.ReadInConfig(); err != nil { - log.Error().Err(err).Msg("failed to read configuration") + /* if file extension is not supported, try everything + it's also possible that the filename is starting with a dot eg: ".config". */ + if !common.Contains(viper.SupportedExts, ext) { + ext = "" + } - return err + switch ext { + case "": + log.Info().Str("path", configPath).Msg("config file with no extension, trying all supported config types") + + var err error + + for _, configType := range viper.SupportedExts { + viperInstance.SetConfigType(configType) + viperInstance.SetConfigFile(configPath) + + err = viperInstance.ReadInConfig() + if err == nil { + break + } + } + + if err != nil { + log.Error().Err(err).Str("path", configPath).Msg("failed to read configuration, tried all supported config types") + + return err + } + default: + viperInstance.SetConfigFile(configPath) + + if err := viperInstance.ReadInConfig(); err != nil { + log.Error().Err(err).Str("path", configPath).Msg("failed to read configuration") + + return err + } } metaData := &mapstructure.Metadata{} diff --git a/pkg/cli/server/root_test.go b/pkg/cli/server/root_test.go index 98072c17..720b2c4b 100644 --- a/pkg/cli/server/root_test.go +++ b/pkg/cli/server/root_test.go @@ -121,6 +121,46 @@ func TestVerify(t *testing.T) { So(err, ShouldNotBeNil) }) + Convey("Test verify config with no extension", t, func(c C) { + tmpfile, err := os.CreateTemp("", "zot-test*") + So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion":"1.1.0-dev","storage":{"rootDirectory":"/tmp/zot"}, + "http":{"address":"127.0.0.1","port":"8080","realm":"zot"}, + "log":{"level":"debug"}}`) + _, err = tmpfile.Write(content) + So(err, ShouldBeNil) + err = tmpfile.Close() + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }) + + Convey("Test verify config with dotted config name", t, func(c C) { + tmpfile, err := os.CreateTemp("", ".zot-test*") + So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(` +distspecversion: 1.1.0-dev +http: + address: 127.0.0.1 + port: 8080 + realm: zot +log: + level: debug +storage: + rootdirectory: /tmp/zot +`) + _, err = tmpfile.Write(content) + So(err, ShouldBeNil) + err = tmpfile.Close() + So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + err = cli.NewServerRootCmd().Execute() + So(err, ShouldBeNil) + }) + Convey("Test verify CVE warn for remote storage", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil)