1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

feat: add tests for different values of generateExisting (#10807)

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
Mariam Fahmy 2024-08-08 15:11:20 +03:00 committed by GitHub
parent ef05ab7b29
commit 60a8384fd4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 466 additions and 53 deletions

View file

@ -781,10 +781,6 @@ type Generation struct {
CloneList CloneList `json:"cloneList,omitempty" yaml:"cloneList,omitempty"`
}
func (g *Generation) IsGenerateExisting() *bool {
return g.GenerateExisting
}
type CloneList struct {
// Namespace specifies source resource namespace.
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`

View file

@ -254,19 +254,16 @@ func (s *Spec) GetMutateExistingOnPolicyUpdate() bool {
return s.MutateExistingOnPolicyUpdate
}
// IsGenerateExisting return GenerateExisting set value
// IsGenerateExisting returns true if any of the generate rules has generateExisting set to true
func (s *Spec) IsGenerateExisting() bool {
for _, rule := range s.Rules {
if rule.HasGenerate() {
isGenerateExisting := rule.Generation.IsGenerateExisting()
if isGenerateExisting != nil {
return *isGenerateExisting
isGenerateExisting := rule.Generation.GenerateExisting
if isGenerateExisting != nil && *isGenerateExisting {
return true
}
}
}
if s.GenerateExistingOnPolicyUpdate != nil && *s.GenerateExistingOnPolicyUpdate {
return true
}
return s.GenerateExisting
}
@ -340,15 +337,8 @@ func (s *Spec) validateDeprecatedFields(path *field.Path) (errs field.ErrorList)
errs = append(errs, field.Forbidden(path.Child("failurePolicy"), "remove the deprecated field and use spec.webhookConfiguration.failurePolicy instead"))
}
for _, rule := range s.Rules {
if rule.HasGenerate() && rule.Generation.IsGenerateExisting() != nil {
if s.GenerateExistingOnPolicyUpdate != nil {
errs = append(errs, field.Forbidden(path.Child("generateExistingOnPolicyUpdate"), "remove the deprecated field and use spec.generate[*].generateExisting instead"))
}
if s.GenerateExisting {
errs = append(errs, field.Forbidden(path.Child("generateExisting"), "remove the deprecated field and use spec.generate[*].generateExisting instead"))
}
}
if s.GenerateExistingOnPolicyUpdate != nil {
errs = append(errs, field.Forbidden(path.Child("generateExistingOnPolicyUpdate"), "remove the deprecated field and use spec.generate[*].generateExisting instead"))
}
return errs
}

View file

@ -223,19 +223,16 @@ func (s *Spec) GetMutateExistingOnPolicyUpdate() bool {
return s.MutateExistingOnPolicyUpdate
}
// IsGenerateExisting return GenerateExisting set value
// IsGenerateExisting returns true if any of the generate rules has generateExisting set to true
func (s *Spec) IsGenerateExisting() bool {
for _, rule := range s.Rules {
if rule.HasGenerate() {
isGenerateExisting := rule.Generation.IsGenerateExisting()
if isGenerateExisting != nil {
return *isGenerateExisting
isGenerateExisting := rule.Generation.GenerateExisting
if isGenerateExisting != nil && *isGenerateExisting {
return true
}
}
}
if s.GenerateExistingOnPolicyUpdate != nil && *s.GenerateExistingOnPolicyUpdate {
return true
}
return s.GenerateExisting
}
@ -300,15 +297,8 @@ func (s *Spec) ValidateDeprecatedFields(path *field.Path) (errs field.ErrorList)
errs = append(errs, field.Forbidden(path.Child("failurePolicy"), "remove the deprecated field and use spec.webhookConfiguration.failurePolicy instead"))
}
for _, rule := range s.Rules {
if rule.HasGenerate() && rule.Generation.IsGenerateExisting() != nil {
if s.GenerateExistingOnPolicyUpdate != nil {
errs = append(errs, field.Forbidden(path.Child("generateExistingOnPolicyUpdate"), "remove the deprecated field and use spec.generate[*].generateExisting instead"))
}
if s.GenerateExisting {
errs = append(errs, field.Forbidden(path.Child("generateExisting"), "remove the deprecated field and use spec.generate[*].generateExisting instead"))
}
}
if s.GenerateExistingOnPolicyUpdate != nil {
errs = append(errs, field.Forbidden(path.Child("generateExistingOnPolicyUpdate"), "remove the deprecated field and use spec.generate[*].generateExisting instead"))
}
return errs
}

View file

@ -95,7 +95,7 @@ func NewGenerateController(
}
func (c *GenerateController) ProcessUR(ur *kyvernov2.UpdateRequest) error {
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String())
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "rule", ur.Spec.GetRuleName(), "resource", ur.Spec.GetResource().String())
var err error
var genResources []kyvernov1.ResourceSpec
logger.Info("start processing UR", "ur", ur.Name, "resourceVersion", ur.GetResourceVersion())
@ -198,7 +198,7 @@ func (c *GenerateController) getTriggerForCreateOperation(spec kyvernov2.UpdateR
}
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur kyvernov2.UpdateRequest, namespaceLabels map[string]string) ([]kyvernov1.ResourceSpec, error) {
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String())
logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "rule", ur.Spec.GetRuleName(), "resource", ur.Spec.GetResource().String())
logger.V(3).Info("applying generate policy rule")
policy, err := c.getPolicySpec(ur)
@ -237,6 +237,10 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
var applicableRules []string
// Removing UR if rule is failed. Used when the generate condition failed but ur exist
for _, r := range engineResponse.PolicyResponse.Rules {
if r.Name() != ur.Spec.GetRuleName() {
continue
}
if r.Status() != engineapi.RuleStatusPass {
logger.V(4).Info("querying all update requests")
selector := labels.SelectorFromSet(labels.Set(map[string]string{

View file

@ -41,10 +41,22 @@ func (pc *policyController) handleGenerateForExisting(policy kyvernov1.PolicyInt
var errors []error
var triggers []*unstructured.Unstructured
ruleType := kyvernov2.Generate
spec := policy.GetSpec()
policyNew := policy.CreateDeepCopy()
policyNew.GetSpec().Rules = nil
for _, rule := range policy.GetSpec().Rules {
for _, rule := range spec.Rules {
// check if the rule sets the generateExisting field.
// if not, use the policy level setting
generateExisting := rule.Generation.GenerateExisting
if generateExisting != nil {
if !*generateExisting {
continue
}
} else if !spec.GenerateExisting {
continue
}
triggers = getTriggers(pc.client, rule, policy.IsNamespaced(), policy.GetNamespace(), pc.log)
policyNew.GetSpec().SetRules([]kyvernov1.Rule{rule})
for _, trigger := range triggers {

View file

@ -96,12 +96,6 @@ func CreatePolicySpec(ff *fuzz.ConsumeFuzzer) (kyvernov1.Spec, error) {
}
spec.MutateExistingOnPolicyUpdate = mutateExistingOnPolicyUpdate
generateExistingOnPolicyUpdate, err := ff.GetBool()
if err != nil {
return *spec, err
}
spec.GenerateExistingOnPolicyUpdate = &generateExistingOnPolicyUpdate
generateExisting, err := ff.GetBool()
if err != nil {
return *spec, err

View file

@ -10,7 +10,7 @@ metadata:
Sync Secret and Configmap from kube-system namespace
spec:
failurePolicy: Ignore
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- name: sync-controller-secret
match:

View file

@ -0,0 +1,17 @@
## Description
This test ensures that a generate policy works as expected in case one rule sets the `generateExisting` field whereas the other don't set it. It is expected that rules which don't set the field will use the higher level value `spec.generateExisting`.
## Expected Behavior
1. Create two Namespaces named `red-ns` and `green-ns`.
2. Create a policy with two generate rules:
- The first rule named `generate-network-policy` matches Namespaces sets the `generateExisting` to `true`.
- The second rule named `generate-config-map` matches Namespaces and it doesn't set the field. It is expected that the rule will use the `spec.generateExisting` value which is `false`.
3. It is expected that a NetworkPolicy will be generated for each Namespace whereas ConfigMaps will not be generated.
## Reference Issue(s)
N/A

View file

@ -0,0 +1,27 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: different-configurations-for-generate-existing
spec:
steps:
- name: step-01
try:
- apply:
file: existing-resources.yaml
- name: step-02
try:
- apply:
file: policy.yaml
- assert:
file: policy-ready.yaml
- name: step-03
try:
- sleep:
duration: 3s
- name: step-04
try:
- assert:
file: generated-resources.yaml
- error:
file: fail-generated-resources.yaml

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: Namespace
metadata:
name: red-ns
labels:
color: red
---
apiVersion: v1
kind: Namespace
metadata:
name: green-ns
labels:
color: green

View file

@ -0,0 +1,21 @@
apiVersion: v1
data:
KAFKA_ADDRESS: 192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092
ZK_ADDRESS: 192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181
kind: ConfigMap
metadata:
labels:
somekey: somevalue
name: zk-kafka-address
namespace: red-ns
---
apiVersion: v1
data:
KAFKA_ADDRESS: 192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092
ZK_ADDRESS: 192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181
kind: ConfigMap
metadata:
labels:
somekey: somevalue
name: zk-kafka-address
namespace: green-ns

View file

@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
created-by: kyverno
name: default-deny
namespace: red-ns
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
created-by: kyverno
name: default-deny
namespace: green-ns
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

View file

@ -0,0 +1,9 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: different-generate-existing-values
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,49 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: different-generate-existing-values
spec:
generateExisting: false
rules:
- name: generate-network-policy
match:
any:
- resources:
kinds:
- Namespace
generate:
generateExisting: true
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
name: default-deny
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
metadata:
labels:
created-by: kyverno
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
- name: generate-config-map
match:
any:
- resources:
kinds:
- Namespace
generate:
synchronize: true
apiVersion: v1
kind: ConfigMap
name: zk-kafka-address
namespace: "{{request.object.metadata.name}}"
data:
kind: ConfigMap
metadata:
labels:
somekey: somevalue
data:
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"

View file

@ -0,0 +1,17 @@
## Description
This test ensures that a generate policy works as expected in case the rules have a different value for the `generateExisting` field.
## Expected Behavior
1. Create two Namespaces named `red-ns` and `green-ns`.
2. Create a policy with two generate rules:
- The first rule named `generate-network-policy` matches Namespaces sets the `generateExisting` to `true`.
- The second rule named `generate-config-map` matches Namespaces sets the `generateExisting` to `false`.
3. It is expected that a NetworkPolicy will be generated for each Namespace whereas ConfigMaps will not be generated.
## Reference Issue(s)
N/A

View file

@ -0,0 +1,27 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: different-generate-existing-values
spec:
steps:
- name: step-01
try:
- apply:
file: existing-resources.yaml
- name: step-02
try:
- apply:
file: policy.yaml
- assert:
file: policy-ready.yaml
- name: step-03
try:
- sleep:
duration: 3s
- name: step-04
try:
- assert:
file: generated-resources.yaml
- error:
file: fail-generated-resources.yaml

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: Namespace
metadata:
name: red-ns
labels:
color: red
---
apiVersion: v1
kind: Namespace
metadata:
name: green-ns
labels:
color: green

View file

@ -0,0 +1,21 @@
apiVersion: v1
data:
KAFKA_ADDRESS: 192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092
ZK_ADDRESS: 192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181
kind: ConfigMap
metadata:
labels:
somekey: somevalue
name: zk-kafka-address
namespace: red-ns
---
apiVersion: v1
data:
KAFKA_ADDRESS: 192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092
ZK_ADDRESS: 192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181
kind: ConfigMap
metadata:
labels:
somekey: somevalue
name: zk-kafka-address
namespace: green-ns

View file

@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
created-by: kyverno
name: default-deny
namespace: red-ns
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
created-by: kyverno
name: default-deny
namespace: green-ns
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

View file

@ -0,0 +1,9 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: different-generate-existing-values
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -0,0 +1,49 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: different-generate-existing-values
spec:
rules:
- name: generate-network-policy
match:
any:
- resources:
kinds:
- Namespace
generate:
generateExisting: true
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
name: default-deny
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
metadata:
labels:
created-by: kyverno
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
- name: generate-config-map
match:
any:
- resources:
kinds:
- Namespace
generate:
generateExisting: false
synchronize: true
apiVersion: v1
kind: ConfigMap
name: zk-kafka-address
namespace: "{{request.object.metadata.name}}"
data:
kind: ConfigMap
metadata:
labels:
somekey: somevalue
data:
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"

View file

@ -3,7 +3,7 @@ kind: ClusterPolicy
metadata:
name: target-namespace-scope-pass-1
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: iam.aws.crossplane.io/v1beta1

View file

@ -3,7 +3,7 @@ kind: ClusterPolicy
metadata:
name: user-per-namespace-pass-2
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: rbac.authorization.k8s.io/v1

View file

@ -3,7 +3,7 @@ kind: ClusterPolicy
metadata:
name: target-namespace-scope-pass-1
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: iam.aws.crossplane.io/v1beta1

View file

@ -0,0 +1,7 @@
## Description
This test ensures that the creation of a generate policy that makes use of `spec.generateExistingOnPolicyUpdate` is blocked since it is a deprecated field.
## Expected Behavior
The test passes if the policy creation is blocked, otherwise fails.

View file

@ -0,0 +1,14 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: use-generate-existing-on-policy-update
spec:
steps:
- name: step-01
try:
- apply:
expect:
- check:
($error != null): true
file: policy.yaml

View file

@ -0,0 +1,31 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-policy
spec:
generateExistingOnPolicyUpdate: true
rules:
- name: generate-rule
match:
any:
- resources:
kinds:
- Namespace
selector:
matchLabels:
color: blue
generate:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
name: default-deny
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
metadata:
labels:
created-by: kyverno
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

View file

@ -5,7 +5,7 @@ metadata:
name: pol-target-namespace-scope-fail-1
namespace: default
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: iam.aws.crossplane.io/v1beta1

View file

@ -5,7 +5,7 @@ metadata:
name: pol-target-namespace-scope-fail-2
namespace: default
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: rbac.authorization.k8s.io/v1

View file

@ -5,7 +5,7 @@ metadata:
name: pol-target-namespace-scope-fail-3
namespace: default
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: rbac.authorization.k8s.io/v1

View file

@ -4,7 +4,7 @@ metadata:
name: user-per-namespace-pass
namespace: default
spec:
generateExistingOnPolicyUpdate: true
generateExisting: true
rules:
- generate:
apiVersion: rbac.authorization.k8s.io/v1

View file

@ -0,0 +1,7 @@
## Description
This test ensures that the creation of a generate policy that makes use of `spec.generateExistingOnPolicyUpdate` is blocked since it is a deprecated field.
## Expected Behavior
The test passes if the policy creation is blocked, otherwise fails.

View file

@ -0,0 +1,14 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: use-generate-existing-on-policy-update
spec:
steps:
- name: step-01
try:
- apply:
expect:
- check:
($error != null): true
file: policy.yaml

View file

@ -0,0 +1,32 @@
apiVersion: kyverno.io/v1
kind: Policy
metadata:
name: generate-policy
namespace: default
spec:
generateExistingOnPolicyUpdate: true
rules:
- name: generate-rule
match:
any:
- resources:
kinds:
- Namespace
selector:
matchLabels:
color: blue
generate:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
name: default-deny
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
metadata:
labels:
created-by: kyverno
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress