Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support namespace flag on edit remove secret/configmap #5454

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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"},
stormqueen1990 marked this conversation as resolved.
Show resolved Hide resolved
},
"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