1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

fix: deepcopy patched resource in foreach mutate (#10252)

* fix: deepcopy patched resource to avoid indirect reversal of its elements

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* fix: copy elements while reversing

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* fix: copy resources inside foreach

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* add test

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add test

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

---------

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
Signed-off-by: Jim Bugwadia <jim@nirmata.com>
Co-authored-by: Jim Bugwadia <jim@nirmata.com>
This commit is contained in:
Vishal Choudhary 2024-05-20 12:15:21 +05:30 committed by GitHub
parent 1302004bc2
commit 3af0e461f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 154 additions and 5 deletions

View file

@ -66,6 +66,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F
defer f.policyContext.JSONContext().Restore()
patchedResource := f.resource
patchedResource.unstructured = *f.resource.unstructured.DeepCopy()
reverse := false
// if it's a patch strategic merge, reverse by default
@ -76,7 +77,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F
reverse = *foreach.Order == kyvernov1.Descending
}
if reverse {
engineutils.InvertedElement(elements)
elements = engineutils.InvertElements(elements)
}
for index, element := range elements {

View file

@ -23,11 +23,14 @@ func EvaluateList(jmesPath string, ctx enginecontext.EvalInterface) ([]interface
return l, nil
}
// InvertedElement inverted the order of element for patchStrategicMerge policies as kustomize patch revering the order of patch resources.
func InvertedElement(elements []interface{}) {
for i, j := 0, len(elements)-1; i < j; i, j = i+1, j-1 {
elements[i], elements[j] = elements[j], elements[i]
// InvertElements inverts the order of elements for patchStrategicMerge policies
// as kustomize patch reverses the order of patch resources.
func InvertElements(elements []interface{}) []interface{} {
elementsCopy := make([]interface{}, len(elements))
for i := range elements {
elementsCopy[i] = elements[len(elements)-i-1]
}
return elementsCopy
}
func AddElementToContext(ctx engineapi.PolicyContext, element interface{}, index, nesting int, elementScope *bool) error {

View file

@ -0,0 +1,16 @@
package utils
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_InvertElements(t *testing.T) {
elems := []interface{}{"a", "b", "c"}
elemsInverted := InvertElements(elems)
assert.Equal(t, "a", elemsInverted[2])
assert.Equal(t, "b", elemsInverted[1])
assert.Equal(t, "c", elemsInverted[0])
}

View file

@ -0,0 +1,6 @@
## Description
This test creates two `Pod`s: trigger and target. The policy updates the image of the third container in the target pod whemn the trigger pod is created.
## Expected Behavior
When the trigger pod is applied the, image in container3 of target pod changes

View file

@ -0,0 +1,35 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: descending-patchjson
spec:
steps:
- name: step-01
try:
- apply:
file: policy.yaml
- name: step-01-assert
try:
- assert:
file: policy-assert.yaml
- name: step-02
try:
- apply:
file: target-pod.yaml
- name: step-02-assert
try:
- assert:
file: target-pod-assert.yaml
- name: step-03
try:
- apply:
file: trigger-pod.yaml
- name: step-03-assert
try:
- assert:
file: trigger-pod-assert.yaml
- name: step-04
try:
- assert:
file: target-pod-updated.yaml

View file

@ -0,0 +1,5 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: descending-jsonpatch

View file

@ -0,0 +1,34 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: descending-jsonpatch
spec:
background: false
schemaValidation: false
rules:
- name: remove-elements
match:
all:
- resources:
kinds:
- Pod
names:
- trigger-pod
mutate:
targets:
- apiVersion: v1
kind: Pod
name: target-pod
namespace: default
foreach:
- list: "target.spec.containers"
order: Descending
preconditions:
all:
- key: "{{ element.name }}"
operator: Equals
value: container3
patchesJson6902: |-
- op: replace
path: /spec/containers/{{elementIndex}}/image
value: ghcr.io/kyverno/test-verify-images:signed

View file

@ -0,0 +1,6 @@
apiVersion: v1
kind: Pod
metadata:
name: target-pod
namespace: default

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: target-pod
namespace: default
spec:
containers:
- name: container1
image: busybox:latest
- name: container2
image: busybox:latest
- name: container3
image: ghcr.io/kyverno/test-verify-images:signed

View file

@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: target-pod
namespace: default
spec:
containers:
- name: container1
image: busybox:latest
- name: container2
image: busybox:latest
- name: container3
image: busybox:latest

View file

@ -0,0 +1,6 @@
apiVersion: v1
kind: Pod
metadata:
name: trigger-pod
namespace: default

View file

@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: trigger-pod
namespace: default
spec:
containers:
- name: container1
image: busybox:latest