Support targeted Patches in the PostRenderer specification.

Signed-off-by: Tomek Rękawek <rekawek@adobe.com>
This commit is contained in:
Tomek Rękawek 2022-03-10 09:51:50 +01:00
parent b0019bc943
commit 5b1b1ce642
7 changed files with 170 additions and 2 deletions

View File

@ -35,6 +35,11 @@ const HelmReleaseFinalizer = "finalizers.fluxcd.io"
// Kustomize Helm PostRenderer specification. // Kustomize Helm PostRenderer specification.
type Kustomize struct { type Kustomize struct {
// Strategic merge and JSON patches, defined as inline YAML objects,
// capable of targeting objects based on kind, label and annotation selectors.
// +optional
Patches []kustomize.Patch `json:"patches,omitempty"`
// Strategic merge patches, defined as inline YAML objects. // Strategic merge patches, defined as inline YAML objects.
// +optional // +optional
PatchesStrategicMerge []apiextensionsv1.JSON `json:"patchesStrategicMerge,omitempty"` PatchesStrategicMerge []apiextensionsv1.JSON `json:"patchesStrategicMerge,omitempty"`

View File

@ -316,6 +316,11 @@ func (in *KubeConfig) DeepCopy() *KubeConfig {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Kustomize) DeepCopyInto(out *Kustomize) { func (in *Kustomize) DeepCopyInto(out *Kustomize) {
*out = *in *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 { if in.PatchesStrategicMerge != nil {
in, out := &in.PatchesStrategicMerge, &out.PatchesStrategicMerge in, out := &in.PatchesStrategicMerge, &out.PatchesStrategicMerge
*out = make([]v1.JSON, len(*in)) *out = make([]v1.JSON, len(*in))

View File

@ -299,6 +299,61 @@ spec:
- name - name
type: object type: object
type: array type: array
patches:
description: Strategic merge and JSON patches, defined as
inline YAML objects, capable of targeting objects based
on kind, label and annotation selectors.
items:
description: Patch contains an inline StrategicMerge or
JSON6902 patch, and the target the patch should be applied
to.
properties:
patch:
description: Patch contains an inline StrategicMerge
patch or an inline JSON6902 patch 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: patchesJson6902:
description: JSON 6902 patches, defined as inline YAML objects. description: JSON 6902 patches, defined as inline YAML objects.
items: items:

View File

@ -1427,6 +1427,21 @@ the HelmRelease.</p>
<tbody> <tbody>
<tr> <tr>
<td> <td>
<code>patches</code><br>
<em>
<a href="https://godoc.org/github.com/fluxcd/pkg/apis/kustomize#Patch">
[]github.com/fluxcd/pkg/apis/kustomize.Patch
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Strategic merge and JSON patches, defined as inline YAML objects,
capable of targeting objects based on kind, label and annotation selectors.</p>
</td>
</tr>
<tr>
<td>
<code>patchesStrategicMerge</code><br> <code>patchesStrategicMerge</code><br>
<em> <em>
<a href="https://pkg.go.dev/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1?tab=doc#JSON"> <a href="https://pkg.go.dev/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1?tab=doc#JSON">

View File

@ -1149,6 +1149,7 @@ HelmRelease resources has a built-in [Kustomize](https://kubectl.docs.kubernetes
compatible [Post Renderer](https://helm.sh/docs/topics/advanced/#post-rendering), which provides compatible [Post Renderer](https://helm.sh/docs/topics/advanced/#post-rendering), which provides
the following Kustomize directives: the following Kustomize directives:
- [patches](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/)
- [patchesStrategicMerge](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/) - [patchesStrategicMerge](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/)
- [patchesJson6902](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/) - [patchesJson6902](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/)
- [images](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/) - [images](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/)

View File

@ -105,6 +105,14 @@ func (k *postRendererKustomize) Run(renderedManifests *bytes.Buffer) (modifiedMa
return nil, err return nil, err
} }
// Add patches.
for _, m := range k.spec.Patches {
cfg.Patches = append(cfg.Patches, kustypes.Patch{
Patch: m.Patch,
Target: adaptSelector(&m.Target),
})
}
// Add strategic merge patches. // Add strategic merge patches.
for _, m := range k.spec.PatchesStrategicMerge { for _, m := range k.spec.PatchesStrategicMerge {
cfg.PatchesStrategicMerge = append(cfg.PatchesStrategicMerge, kustypes.PatchStrategicMerge(m.Raw)) cfg.PatchesStrategicMerge = append(cfg.PatchesStrategicMerge, kustypes.PatchStrategicMerge(m.Raw))

View File

@ -63,6 +63,7 @@ func Test_postRendererKustomize_Run(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
renderedManifests string renderedManifests string
patches string
patchesStrategicMerge string patchesStrategicMerge string
patchesJson6902 string patchesJson6902 string
images string images string
@ -146,6 +147,42 @@ spec:
`, `,
expectManifests: `apiVersion: v1 expectManifests: `apiVersion: v1
kind: Pod kind: Pod
metadata:
annotations:
d: "42"
e: "42"
name: json6902
`,
},
{
name: "targeted json 6902",
renderedManifests: json6902Mock,
patches: `
- target:
version: v1
kind: Pod
name: json6902
patch: |
- op: test
path: /metadata/annotations/c
value: foo
- op: remove
path: /metadata/annotations/c
- op: add
path: /metadata/annotations/c
value: [ "foo", "bar" ]
- op: replace
path: /metadata/annotations/c
value: 42
- op: move
from: /metadata/annotations/c
path: /metadata/annotations/d
- op: copy
from: /metadata/annotations/d
path: /metadata/annotations/e
`,
expectManifests: `apiVersion: v1
kind: Pod
metadata: metadata:
annotations: annotations:
d: "42" d: "42"
@ -170,6 +207,39 @@ metadata:
`, `,
expectManifests: `apiVersion: apps/v1 expectManifests: `apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- image: nignx:latest
name: nginx
`,
},
{
name: "targeted strategic merge test",
renderedManifests: strategicMergeMock,
patches: `
- target:
group: apps
version: v1
kind: Deployment
name: nginx
patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
image: nignx:latest
`,
expectManifests: `apiVersion: apps/v1
kind: Deployment
metadata: metadata:
name: nginx name: nginx
spec: spec:
@ -183,7 +253,11 @@ spec:
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
spec, err := mockKustomize(tt.patchesStrategicMerge, tt.patchesJson6902, tt.images) spec, err := mockKustomize(tt.patches, tt.patchesStrategicMerge, tt.patchesJson6902, tt.images)
if err != nil {
t.Errorf("Run() mockKustomize returned %v", err)
return
}
k := &postRendererKustomize{ k := &postRendererKustomize{
spec: spec, spec: spec,
} }
@ -199,7 +273,11 @@ spec:
} }
} }
func mockKustomize(patchesStrategicMerge, patchesJson6902, images string) (*v2.Kustomize, error) { func mockKustomize(patches, patchesStrategicMerge, patchesJson6902, images string) (*v2.Kustomize, error) {
var targeted []kustomize.Patch
if err := yaml.Unmarshal([]byte(patches), &targeted); err != nil {
return nil, err
}
b, err := yaml.YAMLToJSON([]byte(patchesStrategicMerge)) b, err := yaml.YAMLToJSON([]byte(patchesStrategicMerge))
if err != nil { if err != nil {
return nil, err return nil, err
@ -217,6 +295,7 @@ func mockKustomize(patchesStrategicMerge, patchesJson6902, images string) (*v2.K
return nil, err return nil, err
} }
return &v2.Kustomize{ return &v2.Kustomize{
Patches: targeted,
PatchesStrategicMerge: strategicMerge, PatchesStrategicMerge: strategicMerge,
PatchesJSON6902: json6902, PatchesJSON6902: json6902,
Images: imgs, Images: imgs,