diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index db2f092091..75a5a74ef4 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -101,7 +101,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) { } // operate on the copy of the conditions, as we perform variable substitution - copyConditions, err := transformConditions(rule.AnyAllConditions) + copyConditions, err := transformConditions(ruleCopy.AnyAllConditions) if err != nil { logger.V(2).Info("failed to load context", "reason", err.Error()) continue diff --git a/pkg/engine/mutation_test.go b/pkg/engine/mutation_test.go index f441b52419..b656756215 100644 --- a/pkg/engine/mutation_test.go +++ b/pkg/engine/mutation_test.go @@ -302,3 +302,88 @@ func Test_chained_rules(t *testing.T) { assert.Equal(t, string(er.PolicyResponse.Rules[0].Patches[0]), `{"op":"replace","path":"/spec/containers/0/image","value":"myregistry.corp.com/foo/bash:5.0"}`) assert.Equal(t, string(er.PolicyResponse.Rules[1].Patches[0]), `{"op":"replace","path":"/spec/containers/0/image","value":"otherregistry.corp.com/foo/bash:5.0"}`) } + +func Test_precondition(t *testing.T) { + resourceRaw := []byte(`{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "nginx-config-test", + "labels": { + "app.kubernetes.io/managed-by": "Helm" + } + }, + "spec": { + "containers": [ + { + "image": "nginx:latest", + "name": "test-nginx" + } + ] + } +}`) + + policyraw := []byte(`{ + "apiVersion": "kyverno.io/v1", + "kind": "ClusterPolicy", + "metadata": { + "name": "cm-variable-example" + }, + "spec": { + "rules": [ + { + "name": "example-configmap-lookup", + "match": { + "resources": { + "kinds": [ + "Pod" + ] + } + }, + "preconditions": [ + { + "key": "{{ request.object.metadata.labels.\"app.kubernetes.io/managed-by\"}}", + "operator": "Equals", + "value": "Helm" + } + ], + "mutate": { + "patchStrategicMerge": { + "metadata": { + "labels": { + "my-added-label": "test" + } + } + } + } + } + ] + } +}`) + + expectedPatch := []byte(`{"op":"add","path":"/metadata/labels/my-added-label","value":"test"}`) + + store.SetMock(true) + var policy kyverno.ClusterPolicy + err := json.Unmarshal(policyraw, &policy) + assert.NilError(t, err) + resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw) + assert.NilError(t, err) + + ctx := context.NewContext() + err = ctx.AddResource(resourceRaw) + assert.NilError(t, err) + + policyContext := &PolicyContext{ + Policy: policy, + JSONContext: ctx, + NewResource: *resourceUnstructured, + } + + er := Mutate(policyContext) + t.Log(string(expectedPatch)) + t.Log(string(er.PolicyResponse.Rules[0].Patches[0])) + if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) { + t.Error("patches don't match") + } +}