Skip to content

Commit

Permalink
docs: Add high level description for mutation feature
Browse files Browse the repository at this point in the history
Signed-off-by: aerosouund <[email protected]>
  • Loading branch information
aerosouund committed Sep 30, 2024
1 parent 09292d3 commit 949ffa6
Showing 1 changed file with 154 additions and 13 deletions.
167 changes: 154 additions & 13 deletions proposals/mutation-support-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,165 @@ The introduction of this error message was required as a guardrail for when the

## Proposal

The CLI isn't going to mutate actual resources, its only required to output the changes that will be made by a mutation rather than the original resource in case of a mutation
### apply

## Example
The apply command will receive an additional flag `--target-resource`. this flag can be passed multiple times for single resources. e.g:

This example adds the label `foo=bar` to deployments in the `secure` namespace
```bash
kyverno apply policy-with-mutate-existing.yaml --resource=trigger1.yaml --resource=trigger2.yaml --target-resource=resource1.yaml --target-resource=resource2.yaml
```

Or given a directory containing resources

```bash
kyverno apply policy-with-mutate-existing.yaml /path/to/trigger/resources --target-resource=/path/to/resources
```

When this flag is passed but the policy or policies have no mutate existing, the behavior should be to ignore the flag.
When this flag is not passed but the policy has mutate existing rules, it should not error. but should generate a warning that no resources have been passed. and the rule evaluation should be **SKIPPED**.
The target resource flag being passed here maps to the unchanged resource, the apply command will output the mutated resource if succeded


### test

two extra keys will be added to the test yaml definition to define the behavior of mutate existing with the test command

```yaml
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: kyverno-test
policies:
- <path/to/policy.yaml>
- <path/to/policy.yaml>
resources:
- <path/to/resource.yaml>
- <path/to/resource.yaml>
exceptions:
- <path/to/exception.yaml>
- <path/to/exception.yaml>
targetResources: # This will be added
- <path/to/unmutated/resource.yaml>
variables: variables.yaml # This will receive a new key for mutation target variables
userinfo: user_info.yaml
results:
- policy: <name>
isValidatingAdmissionPolicy: false
rule: <name>
resources:
- <namespace_1/name_1>
- <namespace_2/name_2>
patchedResources: <file_name.yaml> # Mutated resources will be specified here, separated by ---
generatedResource: <file_name.yaml>
- <path/to/patched/resource1.yaml>
- <path/to/patched/resource2.yaml>
cloneSourceResource: <file_name.yaml>
kind: <kind>
result: pass
```
The schema of the variables file will be changed as follows:
```yaml
apiVersion: cli.kyverno.io/v1alpha1
kind: Values
metadata:
name: values
# existing keys
targetResources:
- name: nginx-demo1
values:
request.operation: CREATE
- name: nginx-demo2
values:
request.operation: UPDATE
```
The key `targetResources` will be added and its type is an array of object containing two keys: `name` of type string and values of type `map[string]interface{}` or a mapping of string to anything.

These additions will be optional, all of them will be ignored (whatever value being put to them will not be accounted for) if the policy passed has no mutate existing

### Examples

This example adds data to a `ConfigMap` on namespace creation

`pol.yaml`
```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: policy
name: configmap-policy
spec:
mutateExistingOnPolicyUpdate: true
rules:
- name: configmap-update
match:
any:
- resources:
kinds:
- Namespace
operations:
- "CREATE"
mutate:
targets:
- apiVersion: v1
kind: ConfigMap
namespace: "test"
name: "cm1"
patchStrategicMerge:
data:
monitored-ns: "{{ request.object.metadata.name }}"
```

`ns.yaml`
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: staging
```

`cm.yaml`
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm
namespace: test
data: {}
```

Invocation:
`kyverno apply pol.yaml --resource=ns.yaml --target-resource=cm.yaml`

Should output:

```
Applying 1 policy rule(s) to 1 resource(s)...
mutate policy policy applied to test/ConfigMap/cm:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm
namespace: test
data:
monitored-ns: staging
---
pass: 1, fail: 0, warn: 0, error: 0, skip: 0
```

---

This example adds the label `foo=bar` to deployments in the `secure` namespace in cluster mode

`pol.yaml`
```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deployment-policy
spec:
mutateExistingOnPolicyUpdate: true
rules:
Expand All @@ -97,7 +245,7 @@ spec:
```

Invocation:
`kyverno apply ~/policies/pol.yaml --cluster -n secure`
`kyverno apply pol.yaml --cluster -n secure`

Should output:

Expand All @@ -109,12 +257,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
foo: bar <<< SHOULD REFLECT THE MODIFIED RESOURCE
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"nginx-deployment","namespace":"secure"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"nginx"}},"template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.21.1","name":"nginx","ports":[{"containerPort":80}]}]}}}}
creationTimestamp: "2024-07-29T13:18:13Z"
generation: 2
foo: bar <<< The mutated cluster resource
// omitted fields
spec:
progressDeadlineSeconds: 600
Expand Down Expand Up @@ -164,13 +307,11 @@ status:
status: "True"
type: Available
observedGeneration: 2
---
pass: 1, fail: 0, warn: 0, error: 0, skip: 0
```


## Implementation

There are two scenarios that need to be supported in the implementation:
Expand Down

0 comments on commit 949ffa6

Please sign in to comment.