test

The test command is used to test a given set of resources against one or more policies to check desired results, declared in advance in a separate test manifest file, against the actual results. test is useful when you wish to declare what your expected results should be by defining the intent which then assists with locating discrepancies should those results change.

test works by scanning a given location, which can be either a Git repository or local folder, and executing the tests defined within. The rule types validate, mutate, and generate are currently supported. The command recursively looks for YAML files with policy test declarations (described below) with a specified file name and then executes those tests. All files applicable to the same test must be co-located. Directory recursion is supported. test supports the auto-gen feature making it possible to test, for example, Deployment resources against a Pod policy.

test will search for a file named kyverno-test.yaml and, if found, will execute the tests within.

In each test, there are four desired results which can be tested for. If the actual result of the test, once executed, matches the desired result as defined in the test manifest, it will be scored as a pass in the command output. For example, if the specified result of a given test of a resource against a policy is declared to be a pass and the actual result when tested is also a pass, the command output will show as pass. If the actual result was instead a skip, the command output will show as fail because the two results do not agree. The following are the desired results which can be specified in a test manifest.

  1. pass: The resource passes the policy definition. For validate rules which are written with a deny statement, this will not be a possible result. mutate and generate rules can declare a pass.
  2. skip: The resource does not meet either the match or exclude block, or does not pass the preconditions statements. For validate rules which are written with a deny statement, this is a possible result. If a rule contains certain conditional anchors which are not satisfied, the result may also be scored as a skip.
  3. fail: The resource does not pass the policy definition. Typically used for validate rules with pattern-style policy definitions.
  4. warn: Setting the annotation policies.kyverno.io/scored to "false" on a resource or policy which would otherwise fail will be considered a warn.

Use --detailed-results for a comprehensive output (default value false). For help with the test command, pass the -h flag for extensive output including usage, flags, and sample manifests.

Test File Structures

The test declaration file format of kyverno-test.yaml must be of the following format.

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: kyverno-test
 5policies:
 6  - <path/to/policy.yaml>
 7  - <path/to/policy.yaml>
 8resources:
 9  - <path/to/resource.yaml>
