From 62f21cbe693c77b11db99412afe63c98f848b154 Mon Sep 17 00:00:00 2001 From: Chance Zibolski Date: Wed, 5 Feb 2020 10:15:55 -0800 Subject: [PATCH] Enable specifying GeneratorOptions per resource In addition to specifying GeneratorOptions globally within a kustomization, also allow users to set GeneratorOptions on a per-resource level. --- .../configmapandsecret/configmapfactory.go | 5 +- .../configmapfactory_test.go | 53 +++++++++++++++++-- .../k8sdeps/configmapandsecret/factory.go | 32 +++++++++++ .../configmapandsecret/secretfactory.go | 5 +- .../configmapandsecret/secretfactory_test.go | 53 +++++++++++++++++-- api/types/generatorargs.go | 3 ++ 6 files changed, 137 insertions(+), 14 deletions(-) diff --git a/api/internal/k8sdeps/configmapandsecret/configmapfactory.go b/api/internal/k8sdeps/configmapandsecret/configmapfactory.go index bd11f30d5..74da4d381 100644 --- a/api/internal/k8sdeps/configmapandsecret/configmapfactory.go +++ b/api/internal/k8sdeps/configmapandsecret/configmapfactory.go @@ -38,10 +38,7 @@ func (f *Factory) MakeConfigMap( return nil, errors.Wrap(err, "trouble mapping") } } - if f.options != nil { - cm.SetLabels(f.options.Labels) - cm.SetAnnotations(f.options.Annotations) - } + f.setLabelsAndAnnnotations(cm, args.GeneratorOptions) return cm, nil } diff --git a/api/internal/k8sdeps/configmapandsecret/configmapfactory_test.go b/api/internal/k8sdeps/configmapandsecret/configmapfactory_test.go index fdf2b769d..023e00be2 100644 --- a/api/internal/k8sdeps/configmapandsecret/configmapfactory_test.go +++ b/api/internal/k8sdeps/configmapandsecret/configmapfactory_test.go @@ -53,7 +53,7 @@ BAR=baz } } -func makeLiteralConfigMap(name string) *corev1.ConfigMap { +func makeLiteralConfigMap(name string, labels, annotations map[string]string) *corev1.ConfigMap { cm := &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{ APIVersion: "v1", @@ -69,7 +69,12 @@ func makeLiteralConfigMap(name string) *corev1.ConfigMap { "d": "true", }, } - cm.SetLabels(map[string]string{"foo": "bar"}) + if labels != nil { + cm.SetLabels(labels) + } + if annotations != nil { + cm.SetAnnotations(annotations) + } return cm } @@ -128,7 +133,49 @@ func TestConstructConfigMap(t *testing.T) { "foo": "bar", }, }, - expected: makeLiteralConfigMap("literalConfigMap"), + expected: makeLiteralConfigMap("literalConfigMap", map[string]string{ + "foo": "bar", + }, nil), + }, + { + description: "construct config map from literal with GeneratorOptions in ConfigMapArgs", + input: types.ConfigMapArgs{ + GeneratorArgs: types.GeneratorArgs{ + Name: "literalConfigMap", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"}, + }, + GeneratorOptions: &types.GeneratorOptions{ + Labels: map[string]string{ + "foo": "changed", + "cat": "dog", + }, + Annotations: map[string]string{ + "foo": "changed", + "cat": "dog", + }, + }, + }, + }, + options: &types.GeneratorOptions{ + Labels: map[string]string{ + "foo": "bar", + }, + Annotations: map[string]string{ + "foo": "bar", + }, + }, + // GeneratorOptions from the ConfigMapArgs take precedence over the + // factory level GeneratorOptions and should overwrite + // labels/annotations set in the factory level if there are common + // labels/annotations + expected: makeLiteralConfigMap("literalConfigMap", map[string]string{ + "foo": "changed", + "cat": "dog", + }, map[string]string{ + "foo": "changed", + "cat": "dog", + }), }, } diff --git a/api/internal/k8sdeps/configmapandsecret/factory.go b/api/internal/k8sdeps/configmapandsecret/factory.go index 3975e2ed6..2576b4449 100644 --- a/api/internal/k8sdeps/configmapandsecret/factory.go +++ b/api/internal/k8sdeps/configmapandsecret/factory.go @@ -4,6 +4,7 @@ package configmapandsecret import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/kustomize/api/ifc" "sigs.k8s.io/kustomize/api/types" ) @@ -20,4 +21,35 @@ func NewFactory( return &Factory{kvLdr: kvLdr, options: o} } +// setLabelsAndAnnnotations will take the labels and annotations from +// global GeneratorOptions and resource level GeneratorOptions and merge them +// with the resource level taking precedence, and then set them on the provided +// obj. +func (f *Factory) setLabelsAndAnnnotations(obj metav1.Object, opts *types.GeneratorOptions) { + labels := make(map[string]string) + annotations := make(map[string]string) + if f.options != nil { + for k, v := range f.options.Labels { + labels[k] = v + } + for k, v := range f.options.Annotations { + annotations[k] = v + } + } + if opts != nil { + for k, v := range opts.Labels { + labels[k] = v + } + for k, v := range opts.Annotations { + annotations[k] = v + } + } + if len(labels) != 0 { + obj.SetLabels(labels) + } + if len(annotations) != 0 { + obj.SetAnnotations(annotations) + } +} + const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v" diff --git a/api/internal/k8sdeps/configmapandsecret/secretfactory.go b/api/internal/k8sdeps/configmapandsecret/secretfactory.go index 6b48a0113..487273620 100644 --- a/api/internal/k8sdeps/configmapandsecret/secretfactory.go +++ b/api/internal/k8sdeps/configmapandsecret/secretfactory.go @@ -39,10 +39,7 @@ func (f *Factory) MakeSecret( return nil, err } } - if f.options != nil { - s.SetLabels(f.options.Labels) - s.SetAnnotations(f.options.Annotations) - } + f.setLabelsAndAnnnotations(s, args.GeneratorOptions) return s, nil } diff --git a/api/internal/k8sdeps/configmapandsecret/secretfactory_test.go b/api/internal/k8sdeps/configmapandsecret/secretfactory_test.go index 76416f886..beb51c7c9 100644 --- a/api/internal/k8sdeps/configmapandsecret/secretfactory_test.go +++ b/api/internal/k8sdeps/configmapandsecret/secretfactory_test.go @@ -51,7 +51,7 @@ BAR=baz } } -func makeLiteralSecret(name string) *corev1.Secret { +func makeLiteralSecret(name string, labels, annotations map[string]string) *corev1.Secret { s := &corev1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: "v1", @@ -66,7 +66,12 @@ func makeLiteralSecret(name string) *corev1.Secret { }, Type: "Opaque", } - s.SetLabels(map[string]string{"foo": "bar"}) + if labels != nil { + s.SetLabels(labels) + } + if annotations != nil { + s.SetAnnotations(annotations) + } return s } @@ -120,7 +125,49 @@ func TestConstructSecret(t *testing.T) { "foo": "bar", }, }, - expected: makeLiteralSecret("literalSecret"), + expected: makeLiteralSecret("literalSecret", map[string]string{ + "foo": "bar", + }, nil), + }, + { + description: "construct secret from literal with GeneratorOptions in SecretArgs", + input: types.SecretArgs{ + GeneratorArgs: types.GeneratorArgs{ + Name: "literalSecret", + KvPairSources: types.KvPairSources{ + LiteralSources: []string{"a=x", "b=y"}, + }, + GeneratorOptions: &types.GeneratorOptions{ + Labels: map[string]string{ + "foo": "changed", + "cat": "dog", + }, + Annotations: map[string]string{ + "foo": "changed", + "cat": "dog", + }, + }, + }, + }, + options: &types.GeneratorOptions{ + Labels: map[string]string{ + "foo": "bar", + }, + Annotations: map[string]string{ + "foo": "bar", + }, + }, + // GeneratorOptions from the SecretArgs take precedence over the + // factory level GeneratorOptions and should overwrite + // labels/annotations set in the factory level if there are common + // labels/annotations + expected: makeLiteralSecret("literalSecret", map[string]string{ + "foo": "changed", + "cat": "dog", + }, map[string]string{ + "foo": "changed", + "cat": "dog", + }), }, } diff --git a/api/types/generatorargs.go b/api/types/generatorargs.go index 6b06ac9d5..22f64d505 100644 --- a/api/types/generatorargs.go +++ b/api/types/generatorargs.go @@ -21,4 +21,7 @@ type GeneratorArgs struct { // KvPairSources for the generator. KvPairSources `json:",inline,omitempty" yaml:",inline,omitempty"` + + // GeneratorOptions modify this generator + GeneratorOptions *GeneratorOptions `json:"generatorOptions,omitempty" yaml:"generatorOptions,omitempty"` }