From 75e9e35ce3ba384fb2960b84e4783c9d3e2324aa Mon Sep 17 00:00:00 2001 From: Manuel Alonso <434575+manute@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:55:13 +0100 Subject: [PATCH 1/4] fix(api): configmaps items generated in order --- api/internal/generators/configmap.go | 2 +- api/internal/generators/secret.go | 2 +- api/internal/generators/utils.go | 31 ++++++++++++++++++++-------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/api/internal/generators/configmap.go b/api/internal/generators/configmap.go index 47498aaa58..2f322f7dd3 100644 --- a/api/internal/generators/configmap.go +++ b/api/internal/generators/configmap.go @@ -37,7 +37,7 @@ func MakeConfigMap( if err != nil { return nil, err } - if err = rn.LoadMapIntoConfigMapData(m); err != nil { + if err = rn.LoadMapIntoConfigMapData(m.values); err != nil { return nil, err } err = copyLabelsAndAnnotations(rn, args.Options) diff --git a/api/internal/generators/secret.go b/api/internal/generators/secret.go index 9afaff156a..6a6ef8f68f 100644 --- a/api/internal/generators/secret.go +++ b/api/internal/generators/secret.go @@ -50,7 +50,7 @@ func MakeSecret( if err != nil { return nil, err } - if err = rn.LoadMapIntoSecretData(m); err != nil { + if err = rn.LoadMapIntoSecretData(m.values); err != nil { return nil, err } copyLabelsAndAnnotations(rn, args.Options) diff --git a/api/internal/generators/utils.go b/api/internal/generators/utils.go index b570c7e91b..de265f4916 100644 --- a/api/internal/generators/utils.go +++ b/api/internal/generators/utils.go @@ -36,25 +36,38 @@ kind: %s return rn, nil } +type orderedMap struct { + keys []string + values map[string]string +} + func makeValidatedDataMap( - ldr ifc.KvLoader, name string, sources types.KvPairSources) (map[string]string, error) { + ldr ifc.KvLoader, name string, sources types.KvPairSources, +) (orderedMap, error) { + pairs, err := ldr.Load(sources) if err != nil { - return nil, errors.WrapPrefix(err, "loading KV pairs", 0) + return orderedMap{}, errors.WrapPrefix(err, "loading KV pairs", 0) } - knownKeys := make(map[string]string) + + seen := make(map[string]struct{}) + values := make(map[string]string, len(pairs)) + var keys []string + for _, p := range pairs { - // legal key: alphanumeric characters, '-', '_' or '.' if err := ldr.Validator().ErrIfInvalidKey(p.Key); err != nil { - return nil, err + return orderedMap{}, err } - if _, ok := knownKeys[p.Key]; ok { - return nil, errors.Errorf( + if _, dup := seen[p.Key]; dup { + return orderedMap{}, errors.Errorf( "configmap %s illegally repeats the key `%s`", name, p.Key) } - knownKeys[p.Key] = p.Value + seen[p.Key] = struct{}{} + keys = append(keys, p.Key) + values[p.Key] = p.Value } - return knownKeys, nil + + return orderedMap{keys: keys, values: values}, nil } // copyLabelsAndAnnotations copies labels and annotations from From 2ad7965dba1404ce85161fdf8158b94b0f4df845 Mon Sep 17 00:00:00 2001 From: Manuel Alonso <434575+manute@users.noreply.github.com> Date: Wed, 26 Nov 2025 07:14:19 +0100 Subject: [PATCH 2/4] feat(test): orderMap for makeValidator --- api/internal/generators/utils_test.go | 104 +++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/api/internal/generators/utils_test.go b/api/internal/generators/utils_test.go index fbb2f262cf..77776f6ed2 100644 --- a/api/internal/generators/utils_test.go +++ b/api/internal/generators/utils_test.go @@ -1,13 +1,15 @@ // Copyright 2020 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 -package generators_test +package generators import ( "testing" "github.com/stretchr/testify/require" - . "sigs.k8s.io/kustomize/api/internal/generators" + "sigs.k8s.io/kustomize/api/ifc" + valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest" + "sigs.k8s.io/kustomize/api/types" ) func TestParseFileSource(t *testing.T) { @@ -49,3 +51,101 @@ func TestParseFileSource(t *testing.T) { }) } } + +func TestMakeValidateDataMapOrder(t *testing.T) { + tests := []struct { + name string + pairs []types.Pair + wantKeys []string + wantValues map[string]string + wantErr bool + validatorFn func() ifc.Validator + }{ + { + name: "single pair", + pairs: []types.Pair{ + {Key: "key", Value: "value"}, + }, + wantKeys: []string{"key"}, + wantValues: map[string]string{"key": "value"}, + }, + { + name: "multiple pairs preserve order", + pairs: []types.Pair{ + {Key: "A", Value: "1"}, + {Key: "B", Value: "2"}, + {Key: "C", Value: "3"}, + }, + wantKeys: []string{"A", "B", "C"}, + wantValues: map[string]string{"A": "1", "B": "2", "C": "3"}, + }, + { + name: "multiple pairs out of order - loader order wins", + pairs: []types.Pair{ + {Key: "third", Value: "3"}, + {Key: "first", Value: "1"}, + {Key: "second", Value: "2"}, + }, + wantKeys: []string{"third", "first", "second"}, + wantValues: map[string]string{"third": "3", "first": "1", "second": "2"}, + }, + { + name: "duplicate key returns error", + pairs: []types.Pair{ + {Key: "dup", Value: "1"}, + {Key: "dup", Value: "2"}, + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + loader := &fakeKvLoader{ + Pairs: tt.pairs, + Val: func() ifc.Validator { + if tt.validatorFn != nil { + return tt.validatorFn() + } + return valtest_test.MakeFakeValidator() + }(), + } + + args := types.ConfigMapArgs{ + GeneratorArgs: types.GeneratorArgs{ + Name: "envConfigMap", + KvPairSources: types.KvPairSources{ + EnvSources: []string{"app.env"}, + }, + }, + } + + res, err := makeValidatedDataMap(loader, args.Name, args.KvPairSources) + + if tt.wantErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Exactly(t, tt.wantKeys, res.keys) + require.Exactly(t, tt.wantValues, res.values) + }) + } +} + +type fakeKvLoader struct { + Pairs []types.Pair + Val ifc.Validator +} + +func (f *fakeKvLoader) Load(_ types.KvPairSources) ([]types.Pair, error) { + return f.Pairs, nil +} + +func (f *fakeKvLoader) Validator() ifc.Validator { + if f.Val != nil { + return f.Val + } + return valtest_test.MakeFakeValidator() +} From dcb55de5598907d828df755f77e18db123aeb482 Mon Sep 17 00:00:00 2001 From: Manuel Alonso <434575+manute@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:33:04 +0100 Subject: [PATCH 3/4] chore(lint): fix lint --- api/internal/generators/utils.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/api/internal/generators/utils.go b/api/internal/generators/utils.go index de265f4916..5f4c61d046 100644 --- a/api/internal/generators/utils.go +++ b/api/internal/generators/utils.go @@ -44,7 +44,6 @@ type orderedMap struct { func makeValidatedDataMap( ldr ifc.KvLoader, name string, sources types.KvPairSources, ) (orderedMap, error) { - pairs, err := ldr.Load(sources) if err != nil { return orderedMap{}, errors.WrapPrefix(err, "loading KV pairs", 0) @@ -52,11 +51,11 @@ func makeValidatedDataMap( seen := make(map[string]struct{}) values := make(map[string]string, len(pairs)) - var keys []string + keys := make([]string, len(pairs)) for _, p := range pairs { if err := ldr.Validator().ErrIfInvalidKey(p.Key); err != nil { - return orderedMap{}, err + return orderedMap{}, errors.Wrap(err, 1) } if _, dup := seen[p.Key]; dup { return orderedMap{}, errors.Errorf( From 30a91e397a1c00ed7890fffc145678e4791d5757 Mon Sep 17 00:00:00 2001 From: Manuel Alonso <434575+manute@users.noreply.github.com> Date: Mon, 1 Dec 2025 19:35:42 +0100 Subject: [PATCH 4/4] fix(configmap): simplify map, wrap error with name --- api/internal/generators/utils.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/api/internal/generators/utils.go b/api/internal/generators/utils.go index 5f4c61d046..6368a2d468 100644 --- a/api/internal/generators/utils.go +++ b/api/internal/generators/utils.go @@ -46,7 +46,7 @@ func makeValidatedDataMap( ) (orderedMap, error) { pairs, err := ldr.Load(sources) if err != nil { - return orderedMap{}, errors.WrapPrefix(err, "loading KV pairs", 0) + return orderedMap{}, errors.WrapPrefix(err, fmt.Sprintf("loading KV pairs, name: %s", name), 0) } seen := make(map[string]struct{}) @@ -55,11 +55,7 @@ func makeValidatedDataMap( for _, p := range pairs { if err := ldr.Validator().ErrIfInvalidKey(p.Key); err != nil { - return orderedMap{}, errors.Wrap(err, 1) - } - if _, dup := seen[p.Key]; dup { - return orderedMap{}, errors.Errorf( - "configmap %s illegally repeats the key `%s`", name, p.Key) + return orderedMap{}, errors.WrapPrefix(err, fmt.Sprintf("invalid key %s, name %s", p.Key, name), 0) } seen[p.Key] = struct{}{} keys = append(keys, p.Key)