10  - <path/to/resource.yaml>
11exceptions: # optional files for specifying exceptions. See below for an example.
12  - <path/to/exception.yaml>
13  - <path/to/exception.yaml>
14variables: variables.yaml # optional file for declaring variables. see below for example.
15userinfo: user_info.yaml # optional file for declaring admission request information (roles, cluster roles and subjects). see below for example.
16results:
17- policy: <name> # Namespaced Policy is specified as <namespace>/<name>
18  isValidatingAdmissionPolicy: false # when the policy is ValidatingAdmissionPolicy, this field is required.
19  rule: <name> # when the policy is a Kyverno policy, this field is required.
20  resources: # optional, primarily for `validate` rules.
21  - <namespace_1/name_1>
22  - <namespace_2/name_2>
23  patchedResource: <file_name.yaml> # when testing a mutate rule this field is required.
24  generatedResource: <file_name.yaml> # when testing a generate rule this field is required.
25  cloneSourceResource: <file_name.yaml> # when testing a generate rule that uses `clone` object this field is required.
26  kind: <kind>
27  result: pass
28checks:
29- match:
30    resource: {} # match results associated with a resource
31    policy: {} # match results associated with a policy
32    rule: {} # match results associated with a rule
33  assert: {} # assertion to validate the content of matched elements
34  error: {} # negative assertion to validate the content of matched elements
35
36The test declaration consists of the following parts:
37
381. The `policies` element which lists one or more policies to be applied.
392. The `resources` element which lists one or more resources to which the policies are applied.
403. The `exceptions` element which lists one or more policy exceptions. Cannot be used with ValidatingAdmissionPolicy. Optional.
414. The `variables` element which defines a file in which variables and their values are stored for use in the policy test. Optional depending on policy content.
425. The `userinfo` element which declares admission request data for subjects and roles. Optional depending on policy content.
436. The `results` element which declares the expected results. Depending on the type of rule being tested, this section may vary.
447. The `checks` element which declares the assertions to be evaluted against the results (see [Working with Assertion Trees](../assertion-trees.md)).
45
46If needing to pass variables, such as those from [external data sources](/docs/writing-policies/external-data-sources/) like context variables built from [API calls](/docs/writing-policies/external-data-sources/#variables-from-kubernetes-api-server-calls) or others, a `variables.yaml` file can be defined with the same format as accepted with the `apply` command. If a variable needs to contain an array of strings, it must be formatted as JSON encoded. Like with the `apply` command, variables that begin with `request.object` normally do not need to be specified in the variables file as these will be sourced from the resource. Policies which trigger based upon `request.operation` equaling `CREATE` do not need a variables file. The CLI will assume a value of `CREATE` if no variable for `request.operation` is defined.
47
48```yaml
49apiVersion: cli.kyverno.io/v1alpha1
50kind: Values
51metadata:
52  name: values
53policies:
54  - name: exclude-namespaces-example
55    rules:
56      - name: exclude-namespaces-dynamically
57        values:
58          namespacefilters.data.exclude: asdf
59    resources:
60      - name: nonroot-pod
61        values:
62          namespacefilters.data.exclude: foo
63      - name: root-pod
64        values:
65          namespacefilters.data.exclude: "[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"

A variables file may also optionally specify global variable values without the need to name specific rules or resources avoiding repetition for the same variable and same value.

1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4  name: values
5globalValues:
6  request.operation: UPDATE

If policies use a namespaceSelector, these can also be specified in the variables file.

1apiVersion: cli.kyverno.io/v1alpha1
2kind: Values
3metadata:
4  name: values
5namespaceSelector:
6  - name: test1
7    labels:
8      foo.com/managed-state: managed

The user can also declare a user_info.yaml file that can be used to pass admission request information such as roles, cluster roles, and subjects.

1apiVersion: cli.kyverno.io/v1alpha1
2kind: UserInfo
3metadata:
4  name: user-info
5clusterRoles:
6- admin
7userInfo:
8  username: someone@somecorp.com

Testing for subresources in Kind/Subresource matching format also requires a subresources{} section in the values file.

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Values
 3metadata:
 4  name: values
 5subresources:
 6  - subresource:
 7      name: <name of subresource>
 8      kind: <kind of subresource>
 9      group: <group of subresource>
10      version: <version of subresource>
11    parentResource:
12      name: <name of parent resource>
13      kind: <kind of parent resource>
14      group: <group of parent resource>
15      version: <version of parent resource>

Here is an example when testing for subresources:

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Values
 3metadata:
 4  name: values
 5subresources:
 6  - subresource:
 7      name: "deployments/scale"
 8      kind: "Scale"
 9      group: "autoscaling"
10      version: "v1"
11    parentResource:
12      name: "deployments"
13      kind: "Deployment"
14      group: "apps"
15      version: "v1"

Test Against Local Files

Test a set of local files in the working directory.

1kyverno test .

Test a set of local files by specifying the directory.

1kyverno test /path/to/folderContainingTestYamls

Test Against Git Repositories

Test an entire Git repository by specifying the branch name within the repo URL. If branch is not specified, main will be used as a default.

1kyverno test https://github.com/kyverno/policies/release-1.6

Test a specific directory of the repository by specifying the directory within repo URL and the branch with the --git-branch or -b flag. Even if testing against main, when using a directory in the URL of the repo requires passing the --git-branch or -b flag.

1kyverno test https://github.com/kyverno/policies/pod-security/restricted -b release-1.6

Use the -f flag to set a custom file name which includes test cases. By default, test will search for a file called kyverno-test.yaml.

Testing Policies with Image Registry Access

For policies which require image registry access to set context variables, those variables may be sourced from a variables file (defined below) or from a “live” registry by passing the --registry flag.

Test Subset of Resources

In some cases, you may wish to only test a subset of policy, rules, and/ resource combination rather than all those defined in a test manifest. Use the --test-case-selector flag to specify the exact tests you wish to execute.

1kyverno test . --test-case-selector "policy=add-default-resources, rule=add-default-requests, resource=nginx-demo2"

Examples

The test command executes a test declaration by applying the policies to the resources and comparing the actual results with the desired/expected results. The test passes if the actual results match the expected results.

Below is an example of testing a policy containing two validate rules against the same resource where each is supposed to pass the policy.

Policy manifest (disallow_latest_tag.yaml):

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: disallow-latest-tag
 5spec:
 6  validationFailureAction: Audit
 7  rules:
 8  - name: require-image-tag
 9    match:
10      any:
11      - resources:
12          kinds:
13          - Pod
14        clusterRoles:
15        - cluster-admin
16    validate:
17      message: "An image tag is required."  
18      pattern:
19        spec:
20          containers:
21          - image: "*:*"
22  - name: validate-image-tag
23    match:
24      any:
25      - resources:
26          kinds:
27          - Pod
28    validate:
29      message: "Using a mutable image tag e.g. 'latest' is not allowed."
30      pattern:
31        spec:
32          containers:
33          - image: "!*:latest"

Resource manifest (resource.yaml):

 1apiVersion: v1
 2kind: Pod
 3metadata:
 4  name: myapp-pod
 5  labels:
 6    app: myapp
 7spec: 
 8  containers:
 9  - name: nginx
10    image: nginx:1.12

Test manifest (kyverno-test.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: disallow_latest_tag
 5policies:
 6  - disallow_latest_tag.yaml
 7resources:
 8  - resource.yaml
 9results:
10  - policy: disallow-latest-tag
11    rule: require-image-tag
12    resource: myapp-pod
13    kind: Pod
14    result: pass
15  - policy: disallow-latest-tag
16    rule: validate-image-tag
17    resource: myapp-pod
18    kind: Pod
19    result: pass
 1$ kyverno test .
 2
 3Executing disallow_latest_tag...
 4applying 1 policy to 1 resource... 
 5
 6│───│─────────────────────│────────────────────│───────────────────────│────────│
 7# │ POLICY              │ RULE               │ RESOURCE              │ RESULT │
 8│───│─────────────────────│────────────────────│───────────────────────│────────│
 91 │ disallow-latest-tag │ require-image-tag  │ default/Pod/myapp-pod │ Pass   │
102 │ disallow-latest-tag │ validate-image-tag │ default/Pod/myapp-pod │ Pass   │
11│───│─────────────────────│────────────────────│───────────────────────│────────│
12
13Test Summary: 2 tests passed and 0 tests failed

In the below case, a mutate policy which adds default resources to a Pod is being tested against two resources. Notice the addition of the patchedResource field in the results[] array, which is a requirement when testing mutate rules.

Policy manifest (add-default-resources.yaml):

 1apiVersion : kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: add-default-resources
 5spec:
 6  background: false
 7  rules:
 8  - name: add-default-requests
 9    match:
10      any:
11      - resources:
12          kinds:
13          - Pod
14    preconditions:
15      any:
16      - key: "{{request.operation}}"
17        operator: AnyIn
18        value:
19        - CREATE
20        - UPDATE
21    mutate:
22      patchStrategicMerge:
23        spec:
24          containers:
25            - (name): "*"
26              resources:
27                requests:
28                  +(memory): "100Mi"
29                  +(cpu): "100m"

Resource manifest (resource.yaml):

 1apiVersion: v1
 2kind: Pod
 3metadata:
 4  name: nginx-demo1
 5spec:
 6  containers:
 7  - name: nginx
 8    image: nginx:1.14.2
 9---
10apiVersion: v1
11kind: Pod
12metadata:
13  name: nginx-demo2
14spec:
15  containers:
16  - name: nginx
17    image: nginx:latest
18    resources:
19      requests:
20        memory: "200Mi" 
21        cpu: "200m"

Variables manifest (values.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Values
 3metadata:
 4  name: values
 5policies:
 6- name: add-default-resources
 7  resources:
 8  - name: nginx-demo1
 9    values:
10      request.operation: CREATE
11  - name: nginx-demo2
12    values:
13      request.operation: UPDATE

Test manifest (kyverno-test.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: add-default-resources
 5policies:
 6  - add-default-resources.yaml
 7resources:
 8  - resource.yaml
 9variables: values.yaml
10results:
11  - policy: add-default-resources
12    rule: add-default-requests
13    resource: nginx-demo1
14    patchedResource: patchedResource1.yaml
15    kind: Pod
16    result: pass
17  - policy: add-default-resources
18    rule: add-default-requests
19    resource: nginx-demo2
20    patchedResource: patchedResource2.yaml
21    kind: Pod
22    result: skip
 1$ kyverno test .
 2
 3Executing add-default-resources...
 4applying 1 policy to 2 resources... 
 5
 6skipped mutate policy add-default-resources -> resource default/Pod/nginx-demo2
 7│───│───────────────────────│──────────────────────│─────────────────────────│────────│
 8# │ POLICY                │ RULE                 │ RESOURCE                │ RESULT │
 9│───│───────────────────────│──────────────────────│─────────────────────────│────────│
101 │ add-default-resources │ add-default-requests │ default/Pod/nginx-demo1 │ Pass   │
112 │ add-default-resources │ add-default-requests │ default/Pod/nginx-demo2 │ Pass   │
12│───│───────────────────────│──────────────────────│─────────────────────────│────────│
13
14Test Summary: 2 tests passed and 0 tests failed

In the following policy test, a generate policy rule is applied which generates a new resource from an existing resource present in resource.yaml. To test the generate policy, the addition of a generatedResource field in the results[] array is required which is used to test against the resource generated by the policy.

Policy manifest (add_network_policy.yaml):

 1apiVersion: kyverno.io/v1
 2kind: ClusterPolicy
 3metadata:
 4  name: add-networkpolicy
 5spec:
 6  rules:
 7  - name: default-deny
 8    match:
 9      any:
10      - resources:
11          kinds:
12          - Namespace
13    generate:
14      apiVersion: networking.k8s.io/v1
15      kind: NetworkPolicy
16      name: default-deny
17      namespace: "{{request.object.metadata.name}}"
18      synchronize: true
19      data:
20        spec:
21          podSelector: {}
22          policyTypes:
23          - Ingress
24          - Egress

Resource manifest (resource.yaml):

1apiVersion: v1
2kind: Namespace
3metadata:
4  name: hello-world-namespace

Generated Resource (generatedResource.yaml):

 1apiVersion: networking.k8s.io/v1
 2kind: NetworkPolicy
 3metadata:
 4  name: default-deny
 5  namespace: hello-world-namespace
 6spec:
 7  podSelector: {}
 8  policyTypes:
 9  - Ingress
10  - Egress

Test manifest (kyverno-test.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: deny-all-traffic
 5policies:
 6  - add_network_policy.yaml
 7resources:
 8  - resource.yaml
 9results:
10  - policy: add-networkpolicy
11    rule: default-deny
12    resource: hello-world-namespace
13    generatedResource: generatedResource.yaml
14    kind: Namespace
15    result: pass
 1$ kyverno test .
 2Executing deny-all-traffic...
 3applying 1 policy to 1 resource...
 4
 5│───│───────────────────│──────────────│──────────────────────────────────│────────│
 6# │ POLICY            │ RULE         │ RESOURCE                         │ RESULT │
 7│───│───────────────────│──────────────│──────────────────────────────────│────────│
 81 │ add-networkpolicy │ default-deny │ /Namespace/hello-world-namespace │ Pass   │
 9│───│───────────────────│──────────────│──────────────────────────────────│────────│
10Test Summary: 1 tests passed and 0 tests failed

In the following policy test, a validate rule ensures that Pods aren’t allowed to access host namespaces. A Policy Exception is used to exempt Pods and Deployments beginning with the name important-tool in the delta namespace from this rule. The exceptions field is used in the Test manifest to declare a Policy Exception manifest. It is expected that resources that violate the rule but match policy exceptions will be skipped. Otherwise, they will fail.

Policy manifest (disallow-host-namespaces.yaml):

 1apiVersion: kyverno.io/v2beta1
 2kind: ClusterPolicy
 3metadata:
 4  name: disallow-host-namespaces
 5spec:
 6  validationFailureAction: Enforce
 7  background: false
 8  rules:
 9    - name: host-namespaces
10      match:
11        any:
12        - resources:
13            kinds:
14              - Pod
15      validate:
16        message: >-
17          Sharing the host namespaces is disallowed. The fields spec.hostNetwork,
18          spec.hostIPC, and spec.hostPID must be unset or set to `false`.                    
19        pattern:
20          spec:
21            =(hostPID): "false"
22            =(hostIPC): "false"
23            =(hostNetwork): "false"

Policy Exception manifest (delta-exception.yaml):

 1apiVersion: kyverno.io/v2beta1
 2kind: PolicyException
 3metadata:
 4  name: delta-exception
 5  namespace: delta
 6spec:
 7  exceptions:
 8  - policyName: disallow-host-namespaces
 9    ruleNames:
10    - host-namespaces
11    - autogen-host-namespaces
12  match:
13    any:
14    - resources:
15        kinds:
16        - Pod
17        - Deployment
18        namespaces:
19        - delta
20        names:
21        - important-tool*

Resource manifest (resource.yaml):

Both Deployments violate the policy but only one matches an exception. The Deployment without an exception will fail while the one with an exception will be skipped.

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: important-tool
 5  namespace: delta
 6  labels:
 7    app: busybox
 8spec:
 9  replicas: 1
10  selector:
11    matchLabels:
12      app: busybox
13  template:
14    metadata:
15      labels:
16        app: busybox
17    spec:
18      hostIPC: true
19      containers:
20      - image: busybox:1.35
21        name: busybox
22        command: ["sleep", "1d"]
23---
24apiVersion: apps/v1
25kind: Deployment
26metadata:
27  name: not-important
28  namespace: gamma
29  labels:
30    app: busybox
31spec:
32  replicas: 1
33  selector:
34    matchLabels:
35      app: busybox
36  template:
37    metadata:
38      labels:
39        app: busybox
40    spec:
41      hostIPC: true
42      containers:
43      - image: busybox:1.35
44        name: busybox
45        command: ["sleep", "1d"]        

Test manifest (kyverno-test.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: disallow-host-namespaces-test-exception
 5policies:
 6- disallow-host-namespace.yaml
 7resources:
 8- resource.yaml
 9exceptions: 
10- delta-exception.yaml
11results:
12  - kind: Deployment
13    policy: disallow-host-namespaces
14    resources: 
15    - important-tool
16    rule: host-namespaces
17    result: skip
18  - kind: Deployment
19    policy: disallow-host-namespaces
20    resources:
21    - not-important
22    rule: host-namespaces
23    result: fail
 1kyverno test .
 2
 3Loading test  ( .kyverno-test/kyverno-test.yaml ) ...
 4  Loading values/variables ...
 5  Loading policies ...
 6  Loading resources ...
 7  Loading exceptions ...
 8  Applying 1 policy to 2 resources with 1 exception ...
 9  Checking results ...
10
11│────│──────────────────────────│─────────────────│───────────────────────────│────────│────────│
12│ ID │ POLICY                   │ RULE            │ RESOURCE                  │ RESULT │ REASON │
13│────│──────────────────────────│─────────────────│───────────────────────────│────────│────────│
141  │ disallow-host-namespaces │ host-namespaces │ Deployment/important-tool │ Pass   │ Ok     │
152  │ disallow-host-namespaces │ host-namespaces │ Deployment/not-important  │ Pass   │ Ok     │
16│────│──────────────────────────│─────────────────│───────────────────────────│────────│────────│
17
18
19Test Summary: 2 tests passed and 0 tests failed

For many more examples of test cases, please see the kyverno/policies repository which strives to have test cases for all the sample policies which appear on the website.

Testing ValidatingAdmissionPolicies

Below is an example of testing a ValidatingAdmissionPolicy against two resources, one of which violates the policy.

Policy manifest (disallow-host-path.yaml):

 1apiVersion: admissionregistration.k8s.io/v1beta1
 2kind: ValidatingAdmissionPolicy
 3metadata:
 4  name: disallow-host-path
 5spec:
 6  failurePolicy: Fail
 7  matchConstraints:
 8    resourceRules:
 9    - apiGroups:   ["apps"]
10      apiVersions: ["v1"]
11      operations:  ["CREATE", "UPDATE"]
12      resources:   ["deployments"]
13  validations:
14    - expression: "!has(object.spec.template.spec.volumes) || object.spec.template.spec.volumes.all(volume, !has(volume.hostPath))"
15      message: "HostPath volumes are forbidden. The field spec.template.spec.volumes[*].hostPath must be unset."

Resource manifest (deployments.yaml):

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: deployment-pass
 5spec:
 6  replicas: 1
 7  selector:
 8    matchLabels:
 9      app: nginx
10  template:
11    metadata:
12      labels:
13        app: nginx
14    spec:
15      containers:
16      - name: nginx-server
17        image: nginx
18        volumeMounts:
19          - name: temp
20            mountPath: /scratch
21      volumes:
22      - name: temp
23        emptyDir: {}
24---
25apiVersion: apps/v1
26kind: Deployment
27metadata:
28  name: deployment-fail
29spec:
30  replicas: 1
31  selector:
32    matchLabels:
33      app: nginx
34  template:
35    metadata:
36      labels:
37        app: nginx
38    spec:
39      containers:
40      - name: nginx-server
41        image: nginx
42        volumeMounts:
43          - name: udev
44            mountPath: /data
45      volumes:
46      - name: udev
47        hostPath:
48          path: /etc/udev

Test manifest (kyverno-test.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: disallow-host-path-test
 5policies:
 6  - disallow-host-path.yaml
 7resources:
 8  - deployments.yaml
 9results:
10  - policy: disallow-host-path
11    resource: deployment-pass
12    isValidatingAdmissionPolicy: true
13    kind: Deployment
14    result: pass
15  - policy: disallow-host-path
16    resource: deployment-fail
17    isValidatingAdmissionPolicy: true
18    kind: Deployment
19    result: fail
 1$ kyverno test .
 2
 3Loading test  ( kyverno-test.yaml ) ...
 4  Loading values/variables ...
 5  Loading policies ...
 6  Loading resources ...
 7  Applying 1 policy to 2 resources ...
 8  Checking results ...
 9
10│────│────────────────────│──────│────────────────────────────│────────│────────│
11│ ID │ POLICY             │ RULE │ RESOURCE                   │ RESULT │ REASON │
12│────│────────────────────│──────│────────────────────────────│────────│────────│
131 │ disallow-host-path │      │ Deployment/deployment-pass │ Pass   │ Ok     │
142 │ disallow-host-path │      │ Deployment/deployment-fail │ Pass   │ Ok     │
15│────│────────────────────│──────│────────────────────────────│────────│────────│
16
17
18Test Summary: 2 tests passed and 0 tests failed

In the below example, a ValidatingAdmissionPolicy and its corresponding ValidatingAdmissionPolicyBinding are tested against six resources. Two of these resources do not match the binding, two match the binding but violate the policy, and the remaining two match the binding and do not violate the policy.

Policy manifest (check-deployment-replicas.yaml):

 1apiVersion: admissionregistration.k8s.io/v1beta1
 2kind: ValidatingAdmissionPolicy
 3metadata:
 4  name: "check-deployment-replicas"
 5spec:
 6  matchConstraints:
 7    resourceRules:
 8    - apiGroups:
 9      - apps
10      apiVersions:
11      - v1
12      operations:
13      - CREATE
14      - UPDATE
15      resources:
16      - deployments
17  validations:
18  - expression: object.spec.replicas <= 2
19---
20apiVersion: admissionregistration.k8s.io/v1beta1
21kind: ValidatingAdmissionPolicyBinding
22metadata:
23  name: "check-deployment-replicas-binding"
24spec:
25  policyName: "check-deployment-replicas"
26  validationActions: [Deny]
27  matchResources:
28    namespaceSelector:
29      matchExpressions:
30      - key: environment
31        operator: In
32        values:
33        - staging
34        - production

Resource manifest (resource.yaml):

  1apiVersion: apps/v1
  2kind: Deployment
  3metadata:
  4  name: testing-deployment-1
  5  namespace: testing
  6  labels:
  7    app: busybox
  8spec:
  9  replicas: 4
 10  selector:
 11    matchLabels:
 12      app: busybox
 13  template:
 14    metadata:
 15      labels:
 16        app: busybox
 17    spec:
 18      containers:
 19      - name: busybox
 20        image: busybox:latest
 21---
 22apiVersion: apps/v1
 23kind: Deployment
 24metadata:
 25  name: testing-deployment-2
 26  namespace: testing
 27  labels:
 28    app: busybox
 29spec:
 30  replicas: 2
 31  selector:
 32    matchLabels:
 33      app: busybox
 34  template:
 35    metadata:
 36      labels:
 37        app: busybox
 38    spec:
 39      containers:
 40      - name: busybox
 41        image: busybox:latest
 42---
 43apiVersion: apps/v1
 44kind: Deployment
 45metadata:
 46  name: staging-deployment-1
 47  namespace: staging
 48  labels:
 49    app: nginx
 50spec:
 51  replicas: 4
 52  selector:
 53    matchLabels:
 54      app: nginx
 55  template:
 56    metadata:
 57      labels:
 58        app: nginx
 59    spec:
 60      containers:
 61      - name: nginx
 62        image: nginx:latest
 63---
 64apiVersion: apps/v1
 65kind: Deployment
 66metadata:
 67  name: staging-deployment-2
 68  namespace: staging
 69  labels:
 70    app: nginx
 71spec:
 72  replicas: 2
 73  selector:
 74    matchLabels:
 75      app: nginx
 76  template:
 77    metadata:
 78      labels:
 79        app: nginx
 80    spec:
 81      containers:
 82      - name: nginx
 83        image: nginx:latest
 84---
 85apiVersion: apps/v1
 86kind: Deployment
 87metadata:
 88  name: production-deployment-1
 89  namespace: production
 90  labels:
 91    app: nginx
 92spec:
 93  replicas: 4
 94  selector:
 95    matchLabels:
 96      app: nginx
 97  template:
 98    metadata:
 99      labels:
100        app: nginx
101    spec:
102      containers:
103      - name: nginx
104        image: nginx:latest
105---
106apiVersion: apps/v1
107kind: Deployment
108metadata:
109  name: production-deployment-2
110  namespace: production
111  labels:
112    app: nginx
113spec:
114  replicas: 2
115  selector:
116    matchLabels:
117      app: nginx
118  template:
119    metadata:
120      labels:
121        app: nginx
122    spec:
123      containers:
124      - name: nginx
125        image: nginx:latest

The above resource manifest contains the following:

  1. Two Deployments named testing-deployment-1 and testing-deployment-2 in the testing namespace. The first Deployment has four replicas, while the second Deployment has two.

  2. Two Deployments named staging-deployment-1 and staging-deployment-2 in the staging namespace. The first Deployment has four replicas, while the second Deployment has two.

  3. Two Deployments named production-deployment-1 and production-deployment-2 in the production namespace. The first Deployment has four replicas, while the second Deployment has two.

Variables manifest (values.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Value
 3metadata:
 4  name: values
 5namespaceSelector:
 6  - name: staging
 7    labels:
 8      environment: staging
 9  - name: production
10    labels:
11      environment: production
12  - name: testing
13    labels:
14      environment: testing

Test manifest (kyverno-test.yaml):

 1apiVersion: cli.kyverno.io/v1alpha1
 2kind: Test
 3metadata:
 4  name: kyverno-test.yaml
 5policies:
 6- policy.yaml
 7resources:
 8- resource.yaml
 9variables: values.yaml
10results:
11- kind: Deployment
12  policy: check-deployment-replicas
13  isValidatingAdmissionPolicy: true
14  resources:
15  - testing-deployment-1
16  - testing-deployment-2
17  result: skip
18- kind: Deployment
19  policy: check-deployment-replicas
20  isValidatingAdmissionPolicy: true
21  resources:
22  - staging-deployment-1
23  - production-deployment-1
24  result: fail
25- kind: Deployment
26  policy: check-deployment-replicas
27  isValidatingAdmissionPolicy: true
28  resources:
29  - staging-deployment-2
30  - production-deployment-2
31  result: pass
 1$ kyverno test .
 2
 3Loading test  ( kyverno-test.yaml ) ...
 4  Loading values/variables ...
 5  Loading policies ...
 6  Loading resources ...
 7  Loading exceptions ...
 8  Applying 1 policy to 6 resources ...
 9  Checking results ...
10
11│────│───────────────────────────│──────│────────────────────────────────────│────────│──────────│
12│ ID │ POLICY                    │ RULE │ RESOURCE                           │ RESULT │ REASON   │
13│────│───────────────────────────│──────│────────────────────────────────────│────────│──────────│
141  │ check-deployment-replicas │      │ Deployment/testing-deployment-1    │ Pass   │ Excluded │
152  │ check-deployment-replicas │      │ Deployment/testing-deployment-2    │ Pass   │ Excluded │
163  │ check-deployment-replicas │      │ Deployment/staging-deployment-1    │ Pass   │ Ok       │
174  │ check-deployment-replicas │      │ Deployment/production-deployment-1 │ Pass   │ Ok       │
185  │ check-deployment-replicas │      │ Deployment/staging-deployment-2    │ Pass   │ Ok       │
196  │ check-deployment-replicas │      │ Deployment/production-deployment-2 │ Pass   │ Ok       │
20│────│───────────────────────────│──────│────────────────────────────────────│────────│──────────│
21
22
23Test Summary: 6 tests passed and 0 tests failed

Last modified April 29, 2024 at 11:02 AM PST: Cherry Pick PR 1223 (#1232) (c6f6b34)