diff --git a/go.work.sum b/go.work.sum index 1af079419..a910755d4 100644 --- a/go.work.sum +++ b/go.work.sum @@ -118,6 +118,7 @@ github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= @@ -201,6 +202,7 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= @@ -208,21 +210,56 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= +google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= +gopkg.in/cheggaaa/pb.v1 v1.0.25 h1:Ev7yu1/f6+d+b3pi5vPdRPc6nNtP1umSfcWiEfRqv6I= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= +gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= +k8s.io/apiserver v0.17.0 h1:XhUix+FKFDcBygWkQNp7wKKvZL030QUlH1o8vFeSgZA= +k8s.io/code-generator v0.17.0 h1:y+KWtDWNqlJzJu/kUy8goJZO0X71PGIpAHLX8a0JYk0= +k8s.io/component-base v0.17.0 h1:BnDFcmBDq+RPpxXjmuYnZXb59XNN9CaFrX8ba9+3xrA= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c h1:GohjlNKauSai7gN4wsJkeZ3WAJx4Sh+oT/b5IYn5suA= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= +modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE= +modernc.org/mathutil v1.0.0 h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I= +modernc.org/strutil v1.0.0 h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE= +modernc.org/xc v1.0.0 h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU= +rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= +rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= +rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU= diff --git a/kustomize/commands/edit/add/configmap.go b/kustomize/commands/edit/add/configmap.go index 147f6c4b3..0b44aa786 100644 --- a/kustomize/commands/edit/add/configmap.go +++ b/kustomize/commands/edit/add/configmap.go @@ -148,7 +148,7 @@ func addConfigMap( func findOrMakeConfigMapArgs(m *types.Kustomization, name, namespace string) *types.ConfigMapArgs { for i, v := range m.ConfigMapGenerator { - if name == v.Name && namespace == v.Namespace { + if name == v.Name && util.NamespaceEqual(v.Namespace, namespace) { return &m.ConfigMapGenerator[i] } } diff --git a/kustomize/commands/edit/add/configmap_test.go b/kustomize/commands/edit/add/configmap_test.go index c45ff381c..32d428467 100644 --- a/kustomize/commands/edit/add/configmap_test.go +++ b/kustomize/commands/edit/add/configmap_test.go @@ -26,7 +26,7 @@ const ( func TestNewAddConfigMapIsNotNil(t *testing.T) { fSys := filesys.MakeFsInMemory() - assert.NotNil(t, newCmdAddConfigMap( + require.NotNil(t, newCmdAddConfigMap( fSys, kv.NewLoader( loader.NewFileLoaderAtCwd(fSys), @@ -41,15 +41,14 @@ func TestMakeConfigMapArgs(t *testing.T) { NamePrefix: "test-name-prefix", } - if len(kustomization.ConfigMapGenerator) != 0 { - t.Fatal("Initial kustomization should not have any configmaps") - } + require.Len(t, kustomization.ConfigMapGenerator, 0, "Initial kustomization should not have any configmaps") + args := findOrMakeConfigMapArgs(kustomization, cmName, configMapNamespace) - assert.NotNil(t, args) - assert.Equal(t, 1, len(kustomization.ConfigMapGenerator)) - assert.Equal(t, &kustomization.ConfigMapGenerator[len(kustomization.ConfigMapGenerator)-1], args) - assert.Equal(t, args, findOrMakeConfigMapArgs(kustomization, cmName, configMapNamespace)) - assert.Equal(t, 1, len(kustomization.ConfigMapGenerator)) + require.NotNil(t, args) + require.Equal(t, 1, len(kustomization.ConfigMapGenerator)) + require.Equal(t, &kustomization.ConfigMapGenerator[len(kustomization.ConfigMapGenerator)-1], args) + require.Equal(t, args, findOrMakeConfigMapArgs(kustomization, cmName, configMapNamespace)) + require.Equal(t, 1, len(kustomization.ConfigMapGenerator)) } func TestMergeFlagsIntoConfigMapArgs_LiteralSources(t *testing.T) { @@ -352,3 +351,143 @@ func TestEditAddConfigMapWithFileSource(t *testing.T) { }) } } + +// TestEditAddConfigMapNamespaced tests situations regarding namespacing. For example, it +// verifies that the empty namespace and the default namespace are treated the +// same when adding a configmap to a kustomization file. +func TestEditAddConfigMapNamespaced(t *testing.T) { + testCases := []struct { + name string + configMapName string + configMapNamespace string + literalSources []string + initialArgs string + expectedResult []types.ConfigMapArgs + expectedSliceLength int + }{ + { + name: "adds new key to configmap when default namespace matches empty", + configMapName: "test-cm", + configMapNamespace: "default", + literalSources: []string{"key1=value1"}, + initialArgs: `--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +configMapGenerator: +- literals: + - key=value + name: test-cm +`, + expectedResult: []types.ConfigMapArgs{ + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "", + Name: "test-cm", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key=value", "key1=value1"}, + }, + }, + }, + }, + expectedSliceLength: 1, + }, + { + name: "adds new key to configmap when empty namespace matches default", + configMapName: "test-cm", + configMapNamespace: "", + literalSources: []string{"key1=value1"}, + initialArgs: `--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +configMapGenerator: +- literals: + - key=value + name: test-cm + namespace: default +`, + expectedResult: []types.ConfigMapArgs{ + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "default", + Name: "test-cm", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key=value", "key1=value1"}, + }, + }, + }, + }, + expectedSliceLength: 1, + }, + { + name: "creates a new generator when namespaces don't match", + configMapName: "test-cm", + configMapNamespace: "", + literalSources: []string{"key1=value1"}, + initialArgs: `--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +configMapGenerator: +- literals: + - key=value + name: test-cm + namespace: ns1 +`, + expectedResult: []types.ConfigMapArgs{ + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "ns1", + Name: "test-cm", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key=value"}, + }, + }, + }, + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "", + Name: "test-cm", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key1=value1"}, + }, + }, + }, + }, + expectedSliceLength: 2, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + fSys := filesys.MakeEmptyDirInMemory() + testutils_test.WriteTestKustomizationWith(fSys, []byte(tc.initialArgs)) + + pvd := provider.NewDefaultDepProvider() + ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator()) + + args := []string{ + tc.configMapName, + fmt.Sprintf(util.FlagFormat, util.NamespaceFlag, tc.configMapNamespace), + } + + for _, source := range tc.literalSources { + args = append(args, fmt.Sprintf(util.FlagFormat, util.FromLiteralFlag, source)) + } + + cmd := newCmdAddConfigMap(fSys, ldr, pvd.GetResourceFactory()) + cmd.SetArgs(args) + require.NoError(t, cmd.Execute()) + + _, err := testutils_test.ReadTestKustomization(fSys) + require.NoError(t, err) + + mf, err := kustfile.NewKustomizationFile(fSys) + require.NoError(t, err) + + kustomization, err := mf.Read() + require.NoError(t, err) + + require.Len(t, kustomization.ConfigMapGenerator, tc.expectedSliceLength) + require.ElementsMatch(t, tc.expectedResult, kustomization.ConfigMapGenerator) + }) + } +} diff --git a/kustomize/commands/edit/add/secret.go b/kustomize/commands/edit/add/secret.go index aee0cde16..f55005d0b 100644 --- a/kustomize/commands/edit/add/secret.go +++ b/kustomize/commands/edit/add/secret.go @@ -140,7 +140,7 @@ func addSecret( func findOrMakeSecretArgs(m *types.Kustomization, name, namespace, secretType string) *types.SecretArgs { for i, v := range m.SecretGenerator { - if name == v.Name && namespace == v.Namespace { + if name == v.Name && util.NamespaceEqual(v.Namespace, namespace) { return &m.SecretGenerator[i] } } diff --git a/kustomize/commands/edit/add/secret_test.go b/kustomize/commands/edit/add/secret_test.go index 0b48ac090..99caf8adf 100644 --- a/kustomize/commands/edit/add/secret_test.go +++ b/kustomize/commands/edit/add/secret_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/kv" "sigs.k8s.io/kustomize/api/pkg/loader" "sigs.k8s.io/kustomize/api/provider" @@ -237,3 +238,150 @@ func TestEditAddSecretWithFileSource(t *testing.T) { require.Equal(t, secretName, newSecretGenerator.Name) require.Contains(t, newSecretGenerator.FileSources, fileSource) } + +// TestEditAddSecretNamespaced tests situations regarding namespacing. For example, it +// verifies that the empty namespace and the default namespace are treated the +// same when adding a configmap to a kustomization file. +func TestEditAddSecretNamespaced(t *testing.T) { + testCases := []struct { + name string + secretName string + secretNamespace string + literalSources []string + initialArgs string + expectedResult []types.SecretArgs + expectedSliceLength int + }{ + { + name: "adds new key to secret when default namespace matches empty", + secretName: "test-secret", + secretNamespace: "default", + literalSources: []string{"key1=value1"}, + initialArgs: `--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +secretGenerator: +- literals: + - key=value + name: test-secret + type: Opaque +`, + expectedResult: []types.SecretArgs{ + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "", + Name: "test-secret", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key=value", "key1=value1"}, + }, + }, + Type: ifc.SecretTypeOpaque, + }, + }, + expectedSliceLength: 1, + }, + { + name: "adds new key to secret when empty namespace matches default", + secretName: "test-secret", + secretNamespace: "", + literalSources: []string{"key1=value1"}, + initialArgs: `--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +secretGenerator: +- literals: + - key=value + name: test-secret + namespace: default + type: Opaque +`, + expectedResult: []types.SecretArgs{ + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "default", + Name: "test-secret", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key=value", "key1=value1"}, + }, + }, + Type: ifc.SecretTypeOpaque, + }, + }, + expectedSliceLength: 1, + }, + { + name: "creates a new generator when namespaces don't match", + secretName: "test-secret", + secretNamespace: "", + literalSources: []string{"key1=value1"}, + initialArgs: `--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +secretGenerator: +- literals: + - key=value + name: test-secret + namespace: ns1 + type: Opaque +`, + expectedResult: []types.SecretArgs{ + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "ns1", + Name: "test-secret", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key=value"}, + }, + }, + Type: ifc.SecretTypeOpaque, + }, + { + GeneratorArgs: types.GeneratorArgs{ + Namespace: "", + Name: "test-secret", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"key1=value1"}, + }, + }, + Type: ifc.SecretTypeOpaque, + }, + }, + expectedSliceLength: 2, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + fSys := filesys.MakeEmptyDirInMemory() + testutils_test.WriteTestKustomizationWith(fSys, []byte(tc.initialArgs)) + + pvd := provider.NewDefaultDepProvider() + ldr := kv.NewLoader(loader.NewFileLoaderAtCwd(fSys), pvd.GetFieldValidator()) + + args := []string{ + tc.secretName, + fmt.Sprintf(util.FlagFormat, util.NamespaceFlag, tc.secretNamespace), + } + + for _, source := range tc.literalSources { + args = append(args, fmt.Sprintf(util.FlagFormat, util.FromLiteralFlag, source)) + } + + cmd := newCmdAddSecret(fSys, ldr, pvd.GetResourceFactory()) + cmd.SetArgs(args) + require.NoError(t, cmd.Execute()) + + _, err := testutils_test.ReadTestKustomization(fSys) + require.NoError(t, err) + + mf, err := kustfile.NewKustomizationFile(fSys) + require.NoError(t, err) + + kustomization, err := mf.Read() + require.NoError(t, err) + + require.Len(t, kustomization.SecretGenerator, tc.expectedSliceLength) + require.ElementsMatch(t, tc.expectedResult, kustomization.SecretGenerator) + }) + } +} diff --git a/kustomize/commands/internal/util/util.go b/kustomize/commands/internal/util/util.go index aa42e3213..2c9be9eab 100644 --- a/kustomize/commands/internal/util/util.go +++ b/kustomize/commands/internal/util/util.go @@ -12,6 +12,9 @@ import ( "sigs.k8s.io/kustomize/kyaml/filesys" ) +// DefaultNamespace is the default namespace name in Kubernetes. +const DefaultNamespace = "default" + // GlobPatterns accepts a slice of glob strings and returns the set of // matching file paths. func GlobPatterns(fSys filesys.FileSystem, patterns []string) ([]string, error) { @@ -30,7 +33,7 @@ func GlobPatterns(fSys filesys.FileSystem, patterns []string) ([]string, error) return result, nil } -// GlobPatterns accepts a slice of glob strings and returns the set of matching file paths. +// GlobPatternsWithLoader accepts a slice of glob strings and returns the set of matching file paths. // If validation is skipped, then it will return the patterns as provided. // Otherwise, It will try to load the files from the filesystem. // If files are not found in the filesystem, it will try to load from remote. @@ -109,3 +112,18 @@ func trimQuotes(s string) string { } return s } + +// NamespaceEqual checks if two namespaces are the same. It considers the empty namespace and the default namespace to +// be the same. As such, when one namespace is the empty string ('""') and the other namespace is "default", this function +// will return true. +func NamespaceEqual(namespace string, otherNamespace string) bool { + if "" == namespace { + namespace = DefaultNamespace + } + + if "" == otherNamespace { + otherNamespace = DefaultNamespace + } + + return namespace == otherNamespace +} diff --git a/kustomize/commands/internal/util/util_test.go b/kustomize/commands/internal/util/util_test.go index 16fae2660..5cb3ac32d 100644 --- a/kustomize/commands/internal/util/util_test.go +++ b/kustomize/commands/internal/util/util_test.go @@ -1,7 +1,7 @@ // Copyright 2019 The Kubernetes Authors. // SPDX-License-Identifier: Apache-2.0 -package util +package util_test import ( "fmt" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "sigs.k8s.io/kustomize/api/ifc" + . "sigs.k8s.io/kustomize/kustomize/v5/commands/internal/util" "sigs.k8s.io/kustomize/kyaml/filesys" ) @@ -86,6 +87,58 @@ func TestGlobPatternsWithLoaderRemoteFile(t *testing.T) { require.Equal(t, invalidURL, resources[0], "incorrect resources") } +func TestNamespaceEqual(t *testing.T) { + testCases := []struct { + name string + namespace1 string + namespace2 string + want func(require.TestingT, bool, ...interface{}) + }{ + { + name: "succeeds when namespaces are the same", + namespace1: "ns1", + namespace2: "ns1", + want: require.True, + }, + { + name: "succeeds when namespaces are default and empty string", + namespace1: "", + namespace2: DefaultNamespace, + want: require.True, + }, + { + name: "succeeds when namespaces are empty string and default", + namespace1: DefaultNamespace, + namespace2: "", + want: require.True, + }, + { + name: "fails when namespaces are not the same", + namespace1: "ns1", + namespace2: "ns2", + want: require.False, + }, + { + name: "fails when one is empty and other is different from default", + namespace1: "", + namespace2: "ns1", + want: require.False, + }, + { + name: "fails when one is different from default and other is empty", + namespace1: "ns1", + namespace2: "", + want: require.False, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tc.want(t, NamespaceEqual(tc.namespace1, tc.namespace2)) + }) + } +} + type fakeLoader struct { path string } diff --git a/kustomize/go.mod b/kustomize/go.mod index 0da2375e8..20fe39b18 100644 --- a/kustomize/go.mod +++ b/kustomize/go.mod @@ -33,6 +33,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/sys v0.13.0 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect diff --git a/kustomize/go.sum b/kustomize/go.sum index 377893fe6..ebeb93474 100644 --- a/kustomize/go.sum +++ b/kustomize/go.sum @@ -66,6 +66,8 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=