diff --git a/functions/go/set-labels/README.md b/functions/go/set-labels/README.md index a0cda80c6..854d9f363 100644 --- a/functions/go/set-labels/README.md +++ b/functions/go/set-labels/README.md @@ -72,6 +72,25 @@ labels: fruit: apple ``` +The `set-labels` function adds the desired labels to more fields than just the one +found in `.metadata`. For example, the `Deployment` resource has a `spec.selector`, +which gets updated by the `set-labels` function by default. This is not always desired. + +To disable updating of `.spec.selectors`, define a `SetLabels` custom resource, and set +`.options.setSelectorLabels` to `false` like so: + +```yaml +apiVersion: fn.kpt.dev/v1alpha1 +kind: SetLabels +metadata: + name: my-config +labels: + color: orange + fruit: apple +options: + setSelectorLabels: false # default is true +``` + [labels]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ diff --git a/functions/go/set-labels/generated/docs.go b/functions/go/set-labels/generated/docs.go index 70f7e92fc..fd6ed05d1 100644 --- a/functions/go/set-labels/generated/docs.go +++ b/functions/go/set-labels/generated/docs.go @@ -44,4 +44,21 @@ following ` + "`" + `functionConfig` + "`" + `: labels: color: orange fruit: apple + +The ` + "`" + `set-labels` + "`" + ` function adds the desired labels to more fields than just the one +found in ` + "`" + `.metadata` + "`" + `. For example, the ` + "`" + `Deployment` + "`" + ` resource has a ` + "`" + `spec.selector` + "`" + `, +which gets updated by the ` + "`" + `set-labels` + "`" + ` function by default. This is not always desired. + +To disable updating of ` + "`" + `.spec.selectors` + "`" + `, define a ` + "`" + `SetLabels` + "`" + ` custom resource, and set +` + "`" + `.options.setSelectorLabels` + "`" + ` to ` + "`" + `false` + "`" + ` like so: + + apiVersion: fn.kpt.dev/v1alpha1 + kind: SetLabels + metadata: + name: my-config + labels: + color: orange + fruit: apple + options: + setSelectorLabels: false # default is true ` diff --git a/functions/go/set-labels/run.go b/functions/go/set-labels/run.go index 4af3636e5..ce339a05a 100644 --- a/functions/go/set-labels/run.go +++ b/functions/go/set-labels/run.go @@ -24,7 +24,18 @@ import ( ) func NewTransformer() fn.ResourceListProcessor { - return fn.WithContext(fn.Context{Context: context.Background()}, &setlabels.SetLabels{}) + // Create a new SetLabels struct + labels := make(map[string]string) + options := map[string]bool{ + "setSelectorLabels": true, + } + setLabels := &setlabels.SetLabels{ + Labels: labels, + Options: options, + } + + // Return the SetLabels struct as a fn.ResourceListProcessor + return fn.WithContext(fn.Context{Context: context.Background()}, setLabels) } func run() error { diff --git a/functions/go/set-labels/setlabels/transformer.go b/functions/go/set-labels/setlabels/transformer.go index 7915a8db2..29436cceb 100644 --- a/functions/go/set-labels/setlabels/transformer.go +++ b/functions/go/set-labels/setlabels/transformer.go @@ -20,8 +20,12 @@ var _ fn.Runner = &SetLabels{} // SetLabels supports the set-labels workflow, it uses Config to parse functionConfig, Transform to change the labels type SetLabels struct { // labels is the desired labels - Labels map[string]string `json:"labels,omitempty"` - count int + Labels map[string]string `json:"labels,omitempty"` + + // options is the configurable and optional options + Options map[string]bool `json:"options,omitempty"` + + count int } // EmptyfnConfig is a workaround since kpt creates a FunctionConfig placeholder if users don't provide the functionConfig. @@ -161,6 +165,11 @@ func hasSpecSelector(o *fn.KubeObject) bool { // setLabelsInSelector set labels for all selectors, including spec selector map, spec selector LabelSelector, LabelSelector in JobTemplate, and podSelector in NetworkPolicy, and func (p *SetLabels) setLabelsInSelector(o *fn.KubeObject) error { + // setSelectorLabels is true by default + if !p.Options["setSelectorLabels"] { + return nil + } + if hasSpecSelector(o) { fieldPath := FieldPath{"spec", "selector"} if err := p.updateLabels(&o.SubObject, fieldPath, p.Labels, true); err != nil { diff --git a/tests/set-labels/deployment/.expected/diff.patch b/tests/set-labels/deployment/.expected/diff.patch new file mode 100644 index 000000000..714c8fb0b --- /dev/null +++ b/tests/set-labels/deployment/.expected/diff.patch @@ -0,0 +1,78 @@ +diff --git a/Kptfile b/Kptfile +index ad493d3..917ae02 100644 +--- a/Kptfile ++++ b/Kptfile +@@ -17,4 +17,4 @@ pipeline: + - image: gcr.io/kpt-fn/set-labels:unstable + configPath: fn-config-selector-labels-undefined.yaml + selectors: +- - name: the-deployment-selector-labels-undefined +\ No newline at end of file ++ - name: the-deployment-selector-labels-undefined +diff --git a/deployment.yaml b/deployment.yaml +index 11be507..b03ae0a 100644 +--- a/deployment.yaml ++++ b/deployment.yaml +@@ -4,6 +4,8 @@ metadata: + name: the-deployment-selector-labels-false + labels: + app: the-deployment ++ color: orange ++ fruit: apple + spec: + selector: + matchLabels: +@@ -12,6 +14,8 @@ spec: + metadata: + labels: + app: the-deployment ++ color: orange ++ fruit: apple + spec: + containers: + - name: the-container +@@ -23,14 +27,20 @@ metadata: + name: the-deployment-selector-labels-true + labels: + app: the-deployment ++ color: orange ++ fruit: apple + spec: + selector: + matchLabels: + app: the-deployment ++ color: orange ++ fruit: apple + template: + metadata: + labels: + app: the-deployment ++ color: orange ++ fruit: apple + spec: + containers: + - name: the-container +@@ -42,15 +52,21 @@ metadata: + name: the-deployment-selector-labels-undefined + labels: + app: the-deployment ++ color: orange ++ fruit: apple + spec: + selector: + matchLabels: + app: the-deployment ++ color: orange ++ fruit: apple + template: + metadata: + labels: + app: the-deployment ++ color: orange ++ fruit: apple + spec: + containers: + - name: the-container +- image: the-image +\ No newline at end of file ++ image: the-image diff --git a/tests/set-labels/deployment/.expected/results.yaml b/tests/set-labels/deployment/.expected/results.yaml new file mode 100644 index 000000000..a67954fc9 --- /dev/null +++ b/tests/set-labels/deployment/.expected/results.yaml @@ -0,0 +1,21 @@ +apiVersion: kpt.dev/v1 +kind: FunctionResultList +metadata: + name: fnresults +exitCode: 0 +items: + - image: gcr.io/kpt-fn/set-labels:unstable + exitCode: 0 + results: + - message: set 4 labels in total + severity: info + - image: gcr.io/kpt-fn/set-labels:unstable + exitCode: 0 + results: + - message: set 6 labels in total + severity: info + - image: gcr.io/kpt-fn/set-labels:unstable + exitCode: 0 + results: + - message: set 6 labels in total + severity: info diff --git a/tests/set-labels/deployment/.krmignore b/tests/set-labels/deployment/.krmignore new file mode 100644 index 000000000..9d7a4007d --- /dev/null +++ b/tests/set-labels/deployment/.krmignore @@ -0,0 +1 @@ +.expected diff --git a/tests/set-labels/deployment/Kptfile b/tests/set-labels/deployment/Kptfile new file mode 100644 index 000000000..917ae025f --- /dev/null +++ b/tests/set-labels/deployment/Kptfile @@ -0,0 +1,20 @@ +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: example + annotations: + config.kubernetes.io/local-config: "true" +pipeline: + mutators: + - image: gcr.io/kpt-fn/set-labels:unstable + configPath: fn-config-selector-labels-false.yaml + selectors: + - name: the-deployment-selector-labels-false + - image: gcr.io/kpt-fn/set-labels:unstable + configPath: fn-config-selector-labels-true.yaml + selectors: + - name: the-deployment-selector-labels-true + - image: gcr.io/kpt-fn/set-labels:unstable + configPath: fn-config-selector-labels-undefined.yaml + selectors: + - name: the-deployment-selector-labels-undefined diff --git a/tests/set-labels/deployment/deployment.yaml b/tests/set-labels/deployment/deployment.yaml new file mode 100644 index 000000000..11be507b5 --- /dev/null +++ b/tests/set-labels/deployment/deployment.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: the-deployment-selector-labels-false + labels: + app: the-deployment +spec: + selector: + matchLabels: + app: the-deployment + template: + metadata: + labels: + app: the-deployment + spec: + containers: + - name: the-container + image: the-image +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: the-deployment-selector-labels-true + labels: + app: the-deployment +spec: + selector: + matchLabels: + app: the-deployment + template: + metadata: + labels: + app: the-deployment + spec: + containers: + - name: the-container + image: the-image +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: the-deployment-selector-labels-undefined + labels: + app: the-deployment +spec: + selector: + matchLabels: + app: the-deployment + template: + metadata: + labels: + app: the-deployment + spec: + containers: + - name: the-container + image: the-image \ No newline at end of file diff --git a/tests/set-labels/deployment/fn-config-selector-labels-false.yaml b/tests/set-labels/deployment/fn-config-selector-labels-false.yaml new file mode 100644 index 000000000..ec41199be --- /dev/null +++ b/tests/set-labels/deployment/fn-config-selector-labels-false.yaml @@ -0,0 +1,11 @@ +apiVersion: fn.kpt.dev/v1alpha1 +kind: SetLabels +metadata: + name: my-config + annotations: + config.kubernetes.io/local-config: "true" +labels: + color: orange + fruit: apple +options: + setSelectorLabels: false diff --git a/tests/set-labels/deployment/fn-config-selector-labels-true.yaml b/tests/set-labels/deployment/fn-config-selector-labels-true.yaml new file mode 100644 index 000000000..78f5dd4f4 --- /dev/null +++ b/tests/set-labels/deployment/fn-config-selector-labels-true.yaml @@ -0,0 +1,11 @@ +apiVersion: fn.kpt.dev/v1alpha1 +kind: SetLabels +metadata: + name: my-config + annotations: + config.kubernetes.io/local-config: "true" +labels: + color: orange + fruit: apple +options: + setSelectorLabels: true diff --git a/tests/set-labels/deployment/fn-config-selector-labels-undefined.yaml b/tests/set-labels/deployment/fn-config-selector-labels-undefined.yaml new file mode 100644 index 000000000..bb7dd7a79 --- /dev/null +++ b/tests/set-labels/deployment/fn-config-selector-labels-undefined.yaml @@ -0,0 +1,9 @@ +apiVersion: fn.kpt.dev/v1alpha1 +kind: SetLabels +metadata: + name: my-config + annotations: + config.kubernetes.io/local-config: "true" +labels: + color: orange + fruit: apple