From 21369a39f241a2d0e6296dde03109ffc8e5e6427 Mon Sep 17 00:00:00 2001 From: Max Partenfelder Date: Wed, 24 Sep 2025 19:04:10 +0200 Subject: [PATCH] fix: filtering values files based off directory filter --- go.mod | 2 +- go.sum | 4 +- internal/templating/templating.go | 40 +++++++++++++ internal/templating/templating_test.go | 78 +++++++++++++++++++++----- 4 files changed, 106 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 4f77186..96b6617 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( require ( cloud.google.com/go/compute v1.5.0 // indirect filippo.io/age v1.0.0 // indirect - github.com/Azure/azure-sdk-for-go v63.3.0+incompatible // indirect + github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.26 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect diff --git a/go.sum b/go.sum index 9b46280..b8a328d 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/age v1.0.0 h1:V6q14n0mqYU3qKFkZ6oOaF9oXneOviS3ubXsSVBRSzc= filippo.io/age v1.0.0/go.mod h1:PaX+Si/Sd5G8LgfCwldsSba3H1DDQZhIhFGkhbHaBq8= -github.com/Azure/azure-sdk-for-go v63.3.0+incompatible h1:INepVujzUrmArRZjDLHbtER+FkvCoEwyRCXGqOlmDII= -github.com/Azure/azure-sdk-for-go v63.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= diff --git a/internal/templating/templating.go b/internal/templating/templating.go index c7a61d8..7f85808 100644 --- a/internal/templating/templating.go +++ b/internal/templating/templating.go @@ -39,6 +39,10 @@ func LoadValues() error { } } + valuesFiles = filterValuesFiles(valuesFiles, util.GetCliContext().String("dir")) + + templateValues = TemplateValues{} + for _, valuesFile := range valuesFiles { log.Trace("Loading secret values file: ", valuesFile) absoluteSecretPath := path.Join(util.GetRootDir(), valuesFile) @@ -59,6 +63,42 @@ func LoadValues() error { return nil } +func filterValuesFiles(valuesFiles []string, dirLimit string) []string { + dirLimitNormalized := normalizeDirPath(dirLimit) + if dirLimitNormalized == "" { + return valuesFiles + } + + filtered := make([]string, 0, len(valuesFiles)) + for _, valuesFile := range valuesFiles { + valuesDir := normalizeDirPath(filepath.Dir(valuesFile)) + if shouldIncludeValuesFile(valuesDir, dirLimitNormalized) { + filtered = append(filtered, valuesFile) + } + } + return filtered +} + +func shouldIncludeValuesFile(valuesDir string, dirLimit string) bool { + if dirLimit == "" { + return true + } + if valuesDir == "" { + return true + } + return strings.HasPrefix(valuesDir, dirLimit) || strings.HasPrefix(dirLimit, valuesDir) +} + +func normalizeDirPath(dir string) string { + dir = filepath.ToSlash(strings.TrimSpace(dir)) + dir = strings.TrimPrefix(dir, "./") + dir = strings.Trim(dir, "/") + if dir == "" || dir == "." { + return "" + } + return dir + "/" +} + func mergeMaps(a, b map[interface{}]interface{}) map[interface{}]interface{} { out := make(map[interface{}]interface{}, len(a)) for k, v := range a { diff --git a/internal/templating/templating_test.go b/internal/templating/templating_test.go index cab727f..d00d627 100644 --- a/internal/templating/templating_test.go +++ b/internal/templating/templating_test.go @@ -9,18 +9,18 @@ import ( func TestMapMerge1(t *testing.T) { a := map[interface{}]interface{}{ - "foo": "bar", + "foo": "bar", "fizz": "buzz", } b := map[interface{}]interface{}{ "fizz": "fizz", } c := map[interface{}]interface{}{ - "foo": "bar", + "foo": "bar", "fizz": "fizz", } d := mergeMaps(a, b) - assert.Equal(t, c, d, "Maps should be equal") + assert.Equal(t, c, d, "Maps should be equal") } func TestMapMerge2(t *testing.T) { @@ -39,7 +39,7 @@ func TestMapMerge2(t *testing.T) { "d": "4", } d := mergeMaps(a, b) - assert.Equal(t, c, d, "Maps should be equal") + assert.Equal(t, c, d, "Maps should be equal") } func TestMapMerge3(t *testing.T) { @@ -55,7 +55,7 @@ func TestMapMerge3(t *testing.T) { "b": 42, } d := mergeMaps(a, b) - assert.Equal(t, c, d, "Maps should be equal") + assert.Equal(t, c, d, "Maps should be equal") } func TestMapMerge4(t *testing.T) { @@ -71,7 +71,7 @@ func TestMapMerge4(t *testing.T) { "b": []interface{}{"2", "3"}, } d := mergeMaps(a, b) - assert.Equal(t, c, d, "Maps should be equal") + assert.Equal(t, c, d, "Maps should be equal") } func TestTemplateValuesMerge(t *testing.T) { @@ -159,17 +159,16 @@ func TestTemplateValuesMerge(t *testing.T) { assert.Equal(t, expectedMergedTemplateValues, templateValues, "TemplateValues should be equal") } - func TestValuesFileLoading(t *testing.T) { c := util.GetDummyCliContext() util.SetCliContext(c) util.ComputeRootDir(c) - + LoadValues() - + valuesSet1 := map[interface{}]interface{}{ - "namespace": "gitops-dev", - "stage": "dev", + "namespace": "gitops-dev", + "stage": "dev", "databaseUsername": "my-very-strong-username", "databasePassword": "my-very-strong-password", } @@ -178,12 +177,61 @@ func TestValuesFileLoading(t *testing.T) { assert.Equal(t, valuesSet1, mergedValues1, "Values should be equal") valuesSet2 := map[interface{}]interface{}{ - "namespace": "gitops-dev", - "stage": "sub-dev", + "namespace": "gitops-dev", + "stage": "sub-dev", "databaseUsername": "my-very-strong-username", "databasePassword": "my-very-strong-password", - "key": "fooo", + "key": "fooo", } mergedValues2 := GetValuesForPath("test_assets/subdirectory/subdir-secret.gitops.secret.enc.yml") assert.Equal(t, valuesSet2, mergedValues2, "Values should be equal") -} \ No newline at end of file +} + +func TestFilterValuesFiles(t *testing.T) { + valuesFiles := []string{ + "values.gitops.secret.enc.yml", + "foo/values.gitops.secret.enc.yml", + "foo/bar/values.gitops.secret.enc.yml", + "foo/bar/baz/values.gitops.secret.enc.yml", + "foo/other/values.gitops.secret.enc.yml", + } + + testCases := []struct { + name string + dirLimit string + expected []string + }{ + { + name: "no dir limit returns all", + dirLimit: "", + expected: valuesFiles, + }, + { + name: "limit includes ancestors and descendants", + dirLimit: "foo/bar", + expected: []string{ + "values.gitops.secret.enc.yml", + "foo/values.gitops.secret.enc.yml", + "foo/bar/values.gitops.secret.enc.yml", + "foo/bar/baz/values.gitops.secret.enc.yml", + }, + }, + { + name: "limit with trailing slash", + dirLimit: "foo/bar/", + expected: []string{ + "values.gitops.secret.enc.yml", + "foo/values.gitops.secret.enc.yml", + "foo/bar/values.gitops.secret.enc.yml", + "foo/bar/baz/values.gitops.secret.enc.yml", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + filtered := filterValuesFiles(valuesFiles, tc.dirLimit) + assert.Equal(t, tc.expected, filtered) + }) + } +}