-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add extend CLI for generate policies proposal #6
Changes from all commits
d3c6515
840f8c9
0f32087
e192f66
4a975dd
6b9d33d
4e2af5e
048ac73
567453f
b17242a
2b0ee17
89685ca
691f028
db38d60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
# Kyverno Design Proposal - Extend CLI test command for generate policies | ||
|
||
Author: [Shubham Nazare](https://github.com/shubham4443) | ||
|
||
PR: [#3456](https://github.com/kyverno/kyverno/pull/3456) | ||
|
||
## Contents | ||
|
||
- [Kyverno Design Proposal - Extend CLI test command for generate policies](#kyverno-design-proposal---extend-cli-test-command-for-generate-policies) | ||
* [Introduction](#introduction) | ||
* [Proposal](#proposal) | ||
+ [API Design Changes](#api-design-changes) | ||
+ [Method to test data object](#method-to-test-data-object) | ||
- [Example: Add Network Policy](#example--add-network-policy) | ||
+ [Method to test clone object](#method-to-test-clone-object) | ||
- [Example: Sync Secrets](#example--sync-secrets) | ||
+ [Namespaced Policies](#namespaced-policies) | ||
- [Example: Policy Disruption Budget](#example--policy-disruption-budget) | ||
* [Implementation details](#implementation-details) | ||
+ [Mock Generate-Request Controller](#mock-generate-request-controller) | ||
+ [Building the result](#building-the-result) | ||
|
||
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small> | ||
|
||
|
||
## Introduction | ||
|
||
Prior to this proposal, only validate and mutate policies were covered by the kyverno test CLI command. Generate policies were skipped by the CLI. This document proposes an approach for the test command to cover generate policies as well. | ||
|
||
## Proposal | ||
|
||
When using a generate rule, the target resource can be either an existing resource defined within Kubernetes, or a new resource defined in the rule itself. When the target resource is a pre-existing resource the clone object is used. When the target resource is a new resource defined within the manifest of the rule, the data object is used. Both rules are mutually exclusive, and only one will be specified in a rule. Both objects require a different approach for testing through CLI command. | ||
|
||
### API Design Changes | ||
|
||
The test file will take 2 new fields - generatedResource and cloneSourceResource. | ||
|
||
```go | ||
|
||
type TestResults struct { | ||
Policy string `json:"policy"` | ||
Rule string `json:"rule"` | ||
Result report.PolicyResult `json:"result"` | ||
Status report.PolicyResult `json:"status"` | ||
Resource string `json:"resource"` | ||
Kind string `json:"kind"` | ||
Namespace string `json:"namespace"` | ||
PatchedResource string `json:"patchedResource"` | ||
AutoGeneratedRule string `json:"auto_generated_rule"` | ||
GeneratedResource string `json:"generatedResource"` | ||
CloneSourceResource string `json:"cloneSourceResource"` | ||
} | ||
``` | ||
|
||
### Method to test data object | ||
|
||
The method is similar to the testing for mutate policies. User will provide the desired resource manifest file as generatedResource in the results array of the test file. This manifest file will be compared with the Kyverno generated resource and accordingly the test will display the result as pass or fail. | ||
|
||
Additionally, like in the case of testing mutate policies, we provide the resource on which we want to perform mutation. For generate policies, the triggering resource should be provided on creation/update of which our generation rule is applied. | ||
|
||
#### Example: Add Network Policy | ||
|
||
A sample test file for [this policy](https://kyverno.io/policies/best-practices/add_network_policy/) will look like this - | ||
|
||
```yaml | ||
name: deny-all-traffic | ||
policies: | ||
- policy.yaml | ||
resources: | ||
- resource.yaml | ||
results: | ||
- policy: add-networkpolicy | ||
rule: default-deny | ||
resource: hello-world-namespace | ||
generatedResource: generatedResource.yaml | ||
kind: Namespace | ||
result: pass | ||
``` | ||
resource.yaml is the manifest for creating a new Namespace resource. The result will pass if the generatedResource.yaml looks like this - | ||
|
||
```yaml | ||
apiVersion: networking.k8s.io/v1 | ||
kind: NetworkPolicy | ||
metadata: | ||
name: default-deny | ||
namespace: hello-world-namespace | ||
spec: | ||
podSelector: {} | ||
policyTypes: | ||
- Ingress | ||
- Egress | ||
``` | ||
|
||
### Method to test clone object | ||
|
||
Generate rules with clone object requires a pre-existing resource in the cluster. The manifest of the rule will not have the definition of this resource. Instead, the rule will only specify the name of the resource and the namespace where it resides. To have the resource exist on the cluster before the rule is applied, user should provide the definition of the resource. The rest of the approach remains same as that of data object. | ||
|
||
#### Example: Sync Secrets | ||
|
||
Consider [this policy](https://kyverno.io/policies/other/sync_secrets/). The test file should look like this - | ||
|
||
```yaml | ||
name: sync-secrets | ||
policies: | ||
- policy.yaml | ||
resources: | ||
- resource.yaml | ||
results: | ||
- policy: sync-secrets | ||
rule: sync-image-pull-secret | ||
resource: hello-world-namespace | ||
generatedResource: generatedResource.yaml | ||
cloneSourceResource: cloneSourceResource.yaml # Pre-existing resource definition | ||
kind: Namespace | ||
result: pass | ||
``` | ||
|
||
User should provide the pre-existing resource in the `cloneSourceResource` field of the results array. The cloneSourceResource.yaml for the above test file will look like this - | ||
|
||
```yaml | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: regcred | ||
namespace: default | ||
type: Opaque | ||
data: | ||
password: MWYyZDFlMmU2N2Rm | ||
``` | ||
|
||
The test will pass if the generatedResource.yaml looks like this - | ||
|
||
```yaml | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: regcred | ||
namespace: hello-world-namespace | ||
type: Opaque | ||
data: | ||
password: MWYyZDFlMmU2N2Rm | ||
``` | ||
|
||
### Namespaced Policies | ||
|
||
In order to test namespaced policies, user have to explicitly mention the namespace of the policy in the test file. Additionally, the triggering resource should belong to the namespace for which the policy is configured. | ||
|
||
#### Example: Policy Disruption Budget | ||
|
||
Consider this namespaced policy - | ||
```yaml | ||
apiVersion: kyverno.io/v1 | ||
kind: Policy | ||
metadata: | ||
name: create-default-pdb | ||
namespace: hello-world | ||
spec: | ||
rules: | ||
- name: create-default-pdb | ||
match: | ||
resources: | ||
kinds: | ||
- Deployment | ||
generate: | ||
apiVersion: policy/v1 | ||
kind: PodDisruptionBudget | ||
name: "{{request.object.metadata.name}}-default-pdb" | ||
namespace: "{{request.object.metadata.namespace}}" | ||
data: | ||
spec: | ||
minAvailable: 1 | ||
selector: | ||
matchLabels: | ||
"{{request.object.metadata.labels}}" | ||
``` | ||
|
||
The test file for this policy should explicitly mention the policy namespace. | ||
|
||
```yaml | ||
name: pdb-test | ||
policies: | ||
- policy.yaml | ||
resources: | ||
- resource.yaml | ||
results: | ||
- policy: create-default-pdb | ||
rule: create-default-pdb | ||
resource: nginx-deployment | ||
generatedResource: generatedResource.yaml | ||
kind: Deployment | ||
result: pass | ||
namespace: hello-world | ||
``` | ||
|
||
## Implementation details | ||
|
||
Most of the implementation is similar to testing mutate policies. The key difference is that generate rules require a Generate-Request Controller. | ||
|
||
### Mock Generate-Request Controller | ||
|
||
To process generate rules, we need a Generate-Request Controller. We can make a simple instance of the Controller with only the Kubernetes' dynamic client. The dynamic client must be a fake one so as to not process the rule on an actual cluster. Additionally, the triggering resource and pre-existing resource for the clone object should exist in the cluster. The dynamic client will be initialized with these resources. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on the above proposal, all test resources are local resources, do we need the dynamic client? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we require the dynamic client otherwise its not possible to invoke the function responsible for handling generate policies. |
||
|
||
### Building the result | ||
|
||
We can use the same function used for testing mutate policies to compare user defined resource and Kyverno generated resource and give it some generic name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the above proposal, all test resources are local resources, do we need the dynamic client?