diff --git a/api/v1beta1/kustomization_types.go b/api/v1beta1/kustomization_types.go index f2c0c8ec..8d6a2e8a 100644 --- a/api/v1beta1/kustomization_types.go +++ b/api/v1beta1/kustomization_types.go @@ -83,6 +83,10 @@ type KustomizationSpec struct { // +optional HealthChecks []meta.NamespacedObjectKindReference `json:"healthChecks,omitempty"` + // Patches (also called overlays), defined as inline YAML objects. + // +optional + Patches []kustomize.Patch `json:"patches,omitempty"` + // Strategic merge patches, defined as inline YAML objects. // +optional PatchesStrategicMerge []apiextensionsv1.JSON `json:"patchesStrategicMerge,omitempty"` diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 74448f61..933861a7 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -173,6 +173,11 @@ func (in *KustomizationSpec) DeepCopyInto(out *KustomizationSpec) { *out = make([]meta.NamespacedObjectKindReference, len(*in)) copy(*out, *in) } + if in.Patches != nil { + in, out := &in.Patches, &out.Patches + *out = make([]kustomize.Patch, len(*in)) + copy(*out, *in) + } if in.PatchesStrategicMerge != nil { in, out := &in.PatchesStrategicMerge, &out.PatchesStrategicMerge *out = make([]apiextensionsv1.JSON, len(*in)) diff --git a/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml b/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml index c3890d06..2e9147c6 100644 --- a/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml +++ b/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml @@ -142,6 +142,41 @@ spec: - name type: object type: object + patches: + description: Patches (also called overlays), defined as inline YAML objects. + items: + description: Patch contains either a StrategicMerge or a JSON6902 patch, either a file or inline, and the target the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources from. Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. Together with Group and Version it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources from. Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + type: object + type: array patchesJson6902: description: JSON 6902 patches, defined as inline YAML objects. items: diff --git a/controllers/kustomization_controller_patch_test.go b/controllers/kustomization_controller_patch_test.go index b890d419..039e3f97 100644 --- a/controllers/kustomization_controller_patch_test.go +++ b/controllers/kustomization_controller_patch_test.go @@ -144,10 +144,62 @@ var _ = Describe("KustomizationReconciler", func() { Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal("ghcr.io/stefanprodan/podinfo:5.2.0")) }) + It("patches as JSON", func() { + kustomization.Spec.Patches = []kustomize.Patch{ + { + Patch: ` +- op: add + path: /metadata/labels/patch + value: inline-json + `, + Target: kustomize.Selector{ + LabelSelector: "app=podinfo", + }, + }, + } + Expect(k8sClient.Create(context.TODO(), kustomization)).To(Succeed()) + + Eventually(func() bool { + var obj kustomizev1.Kustomization + _ = k8sClient.Get(context.Background(), ObjectKey(kustomization), &obj) + return obj.Status.LastAppliedRevision == "main/"+artifactChecksum + }, timeout, time.Second).Should(BeTrue()) + + var deployment appsv1.Deployment + Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) + Expect(deployment.ObjectMeta.Labels["patch"]).To(Equal("inline-json")) + }) + + It("patches as YAML", func() { + kustomization.Spec.Patches = []kustomize.Patch{ + { + Patch: ` +apiVersion: v1 +kind: Pod +metadata: + name: podinfo + labels: + patch: inline-yaml + `, + }, + } + Expect(k8sClient.Create(context.TODO(), kustomization)).To(Succeed()) + + Eventually(func() bool { + var obj kustomizev1.Kustomization + _ = k8sClient.Get(context.Background(), ObjectKey(kustomization), &obj) + return obj.Status.LastAppliedRevision == "main/"+artifactChecksum + }, timeout, time.Second).Should(BeTrue()) + + var deployment appsv1.Deployment + Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) + Expect(deployment.ObjectMeta.Labels["patch"]).To(Equal("inline-yaml")) + }) + It("strategic merge patches", func() { kustomization.Spec.PatchesStrategicMerge = []apiextensionsv1.JSON{ { - Raw: []byte(`{"kind":"Deployment","apiVersion":"apps/v1","metadata":{"name":"podinfo","labels":{"xxxx":"yyyy"}}}`), + Raw: []byte(`{"kind":"Deployment","apiVersion":"apps/v1","metadata":{"name":"podinfo","labels":{"patch":"strategic-merge"}}}`), }, } Expect(k8sClient.Create(context.TODO(), kustomization)).To(Succeed()) @@ -160,15 +212,14 @@ var _ = Describe("KustomizationReconciler", func() { var deployment appsv1.Deployment Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) - Expect(deployment.ObjectMeta.Labels["xxxx"]).To(Equal("yyyy")) + Expect(deployment.ObjectMeta.Labels["patch"]).To(Equal("strategic-merge")) }) It("JSON6902 patches", func() { kustomization.Spec.PatchesJSON6902 = []kustomize.JSON6902Patch{ { - Patch: []kustomize.JSON6902{ - {Op: "add", Path: "/metadata/labels/yyyy", Value: &apiextensionsv1.JSON{Raw: []byte(`"xxxx"`)}}, + {Op: "add", Path: "/metadata/labels/patch", Value: &apiextensionsv1.JSON{Raw: []byte(`"json6902"`)}}, {Op: "replace", Path: "/spec/replicas", Value: &apiextensionsv1.JSON{Raw: []byte("2")}}, }, Target: kustomize.Selector{ @@ -189,7 +240,7 @@ var _ = Describe("KustomizationReconciler", func() { var deployment appsv1.Deployment Expect(k8sClient.Get(context.TODO(), client.ObjectKey{Name: "podinfo", Namespace: namespace.Name}, &deployment)).To(Succeed()) - Expect(deployment.ObjectMeta.Labels["yyyy"]).To(Equal("xxxx")) + Expect(deployment.ObjectMeta.Labels["patch"]).To(Equal("json6902")) Expect(*deployment.Spec.Replicas).To(Equal(int32(2))) }) }) diff --git a/controllers/kustomization_generator.go b/controllers/kustomization_generator.go index 7c47114e..a1c5973f 100644 --- a/controllers/kustomization_generator.go +++ b/controllers/kustomization_generator.go @@ -104,6 +104,13 @@ func (kg *KustomizeGenerator) WriteFile(ctx context.Context, dirPath string) (st kus.Namespace = kg.kustomization.Spec.TargetNamespace } + for _, m := range kg.kustomization.Spec.Patches { + kus.Patches = append(kus.Patches, kustypes.Patch{ + Patch: m.Patch, + Target: adaptSelector(&m.Target), + }) + } + for _, m := range kg.kustomization.Spec.PatchesStrategicMerge { kus.PatchesStrategicMerge = append(kus.PatchesStrategicMerge, kustypes.PatchStrategicMerge(m.Raw)) } diff --git a/docs/api/kustomize.md b/docs/api/kustomize.md index 84f1cb06..5ccdfec9 100644 --- a/docs/api/kustomize.md +++ b/docs/api/kustomize.md @@ -198,6 +198,20 @@ bool
patches
Patches (also called overlays), defined as inline YAML objects.
+patchesStrategicMerge
patches
Patches (also called overlays), defined as inline YAML objects.
+patchesStrategicMerge