diff --git a/kustomize/internal/commands/edit/add/configmap.go b/kustomize/internal/commands/edit/add/configmap.go index 25272c141..7e928fcac 100644 --- a/kustomize/internal/commands/edit/add/configmap.go +++ b/kustomize/internal/commands/edit/add/configmap.go @@ -18,7 +18,7 @@ func newCmdAddConfigMap( kf ifc.KunstructuredFactory) *cobra.Command { var flags flagsAndArgs cmd := &cobra.Command{ - Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1]", + Use: "configmap NAME [--behavior={create|merge|replace}] [--from-file=[key=]source] [--from-literal=key1=value1]", Short: "Adds a configmap to the kustomization file.", Long: "", Example: ` @@ -30,6 +30,9 @@ func newCmdAddConfigMap( # Adds a configmap from env-file kustomize edit add configmap my-configmap --from-env-file=env/path.env + + # Adds a configmap from env-file with behavior merge + kustomize edit add configmap my-configmap --behavior=merge --from-env-file=env/path.env `, RunE: func(_ *cobra.Command, args []string) error { err := flags.ExpandFileSource(fSys) @@ -86,6 +89,13 @@ func newCmdAddConfigMap( "disableNameSuffixHash", false, "Disable the name suffix for the configmap") + cmd.Flags().StringVar( + &flags.Behavior, + "behavior", + "", + "Specify the behavior for config map generation, i.e whether to create a new configmap (the default), "+ + "to merge with a previously defined one, or to replace an existing one. Merge and replace should be used only "+ + " when overriding an existing configmap defined in a base") return cmd } @@ -136,4 +146,7 @@ func mergeFlagsIntoCmArgs(args *types.ConfigMapArgs, flags flagsAndArgs) { DisableNameSuffixHash: true, } } + if flags.Behavior != "" { + args.Behavior = flags.Behavior + } } diff --git a/kustomize/internal/commands/edit/add/configmap_test.go b/kustomize/internal/commands/edit/add/configmap_test.go index 84ed55373..a1e64469d 100644 --- a/kustomize/internal/commands/edit/add/configmap_test.go +++ b/kustomize/internal/commands/edit/add/configmap_test.go @@ -110,3 +110,41 @@ func TestMergeFlagsIntoConfigMapArgs_EnvSource(t *testing.T) { t.Fatalf("expected env2") } } + +func TestMergeFlagsIntoConfigMapArgs_Behavior(t *testing.T) { + k := &types.Kustomization{} + args := findOrMakeConfigMapArgs(k, "foo") + + createBehaviorFlags := flagsAndArgs{ + Behavior: "create", + EnvFileSource: "env1", + } + mergeFlagsIntoGeneratorArgs( + &args.GeneratorArgs, + createBehaviorFlags) + if k.ConfigMapGenerator[0].Behavior != "create" { + t.Fatalf("expected create") + } + + mergeBehaviorFlags := flagsAndArgs{ + Behavior: "merge", + EnvFileSource: "env1", + } + mergeFlagsIntoGeneratorArgs( + &args.GeneratorArgs, + mergeBehaviorFlags) + if k.ConfigMapGenerator[0].Behavior != "merge" { + t.Fatalf("expected merge") + } + + replaceBehaviorFlags := flagsAndArgs{ + Behavior: "replace", + EnvFileSource: "env1", + } + mergeFlagsIntoGeneratorArgs( + &args.GeneratorArgs, + replaceBehaviorFlags) + if k.ConfigMapGenerator[0].Behavior != "replace" { + t.Fatalf("expected replace") + } +} diff --git a/kustomize/internal/commands/edit/add/flagsandargs.go b/kustomize/internal/commands/edit/add/flagsandargs.go index 5f24fe6bf..1a896e4ff 100644 --- a/kustomize/internal/commands/edit/add/flagsandargs.go +++ b/kustomize/internal/commands/edit/add/flagsandargs.go @@ -7,6 +7,8 @@ import ( "fmt" "strings" + "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/kustomize/v3/internal/commands/util" ) @@ -22,6 +24,8 @@ type flagsAndArgs struct { // EnvFileSource to derive the configMap/Secret from (optional) // TODO: Rationalize this name with Generic.EnvSource EnvFileSource string + // Resource generation behavior (optional) + Behavior string // Type of secret to create Type string // Namespace of secret @@ -42,6 +46,10 @@ func (a *flagsAndArgs) Validate(args []string) error { if len(a.EnvFileSource) > 0 && (len(a.FileSources) > 0 || len(a.LiteralSources) > 0) { return fmt.Errorf("from-env-file cannot be combined with from-file or from-literal") } + if len(a.Behavior) > 0 && types.NewGenerationBehavior(a.Behavior) == types.BehaviorUnspecified { + return fmt.Errorf(`invalid behavior: must be one of "%s", "%s", or "%s"`, + types.BehaviorCreate, types.BehaviorMerge, types.BehaviorReplace) + } // TODO: Should we check if the path exists? if it's valid, if it's within the same (sub-)directory? return nil } diff --git a/kustomize/internal/commands/edit/add/flagsandargs_test.go b/kustomize/internal/commands/edit/add/flagsandargs_test.go index 80b4f160b..98bf03e8f 100644 --- a/kustomize/internal/commands/edit/add/flagsandargs_test.go +++ b/kustomize/internal/commands/edit/add/flagsandargs_test.go @@ -61,6 +61,22 @@ func TestDataConfigValidation_Flags(t *testing.T) { }, shouldFail: false, }, + { + name: "correct behavior", + fa: flagsAndArgs{ + EnvFileSource: "foo", + Behavior: "merge", + }, + shouldFail: false, + }, + { + name: "incorrect behavior", + fa: flagsAndArgs{ + EnvFileSource: "foo", + Behavior: "merge-unknown", + }, + shouldFail: true, + }, } for _, test := range tests { diff --git a/kustomize/internal/commands/edit/add/secret.go b/kustomize/internal/commands/edit/add/secret.go index 4a87080d7..4fc93c616 100644 --- a/kustomize/internal/commands/edit/add/secret.go +++ b/kustomize/internal/commands/edit/add/secret.go @@ -149,4 +149,7 @@ func mergeFlagsIntoGeneratorArgs(args *types.GeneratorArgs, flags flagsAndArgs) DisableNameSuffixHash: true, } } + if flags.Behavior != "" { + args.Behavior = flags.Behavior + } }