diff --git a/internal/config/application.go b/internal/config/application.go index 0cee7c2b3d1..0c9ae0a27e9 100644 --- a/internal/config/application.go +++ b/internal/config/application.go @@ -270,13 +270,12 @@ func loadConfig(v *viper.Viper, configPath string) error { } } - // 4. look for ./config.yaml in xdg locations (starting with xdg home config dir, then moving upwards) - + // 4. look for /config.yaml in xdg locations (starting with xdg home config dir, then moving upwards) v.SetConfigName("config") - configPath = path.Join(xdg.ConfigHome, "."+internal.ApplicationName) + configPath = path.Join(xdg.ConfigHome, internal.ApplicationName) v.AddConfigPath(configPath) for _, dir := range xdg.ConfigDirs { - v.AddConfigPath(path.Join(dir, "."+internal.ApplicationName)) + v.AddConfigPath(path.Join(dir, internal.ApplicationName)) } if err = v.ReadInConfig(); err == nil { v.Set("config", v.ConfigFileUsed()) diff --git a/internal/config/application_test.go b/internal/config/application_test.go index a5108a5081c..eac0280dea6 100644 --- a/internal/config/application_test.go +++ b/internal/config/application_test.go @@ -1,17 +1,35 @@ package config import ( + "fmt" "os" "path" "testing" "github.com/adrg/xdg" + "github.com/mitchellh/go-homedir" "github.com/spf13/viper" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TODO: set negative case when config.yaml is no longer a valid option func TestApplicationConfig(t *testing.T) { + // disable homedir package cache for testing + originalCacheOpt := homedir.DisableCache + homedir.DisableCache = true + t.Cleanup(func() { + homedir.DisableCache = originalCacheOpt + }) + + // ensure we have no side effects for xdg package for future tests + originalXDG := os.Getenv("XDG_CONFIG_HOME") + t.Cleanup(func() { + // note: we're not using t.Setenv since the effect we're trying to eliminate is within the xdg package + require.NoError(t, os.Setenv("XDG_CONFIG_HOME", originalXDG)) + xdg.Reload() + }) + // config is picked up at desired configuration paths // VALID: .syft.yaml, .syft/config.yaml, ~/.syft.yaml, /syft/config.yaml // DEPRECATED: config.yaml is currently supported by @@ -19,7 +37,7 @@ func TestApplicationConfig(t *testing.T) { name string setup func(t *testing.T) string assertions func(t *testing.T, app *Application) - Cleanup func(t *testing.T) + cleanup func() }{ { name: "explicit config", @@ -29,92 +47,82 @@ func TestApplicationConfig(t *testing.T) { assertions: func(t *testing.T, app *Application) { assert.Equal(t, "test-explicit-config", app.File) }, - Cleanup: func(t *testing.T) {}, }, { name: "current working directory named config", setup: func(t *testing.T) string { err := os.Chdir("./test-fixtures/config-wd-file") // change application cwd to test-fixtures - if err != nil { - t.Fatalf("%s failed to change cwd: %+v", t.Name(), err) - } + require.NoError(t, err) return "" }, assertions: func(t *testing.T, app *Application) { assert.Equal(t, "test-wd-named-config", app.File) }, - Cleanup: func(t *testing.T) {}, }, { name: "current working directory syft dir config", setup: func(t *testing.T) string { err := os.Chdir("./test-fixtures/config-dir-test") // change application cwd to test-fixtures - if err != nil { - t.Fatalf("%s failed to change cwd: %+v", t.Name(), err) - } + require.NoError(t, err) return "" }, assertions: func(t *testing.T, app *Application) { assert.Equal(t, "test-dir-config", app.File) }, - Cleanup: func(t *testing.T) {}, }, { name: "home directory file config", setup: func(t *testing.T) string { // Because Setenv affects the whole process, it cannot be used in parallel tests or // tests with parallel ancestors: see separate XDG test for consequence of this - t.Setenv("HOME", "./test-fixtures/config-home-test") - err := os.Link("./test-fixtures/config-home-test/config-file/.syft.yaml", "./test-fixtures/config-home-test/.syft.yaml") - if err != nil { - t.Fatalf("%s failed to link home config: %+v", t.Name(), err) - } + t.Setenv("HOME", "./test-fixtures/config-home-test/config-file") return "" }, assertions: func(t *testing.T, app *Application) { assert.Equal(t, "test-home-config", app.File) }, - Cleanup: func(t *testing.T) { - err := os.Remove("./test-fixtures/config-home-test/.syft.yaml") // - if err != nil { - t.Fatalf("%s failed to remove home config link: %+v", t.Name(), err) - } - }, }, { name: "XDG file config", setup: func(t *testing.T) string { wd, err := os.Getwd() - if err != nil { - t.Fatalf("%s: failed to get working directory: %+v", t.Name(), err) - } + require.NoError(t, err) configDir := path.Join(wd, "./test-fixtures/config-home-test") // set HOME to testdata - t.Setenv("XDG_CONFIG_DIRS", configDir) + // note: this explicitly has multiple XDG paths, make certain we use the first VALID one (not the first one) + t.Setenv("XDG_CONFIG_DIRS", fmt.Sprintf("/another/foo/bar:%s", configDir)) xdg.Reload() return "" }, assertions: func(t *testing.T, app *Application) { assert.Equal(t, "test-home-XDG-config", app.File) }, - Cleanup: func(t *testing.T) {}, + cleanup: func() { + require.NoError(t, os.Unsetenv("XDG_CONFIG_DIRS")) + xdg.Reload() + }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - defer test.Cleanup(t) - wd, err := os.Getwd() - if err != nil { - t.Fatalf("failed to get working directory: %+v", err) + if test.cleanup != nil { + t.Cleanup(test.cleanup) } + wd, err := os.Getwd() + require.NoError(t, err) + defer os.Chdir(wd) // reset working directory after test application := &Application{} viperInstance := viper.New() + // this will override home in case you are running this test locally and DO have a syft config + // in your home directory... now it will be ignored. Same for XDG_CONFIG_DIRS. + t.Setenv("HOME", "/foo/bar") + t.Setenv("XDG_CONFIG_DIRS", "/foo/bar") + xdg.Reload() + configPath := test.setup(t) err = application.LoadAllValues(viperInstance, configPath) - if err != nil { - t.Fatalf("failed to load application config: %+v", err) - } + require.NoError(t, err) test.assertions(t, application) }) } diff --git a/internal/config/test-fixtures/config-home-test/.syft/config.yaml b/internal/config/test-fixtures/config-home-test/syft/config.yaml similarity index 100% rename from internal/config/test-fixtures/config-home-test/.syft/config.yaml rename to internal/config/test-fixtures/config-home-test/syft/config.yaml