Skip to content

Commit

Permalink
fix: support namespace flag on edit remove secret/configmap
Browse files Browse the repository at this point in the history
Fix the 'edit remove secret'/'edit remove configmap' commands that were previously
missing support to specifying a namespace.
  • Loading branch information
stormqueen1990 committed Nov 29, 2023
1 parent bfb00ec commit 228d22c
Show file tree
Hide file tree
Showing 4 changed files with 339 additions and 96 deletions.
40 changes: 29 additions & 11 deletions kustomize/commands/edit/remove/removeconfigmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,49 @@ import (
"sigs.k8s.io/kustomize/api/konfig"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/util"
"sigs.k8s.io/kustomize/kyaml/filesys"
)

type removeConfigMapOptions struct {
configMapNamesToRemove []string
namespace string
}

// newCmdRemoveConfigMap removes configMapGenerator(s) with the specified name(s).
func newCmdRemoveConfigMap(fSys filesys.FileSystem) *cobra.Command {
var o removeConfigMapOptions
var flags removeConfigMapOptions

cmd := &cobra.Command{
Use: "configmap",
Use: "configmap NAME [,NAME] [--namespace=namespace-name]",
Short: "Removes the specified configmap(s) from " +
konfig.DefaultKustomizationFileName(),
Long: "",
Long: `Removes the specified configmap(s) from the ` + konfig.DefaultKustomizationFileName() + ` file in the specified namespace.
If multiple configmap names are specified, the command will not fail on secret names that were not found in the file,
but will issue a warning for each name that wasn't found.`,
Example: `
remove configmap my-configmap
`,
# Removes a single configmap named 'my-configmap' in the default namespace from the ` + konfig.DefaultKustomizationFileName() + ` file
kustomize edit remove configmap my-configmap
# Removes configmaps named 'my-configmap' and 'other-configmap' in namespace 'test-namespace' from the ` + konfig.DefaultKustomizationFileName() + ` file
kustomize edit remove configmap my-configmap,other-configmap --namespace=test-namespace
`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
err := flags.Validate(args)
if err != nil {
return err
}
return o.RunRemoveConfigMap(fSys)
return flags.RunRemoveConfigMap(fSys)
},
}

cmd.Flags().StringVar(
&flags.namespace,
util.NamespaceFlag,
"",
"Namespace to remove ConfigMap(s) from",
)

return cmd
}

Expand Down Expand Up @@ -69,14 +85,16 @@ func (o *removeConfigMapOptions) RunRemoveConfigMap(fSys filesys.FileSystem) err
}

foundConfigMaps := make(map[string]struct{})
remainingConfigMaps := make([]types.ConfigMapArgs, 0, len(m.ConfigMapGenerator))

newConfigMaps := make([]types.ConfigMapArgs, 0, len(m.ConfigMapGenerator))
for _, currentConfigMap := range m.ConfigMapGenerator {
if kustfile.StringInSlice(currentConfigMap.Name, o.configMapNamesToRemove) {
if kustfile.StringInSlice(currentConfigMap.Name, o.configMapNamesToRemove) &&
util.NamespaceEqual(currentConfigMap.Namespace, o.namespace) {
foundConfigMaps[currentConfigMap.Name] = struct{}{}
continue
}
newConfigMaps = append(newConfigMaps, currentConfigMap)

remainingConfigMaps = append(remainingConfigMaps, currentConfigMap)
}

if len(foundConfigMaps) == 0 {
Expand All @@ -90,7 +108,7 @@ func (o *removeConfigMapOptions) RunRemoveConfigMap(fSys filesys.FileSystem) err
}
}

m.ConfigMapGenerator = newConfigMaps
m.ConfigMapGenerator = remainingConfigMaps
err = mf.Write(m)
if err != nil {
return fmt.Errorf("failed to write kustomization file: %w", err)
Expand Down
178 changes: 141 additions & 37 deletions kustomize/commands/edit/remove/removeconfigmap_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// Copyright 2023 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package remove //nolint:testpackage
package remove

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -13,84 +12,188 @@ import (
)

func TestRemoveConfigMap(t *testing.T) {
const configMapName01 = "example-configmap-01"
const configMapName02 = "example-configmap-02"

tests := map[string]struct {
input string
args []string
expectedOutput string
wantErr bool
expectedErr string
}{
"happy path": {
input: fmt.Sprintf(`
"removes a configmap successfully": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: %s
- name: test-cm-1
files:
- application.properties
`, configMapName01),
args: []string{configMapName01},
`,
args: []string{"test-cm-1"},
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`,
},
"multiple": {
input: fmt.Sprintf(`
"removes multiple configmaps successfully": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: %s
- name: test-cm-1
files:
- application.properties
- name: %s
- name: test-cm-2
files:
- application.properties
`, configMapName01, configMapName02),
args: []string{
fmt.Sprintf("%s,%s", configMapName01, configMapName02),
},
`,
args: []string{"test-cm-1,test-cm-2"},
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`,
},
"miss": {
input: fmt.Sprintf(`
"removes a configmap successfully when single configmap name is specified, it exists, but is not the only configmap present": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: %s
- name: test-cm-1
namespace: test-ns
files:
- application.properties
`, configMapName01),
args: []string{"foo"},
expectedErr: "no specified configmap(s) were found",
- name: test-cm-2
namespace: default
literals:
- test-key=test-value
`,
args: []string{"test-cm-1", "--namespace=test-ns"},
wantErr: false,
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- literals:
- test-key=test-value
name: test-cm-2
namespace: default
`,
},
"no configmap name specified": {
args: []string{},
expectedErr: "at least one configmap name must be specified",
"succeeds when one configmap name exists and one doesn't exist": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: test-cm-1
files:
- application.properties
`,
args: []string{"test-cm-1,foo"},
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`,
},
"too many configmap names specified": {
args: []string{"test1", "test2"},
expectedErr: "too many arguments",
"succeeds when one configmap name exists in the specified namespace": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: test-cm
namespace: test-ns
files:
- application.properties
`,
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`,
wantErr: false,
args: []string{"test-cm", "--namespace=test-ns"},
},
"one existing and one non-existing": {
input: fmt.Sprintf(`
"handles empty namespace as default in the args": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: %s
- name: test-cm
namespace: default
files:
- application.properties
`, configMapName01),
args: []string{fmt.Sprintf("%s,%s", configMapName01, "foo")},
`,
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`,
wantErr: false,
args: []string{"test-cm"},
},
"handles empty namespace as default in the kustomization file": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: test-cm
files:
- application.properties
`,
expectedOutput: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
`,
wantErr: false,
args: []string{"test-cm", "--namespace=default"},
},
"fails when single configmap name is specified and doesn't exist": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: test-cm-1
files:
- application.properties
`,
args: []string{"foo"},
wantErr: true,
expectedErr: "no specified configmap(s) were found",
},
"fails when single configmap name is specified and doesn't exist in the specified namespace": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: test-cm-1
namespace: test-ns
files:
- application.properties
`,
args: []string{"test-cm-1"},
wantErr: true,
expectedErr: "no specified configmap(s) were found",
},

"fails when single configmap name is specified and doesn't exist in the specified namespace, and neither namespace is the default one": {
input: `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: test-cm-1
namespace: test-ns
files:
- application.properties
`,
args: []string{"test-cm-1", "--namespace=other-ns"},
wantErr: true,
expectedErr: "no specified configmap(s) were found",
},
"fails when no configmap name is specified": {
args: []string{},
wantErr: true,
expectedErr: "at least one configmap name must be specified",
},
"fails when too many configmap names are specified": {
args: []string{"test1", "test2"},
wantErr: true,
expectedErr: "too many arguments",
},
}

Expand All @@ -99,9 +202,10 @@ kind: Kustomization
fSys := filesys.MakeFsInMemory()
testutils_test.WriteTestKustomizationWith(fSys, []byte(tc.input))
cmd := newCmdRemoveConfigMap(fSys)
err := cmd.RunE(cmd, tc.args)
cmd.SetArgs(tc.args)
err := cmd.Execute()

if tc.expectedErr != "" {
if tc.wantErr {
require.Error(t, err)
require.Contains(t, err.Error(), tc.expectedErr)
return
Expand Down

0 comments on commit 228d22c

Please sign in to comment.