diff --git a/api/internal/target/kusttarget_configplugin.go b/api/internal/target/kusttarget_configplugin.go index 0cf629b82..712b0cc6a 100644 --- a/api/internal/target/kusttarget_configplugin.go +++ b/api/internal/target/kusttarget_configplugin.go @@ -223,6 +223,31 @@ var transformerConfigurators = map[builtinhelpers.BuiltinPluginType]func( builtinhelpers.LabelTransformer: func( kt *KustTarget, bpt builtinhelpers.BuiltinPluginType, f tFactory, tc *builtinconfig.TransformerConfig) ( result []resmap.Transformer, err error) { + for _, label := range kt.kustomization.Labels { + var c struct { + Labels map[string]string + FieldSpecs []types.FieldSpec + } + c.Labels = label.Pairs + fss := types.FsSlice(label.FieldSpecs) + // merge the custom fieldSpecs with the default + if label.IncludeSelectors { + fss, err = fss.MergeAll(tc.CommonLabels) + } else { + // only add to metadata by default + fss, err = fss.MergeOne(types.FieldSpec{Path: "metadata/labels", CreateIfNotPresent: true}) + } + if err != nil { + return nil, err + } + c.FieldSpecs = fss + p := f() + err = kt.configureBuiltinPlugin(p, c, bpt) + if err != nil { + return nil, err + } + result = append(result, p) + } var c struct { Labels map[string]string FieldSpecs []types.FieldSpec diff --git a/api/krusty/inlinelabels_test.go b/api/krusty/inlinelabels_test.go new file mode 100644 index 000000000..889692418 --- /dev/null +++ b/api/krusty/inlinelabels_test.go @@ -0,0 +1,93 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package krusty_test + +import ( + "testing" + + kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" +) + +const resources string = `apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-deployment +spec: + template: + spec: + containers: + - name: my-deployment + livenessProbe: + httpGet: + path: /healthz + port: 8080 +--- +apiVersion: example.dev/v1 +kind: MyCRD +metadata: + name: crd +` + +func TestKustomizationLabels(t *testing.T) { + th := kusttest_test.MakeHarness(t) + makeResourcesForPatchTest(th) + th.WriteK("/app", ` +resources: +- deployment.yaml + +labels: +- pairs: + foo: bar +- pairs: + a: b + includeSelectors: true +- pairs: + c: d + fields: + - path: spec/selector + group: example.dev + version: v1 + kind: MyCRD + create: true +`) + th.WriteF("/app/deployment.yaml", resources) + m := th.Run("/app", th.MakeDefaultOptions()) + th.AssertActualEqualsExpected(m, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + a: b + c: d + foo: bar + name: my-deployment +spec: + selector: + matchLabels: + a: b + template: + metadata: + labels: + a: b + spec: + containers: + - livenessProbe: + httpGet: + path: /healthz + port: 8080 + name: my-deployment +--- +apiVersion: example.dev/v1 +kind: MyCRD +metadata: + labels: + a: b + c: d + foo: bar + name: crd +spec: + selector: + c: d +`) +} diff --git a/api/types/kustomization.go b/api/types/kustomization.go index 30f0e4b2e..da019f075 100644 --- a/api/types/kustomization.go +++ b/api/types/kustomization.go @@ -46,6 +46,9 @@ type Kustomization struct { // CommonLabels to add to all objects and selectors. CommonLabels map[string]string `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"` + // Labels to add to all objects but not selectors. + Labels []Label `json:"labels,omitempty" yaml:"labels,omitempty"` + // CommonAnnotations to add to all objects. CommonAnnotations map[string]string `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"` @@ -190,6 +193,11 @@ func (k *Kustomization) FixKustomizationPreMarshalling() { // PatchesJson6902 should be under the Patches field. k.Patches = append(k.Patches, k.PatchesJson6902...) k.PatchesJson6902 = nil + + if l := labelFromCommonLabels(k.CommonLabels); l != nil { + k.Labels = append(k.Labels, *l) + k.CommonLabels = nil + } } func (k *Kustomization) EnforceFields() []string { diff --git a/api/types/kustomization_test.go b/api/types/kustomization_test.go index 1374df5b4..74101b1ab 100644 --- a/api/types/kustomization_test.go +++ b/api/types/kustomization_test.go @@ -22,6 +22,9 @@ func TestFixKustomizationPostUnmarshalling(t *testing.T) { EnvSource: "c", }, }}} + k.CommonLabels = map[string]string{ + "foo": "bar", + } k.FixKustomizationPostUnmarshalling() expected := Kustomization{ @@ -35,6 +38,9 @@ func TestFixKustomizationPostUnmarshalling(t *testing.T) { EnvSources: []string{"a", "b", "c"}, }, }}}, + CommonLabels: map[string]string{ + "foo": "bar", + }, } if !reflect.DeepEqual(k, expected) { t.Fatalf("unexpected output: %v", k) diff --git a/api/types/labels.go b/api/types/labels.go new file mode 100644 index 000000000..e2a2aee78 --- /dev/null +++ b/api/types/labels.go @@ -0,0 +1,25 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package types + +type Label struct { + // Pairs contains the key-value pairs for labels to add + Pairs map[string]string `json:"pairs,omitempty" yaml:"pairs,omitempty"` + // IncludeSelectors inidicates should transformer include the + // fieldSpecs for selectors. Custom fieldSpecs specified by + // FieldSpecs will be merged with builtin fieldSpecs if this + // is true. + IncludeSelectors bool `json:"includeSelectors,omitempty" yaml:"includeSelectors,omitempty"` + FieldSpecs []FieldSpec `json:"fields,omitempty" yaml:"fields,omitempty"` +} + +func labelFromCommonLabels(commonLabels map[string]string) *Label { + if len(commonLabels) == 0 { + return nil + } + return &Label{ + Pairs: commonLabels, + IncludeSelectors: true, + } +} diff --git a/kustomize/commands/edit/fix/fix_test.go b/kustomize/commands/edit/fix/fix_test.go index dda973cde..c3195b9c7 100644 --- a/kustomize/commands/edit/fix/fix_test.go +++ b/kustomize/commands/edit/fix/fix_test.go @@ -133,3 +133,45 @@ kind: Kustomization t.Errorf("Mismatch (-expected, +actual):\n%s", diff) } } + +func TestFixOutdatedCommonLabels(t *testing.T) { + kustomizationContentWithOutdatedCommonLabels := []byte(` +commonLabels: + foo: bar +labels: +- pairs: + a: b +`) + + expected := []byte(` +labels: +- pairs: + a: b +- includeSelectors: true + pairs: + foo: bar +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +`) + fSys := filesys.MakeFsInMemory() + testutils_test.WriteTestKustomizationWith(fSys, kustomizationContentWithOutdatedCommonLabels) + cmd := NewCmdFix(fSys) + err := cmd.RunE(cmd, nil) + if err != nil { + t.Errorf("unexpected cmd error: %v", err) + } + content, err := testutils_test.ReadTestKustomization(fSys) + if err != nil { + t.Errorf("unexpected read error: %v", err) + } + if !strings.Contains(string(content), "apiVersion: ") { + t.Errorf("expected apiVersion in kustomization") + } + if !strings.Contains(string(content), "kind: Kustomization") { + t.Errorf("expected kind in kustomization") + } + + if diff := cmp.Diff(expected, content); diff != "" { + t.Errorf("Mismatch (-expected, +actual):\n%s", diff) + } +} diff --git a/kustomize/commands/internal/kustfile/kustomizationfile.go b/kustomize/commands/internal/kustfile/kustomizationfile.go index ed5f9d25d..8b6ecdfb4 100644 --- a/kustomize/commands/internal/kustfile/kustomizationfile.go +++ b/kustomize/commands/internal/kustfile/kustomizationfile.go @@ -46,6 +46,7 @@ func determineFieldOrder() []string { "Namespace", "Crds", "CommonLabels", + "Labels", "CommonAnnotations", "PatchesStrategicMerge", "PatchesJson6902", diff --git a/kustomize/commands/internal/kustfile/kustomizationfile_test.go b/kustomize/commands/internal/kustfile/kustomizationfile_test.go index 44c4a4e78..428c74a53 100644 --- a/kustomize/commands/internal/kustfile/kustomizationfile_test.go +++ b/kustomize/commands/internal/kustfile/kustomizationfile_test.go @@ -28,6 +28,7 @@ func TestFieldOrder(t *testing.T) { "Namespace", "Crds", "CommonLabels", + "Labels", "CommonAnnotations", "PatchesStrategicMerge", "PatchesJson6902",