From 1eda4789d1c666a5b8eac7b0525aa1b847f6d155 Mon Sep 17 00:00:00 2001 From: Khaled Emara <khaled.emara@nirmata.com> Date: Tue, 6 Feb 2024 19:03:32 +0200 Subject: [PATCH] test(globalcontext): add e2e tests (#9661) * fix(globalcontext): validation Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): use existence instead of ready for now Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): improve not ready error message Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): allow any APICall Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): prevent double marshal Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * test(globalcontext): add e2e tests Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): move vaildation to OpenAPI V3 Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> --------- Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com> --- api/kyverno/v1/common_types.go | 1 + .../v2alpha1/global_context_entry_types.go | 3 -- pkg/controllers/webhook/controller.go | 4 +-- pkg/engine/context/loaders/globalcontext.go | 11 +++++-- pkg/globalcontext/externalapi/entry.go | 1 - pkg/validation/policy/validate.go | 32 +++++++++++++++--- .../globalcontext/apicall-correct/README.md | 11 +++++++ .../apicall-correct/chainsaw-test.yaml | 23 +++++++++++++ .../clusterpolicy-succeeded.yaml | 9 +++++ .../apicall-correct/clusterpolicy.yaml | 33 +++++++++++++++++++ .../apicall-correct/gctxentry.yaml | 8 +++++ .../apicall-correct/main-deployment.yaml | 22 +++++++++++++ .../apicall-correct/namespace.yaml | 4 +++ .../new-deployment-exists.yaml | 7 ++++ .../apicall-correct/new-deployment.yaml | 22 +++++++++++++ .../globalcontext/apicall-not-exist/README.md | 11 +++++++ .../apicall-not-exist/chainsaw-test.yaml | 26 +++++++++++++++ .../clusterpolicy-failed.yaml | 9 +++++ .../apicall-not-exist/clusterpolicy.yaml | 33 +++++++++++++++++++ .../apicall-not-exist/gctxentry.yaml | 8 +++++ .../apicall-not-exist/main-deployment.yaml | 22 +++++++++++++ .../apicall-not-exist/namespace.yaml | 4 +++ .../apicall-not-exist/new-deployment.yaml | 22 +++++++++++++ .../globalcontext/resource-correct/README.md | 11 +++++++ .../resource-correct/chainsaw-test.yaml | 23 +++++++++++++ .../clusterpolicy-succeeded.yaml | 9 +++++ .../resource-correct/clusterpolicy.yaml | 33 +++++++++++++++++++ .../resource-correct/gctxentry.yaml | 10 ++++++ .../resource-correct/main-deployment.yaml | 22 +++++++++++++ .../resource-correct/namespace.yaml | 4 +++ .../new-deployment-exists.yaml | 7 ++++ .../resource-correct/new-deployment.yaml | 22 +++++++++++++ .../resource-not-exist/README.md | 11 +++++++ .../resource-not-exist/chainsaw-test.yaml | 26 +++++++++++++++ .../clusterpolicy-failed.yaml | 9 +++++ .../resource-not-exist/clusterpolicy.yaml | 33 +++++++++++++++++++ .../resource-not-exist/gctxentry.yaml | 10 ++++++ .../resource-not-exist/main-deployment.yaml | 22 +++++++++++++ .../resource-not-exist/namespace.yaml | 4 +++ .../resource-not-exist/new-deployment.yaml | 22 +++++++++++++ 40 files changed, 590 insertions(+), 14 deletions(-) create mode 100644 test/conformance/chainsaw/globalcontext/apicall-correct/README.md create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/chainsaw-test.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy-succeeded.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/gctxentry.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/main-deployment.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/namespace.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment-exists.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment.yaml create mode 100644 test/conformance/chainsaw/globalcontext/apicall-not-exist/README.md create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/chainsaw-test.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy-failed.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/gctxentry.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/main-deployment.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/namespace.yaml create mode 100755 test/conformance/chainsaw/globalcontext/apicall-not-exist/new-deployment.yaml create mode 100644 test/conformance/chainsaw/globalcontext/resource-correct/README.md create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/chainsaw-test.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy-succeeded.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/gctxentry.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/main-deployment.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/namespace.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/new-deployment-exists.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-correct/new-deployment.yaml create mode 100644 test/conformance/chainsaw/globalcontext/resource-not-exist/README.md create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/chainsaw-test.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy-failed.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/gctxentry.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/main-deployment.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/namespace.yaml create mode 100755 test/conformance/chainsaw/globalcontext/resource-not-exist/new-deployment.yaml diff --git a/api/kyverno/v1/common_types.go b/api/kyverno/v1/common_types.go index 906572b59f..0d641583c0 100644 --- a/api/kyverno/v1/common_types.go +++ b/api/kyverno/v1/common_types.go @@ -97,6 +97,7 @@ type ContextEntry struct { Variable *Variable `json:"variable,omitempty" yaml:"variable,omitempty"` // GlobalContextEntryReference is a reference to a cached global context entry. + // +kubebuilder:validation:Required GlobalReference *GlobalContextEntryReference `json:"globalReference,omitempty" yaml:"globalReference,omitempty"` } diff --git a/api/kyverno/v2alpha1/global_context_entry_types.go b/api/kyverno/v2alpha1/global_context_entry_types.go index ba142bb591..2273a8c955 100644 --- a/api/kyverno/v2alpha1/global_context_entry_types.go +++ b/api/kyverno/v2alpha1/global_context_entry_types.go @@ -142,9 +142,6 @@ type ExternalAPICall struct { // Validate implements programmatic validation func (e *ExternalAPICall) Validate(path *field.Path) (errs field.ErrorList) { - if e.Service.URL == "" { - errs = append(errs, field.Required(path.Child("url"), "An External API Call entry requires a url")) - } if e.RefreshInterval.Duration == 0*time.Second { errs = append(errs, field.Required(path.Child("refreshIntervalSeconds"), "A Resource entry requires a refresh interval greater than 0 seconds")) } diff --git a/pkg/controllers/webhook/controller.go b/pkg/controllers/webhook/controller.go index b3f87711cf..d55f175386 100644 --- a/pkg/controllers/webhook/controller.go +++ b/pkg/controllers/webhook/controller.go @@ -426,7 +426,7 @@ func (c *controller) reconcileMutatingWebhookConfiguration(ctx context.Context, func (c *controller) isGlobalContextEntryReady(name string, gctxentries []*kyvernov2alpha1.GlobalContextEntry) bool { for _, gctxentry := range gctxentries { if gctxentry.Name == name { - return gctxentry.Status.Ready + return true } } return false @@ -466,7 +466,7 @@ func (c *controller) updatePolicyStatuses(ctx context.Context) error { for _, ctxEntry := range rule.Context { if ctxEntry.GlobalReference != nil { if !c.isGlobalContextEntryReady(ctxEntry.GlobalReference.Name, gctxentries) { - ready, message = false, "Not ready yet" + ready, message = false, "global context entry not ready" break } } diff --git a/pkg/engine/context/loaders/globalcontext.go b/pkg/engine/context/loaders/globalcontext.go index fb767c6b36..f7c30335b9 100644 --- a/pkg/engine/context/loaders/globalcontext.go +++ b/pkg/engine/context/loaders/globalcontext.go @@ -100,9 +100,14 @@ func (g *gctxLoader) loadGctxData() ([]byte, error) { return nil, err } - jsonData, err := json.Marshal(data) - if err != nil { - return nil, err + var jsonData []byte + if _, ok := data.([]byte); ok { + jsonData = data.([]byte) + } else { + jsonData, err = json.Marshal(data) + if err != nil { + return nil, err + } } g.logger.V(6).Info("fetched json data", "name", g.entry.Name, "jsondata", jsonData) diff --git a/pkg/globalcontext/externalapi/entry.go b/pkg/globalcontext/externalapi/entry.go index 8e3098ac9b..b035074ee0 100644 --- a/pkg/globalcontext/externalapi/entry.go +++ b/pkg/globalcontext/externalapi/entry.go @@ -70,6 +70,5 @@ func (e *entry) setData(data any) { } func doCall(ctx context.Context, caller apicall.Caller, call kyvernov1.APICall) (any, error) { - // TODO: unmarshall json ? return caller.Execute(ctx, &call) } diff --git a/pkg/validation/policy/validate.go b/pkg/validation/policy/validate.go index 38c6d09512..1d664c33ba 100644 --- a/pkg/validation/policy/validate.go +++ b/pkg/validation/policy/validate.go @@ -680,7 +680,7 @@ func getAllowedVariables(background bool, target bool) *regexp.Regexp { func addContextVariables(entries []kyvernov1.ContextEntry, ctx *enginecontext.MockContext) { for _, contextEntry := range entries { - if contextEntry.APICall != nil || contextEntry.ImageRegistry != nil || contextEntry.Variable != nil { + if contextEntry.APICall != nil || contextEntry.GlobalReference != nil || contextEntry.ImageRegistry != nil || contextEntry.Variable != nil { ctx.AddVariable(contextEntry.Name + "*") } @@ -1197,13 +1197,15 @@ func validateRuleContext(rule kyvernov1.Rule) error { } var err error - if entry.ConfigMap != nil && entry.APICall == nil && entry.ImageRegistry == nil && entry.Variable == nil { + if entry.ConfigMap != nil && entry.APICall == nil && entry.GlobalReference == nil && entry.ImageRegistry == nil && entry.Variable == nil { err = validateConfigMap(entry) - } else if entry.ConfigMap == nil && entry.APICall != nil && entry.ImageRegistry == nil && entry.Variable == nil { + } else if entry.ConfigMap == nil && entry.APICall != nil && entry.GlobalReference == nil && entry.ImageRegistry == nil && entry.Variable == nil { err = validateAPICall(entry) - } else if entry.ConfigMap == nil && entry.APICall == nil && entry.ImageRegistry != nil && entry.Variable == nil { + } else if entry.ConfigMap == nil && entry.APICall == nil && entry.GlobalReference != nil && entry.ImageRegistry == nil && entry.Variable == nil { + err = validateGlobalReference(entry) + } else if entry.ConfigMap == nil && entry.APICall == nil && entry.GlobalReference == nil && entry.ImageRegistry != nil && entry.Variable == nil { err = validateImageRegistry(entry) - } else if entry.ConfigMap == nil && entry.APICall == nil && entry.ImageRegistry == nil && entry.Variable != nil { + } else if entry.ConfigMap == nil && entry.APICall == nil && entry.GlobalReference == nil && entry.ImageRegistry == nil && entry.Variable != nil { err = validateVariable(entry) } else { return fmt.Errorf("exactly one of configMap or apiCall or imageRegistry or variable is required for context entries") @@ -1311,6 +1313,26 @@ func validateAPICall(entry kyvernov1.ContextEntry) error { return nil } +func validateGlobalReference(entry kyvernov1.ContextEntry) error { + if entry.GlobalReference == nil { + return nil + } + + // If JMESPath contains variables, the validation will fail because it's not + // possible to infer which value will be inserted by the variable + // Skip validation if a variable is detected + + jmesPath := variables.ReplaceAllVars(entry.GlobalReference.JMESPath, func(s string) string { return "kyvernojmespathvariable" }) + + if !strings.Contains(jmesPath, "kyvernojmespathvariable") && entry.GlobalReference.JMESPath != "" { + if _, err := jmespath.NewParser().Parse(entry.GlobalReference.JMESPath); err != nil { + return fmt.Errorf("failed to parse JMESPath %s: %v", entry.GlobalReference.JMESPath, err) + } + } + + return nil +} + func validateImageRegistry(entry kyvernov1.ContextEntry) error { if entry.ImageRegistry.Reference == "" { return fmt.Errorf("a ref is required for imageRegistry context entry") diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/README.md b/test/conformance/chainsaw/globalcontext/apicall-correct/README.md new file mode 100644 index 0000000000..e4830f2597 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/README.md @@ -0,0 +1,11 @@ +## Description + +This test verifies that Global Context Entries are evaluated correctly. + +## Expected Behavior + +`new-deployment` should be created. + +## Reference Issues + + diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/chainsaw-test.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/chainsaw-test.yaml new file mode 100755 index 0000000000..4c74ff5137 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/chainsaw-test.yaml @@ -0,0 +1,23 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: resource-correct +spec: + steps: + - name: scenario + try: + - apply: + file: namespace.yaml + - apply: + file: main-deployment.yaml + - apply: + file: gctxentry.yaml + - apply: + file: clusterpolicy.yaml + - apply: + file: new-deployment.yaml + - assert: + file: clusterpolicy-succeeded.yaml + - assert: + file: new-deployment-exists.yaml diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy-succeeded.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy-succeeded.yaml new file mode 100755 index 0000000000..47b54ce1f2 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy-succeeded.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy.yaml new file mode 100755 index 0000000000..1c459b0a16 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/clusterpolicy.yaml @@ -0,0 +1,33 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +spec: + validationFailureAction: Enforce + failurePolicy: Fail + rules: + - name: main-deployment-exists + context: + - name: deploymentCount + globalReference: + name: deployments + jmesPath: "items | length(@)" + match: + all: + - resources: + kinds: + - Pod + preconditions: + all: + - key: '{{ request.operation }}' + operator: AnyIn + value: + - CREATE + - UPDATE + validate: + deny: + conditions: + any: + - key: "{{ deploymentCount }}" + operator: Equal + value: 0 diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/gctxentry.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/gctxentry.yaml new file mode 100755 index 0000000000..46d1da9f8f --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/gctxentry.yaml @@ -0,0 +1,8 @@ +apiVersion: kyverno.io/v2alpha1 +kind: GlobalContextEntry +metadata: + name: deployments +spec: + apiCall: + urlPath: "/apis/apps/v1/namespaces/test-globalcontext/deployments" + refreshInterval: 10s diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/main-deployment.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/main-deployment.yaml new file mode 100755 index 0000000000..bd269e4252 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/main-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: main-deployment + namespace: test-globalcontext + labels: + app: main-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: main-deployment + template: + metadata: + labels: + app: main-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/namespace.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/namespace.yaml new file mode 100755 index 0000000000..9310828450 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-globalcontext diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment-exists.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment-exists.yaml new file mode 100755 index 0000000000..969c3bc053 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment-exists.yaml @@ -0,0 +1,7 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: new-deployment + namespace: test-globalcontext + labels: + app: new-deployment diff --git a/test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment.yaml b/test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment.yaml new file mode 100755 index 0000000000..343cbc492b --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-correct/new-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: new-deployment + namespace: test-globalcontext + labels: + app: new-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: new-deployment + template: + metadata: + labels: + app: new-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/README.md b/test/conformance/chainsaw/globalcontext/apicall-not-exist/README.md new file mode 100644 index 0000000000..8e678c56af --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/README.md @@ -0,0 +1,11 @@ +## Description + +This test verifies that policies are not ready if referenced Global Context Entries don't exist. + +## Expected Behavior + +`new-deployment` should not be created because the policy is not ready. + +## Reference Issues + + diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/chainsaw-test.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/chainsaw-test.yaml new file mode 100755 index 0000000000..5c5984cf95 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/chainsaw-test.yaml @@ -0,0 +1,26 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: resource-not-exist +spec: + steps: + - name: setup + try: + - apply: + file: namespace.yaml + - apply: + file: main-deployment.yaml + - apply: + file: gctxentry.yaml + - apply: + file: clusterpolicy.yaml + - assert: + file: clusterpolicy-failed.yaml + - name: negative + try: + - apply: + expect: + - check: + ($error != null): true + file: new-deployment.yaml diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy-failed.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy-failed.yaml new file mode 100755 index 0000000000..8e33aa69ed --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy-failed.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +status: + conditions: + - reason: Failed + status: "False" + type: Ready diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy.yaml new file mode 100755 index 0000000000..b1ae1169a3 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/clusterpolicy.yaml @@ -0,0 +1,33 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +spec: + validationFailureAction: Enforce + failurePolicy: Fail + rules: + - name: main-deployment-exists + context: + - name: deploymentCount + globalReference: + name: non-existent-reference + jmesPath: "items | length(@)" + match: + all: + - resources: + kinds: + - Pod + preconditions: + all: + - key: '{{ request.operation }}' + operator: AnyIn + value: + - CREATE + - UPDATE + validate: + deny: + conditions: + any: + - key: "{{ deploymentCount }}" + operator: Equal + value: 0 diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/gctxentry.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/gctxentry.yaml new file mode 100755 index 0000000000..46d1da9f8f --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/gctxentry.yaml @@ -0,0 +1,8 @@ +apiVersion: kyverno.io/v2alpha1 +kind: GlobalContextEntry +metadata: + name: deployments +spec: + apiCall: + urlPath: "/apis/apps/v1/namespaces/test-globalcontext/deployments" + refreshInterval: 10s diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/main-deployment.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/main-deployment.yaml new file mode 100755 index 0000000000..bd269e4252 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/main-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: main-deployment + namespace: test-globalcontext + labels: + app: main-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: main-deployment + template: + metadata: + labels: + app: main-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/namespace.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/namespace.yaml new file mode 100755 index 0000000000..9310828450 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-globalcontext diff --git a/test/conformance/chainsaw/globalcontext/apicall-not-exist/new-deployment.yaml b/test/conformance/chainsaw/globalcontext/apicall-not-exist/new-deployment.yaml new file mode 100755 index 0000000000..343cbc492b --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/apicall-not-exist/new-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: new-deployment + namespace: test-globalcontext + labels: + app: new-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: new-deployment + template: + metadata: + labels: + app: new-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/README.md b/test/conformance/chainsaw/globalcontext/resource-correct/README.md new file mode 100644 index 0000000000..e4830f2597 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/README.md @@ -0,0 +1,11 @@ +## Description + +This test verifies that Global Context Entries are evaluated correctly. + +## Expected Behavior + +`new-deployment` should be created. + +## Reference Issues + + diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/chainsaw-test.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/chainsaw-test.yaml new file mode 100755 index 0000000000..4c74ff5137 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/chainsaw-test.yaml @@ -0,0 +1,23 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: resource-correct +spec: + steps: + - name: scenario + try: + - apply: + file: namespace.yaml + - apply: + file: main-deployment.yaml + - apply: + file: gctxentry.yaml + - apply: + file: clusterpolicy.yaml + - apply: + file: new-deployment.yaml + - assert: + file: clusterpolicy-succeeded.yaml + - assert: + file: new-deployment-exists.yaml diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy-succeeded.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy-succeeded.yaml new file mode 100755 index 0000000000..47b54ce1f2 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy-succeeded.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy.yaml new file mode 100755 index 0000000000..35e172629e --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/clusterpolicy.yaml @@ -0,0 +1,33 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +spec: + validationFailureAction: Enforce + failurePolicy: Fail + rules: + - name: main-deployment-exists + context: + - name: deploymentCount + globalReference: + name: deployments + jmesPath: "length(@)" + match: + all: + - resources: + kinds: + - Pod + preconditions: + all: + - key: '{{ request.operation }}' + operator: AnyIn + value: + - CREATE + - UPDATE + validate: + deny: + conditions: + any: + - key: "{{ deploymentCount }}" + operator: Equal + value: 0 diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/gctxentry.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/gctxentry.yaml new file mode 100755 index 0000000000..334874bd89 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/gctxentry.yaml @@ -0,0 +1,10 @@ +apiVersion: kyverno.io/v2alpha1 +kind: GlobalContextEntry +metadata: + name: deployments +spec: + kubernetesResource: + group: apps + version: v1 + resource: deployments + namespace: test-globalcontext diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/main-deployment.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/main-deployment.yaml new file mode 100755 index 0000000000..bd269e4252 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/main-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: main-deployment + namespace: test-globalcontext + labels: + app: main-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: main-deployment + template: + metadata: + labels: + app: main-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/namespace.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/namespace.yaml new file mode 100755 index 0000000000..9310828450 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-globalcontext diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/new-deployment-exists.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/new-deployment-exists.yaml new file mode 100755 index 0000000000..969c3bc053 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/new-deployment-exists.yaml @@ -0,0 +1,7 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: new-deployment + namespace: test-globalcontext + labels: + app: new-deployment diff --git a/test/conformance/chainsaw/globalcontext/resource-correct/new-deployment.yaml b/test/conformance/chainsaw/globalcontext/resource-correct/new-deployment.yaml new file mode 100755 index 0000000000..343cbc492b --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-correct/new-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: new-deployment + namespace: test-globalcontext + labels: + app: new-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: new-deployment + template: + metadata: + labels: + app: new-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/README.md b/test/conformance/chainsaw/globalcontext/resource-not-exist/README.md new file mode 100644 index 0000000000..8e678c56af --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/README.md @@ -0,0 +1,11 @@ +## Description + +This test verifies that policies are not ready if referenced Global Context Entries don't exist. + +## Expected Behavior + +`new-deployment` should not be created because the policy is not ready. + +## Reference Issues + + diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/chainsaw-test.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/chainsaw-test.yaml new file mode 100755 index 0000000000..5c5984cf95 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/chainsaw-test.yaml @@ -0,0 +1,26 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: resource-not-exist +spec: + steps: + - name: setup + try: + - apply: + file: namespace.yaml + - apply: + file: main-deployment.yaml + - apply: + file: gctxentry.yaml + - apply: + file: clusterpolicy.yaml + - assert: + file: clusterpolicy-failed.yaml + - name: negative + try: + - apply: + expect: + - check: + ($error != null): true + file: new-deployment.yaml diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy-failed.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy-failed.yaml new file mode 100755 index 0000000000..8e33aa69ed --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy-failed.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +status: + conditions: + - reason: Failed + status: "False" + type: Ready diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy.yaml new file mode 100755 index 0000000000..0c86d8843b --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/clusterpolicy.yaml @@ -0,0 +1,33 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: namespace-has-coordinator +spec: + validationFailureAction: Enforce + failurePolicy: Fail + rules: + - name: main-deployment-exists + context: + - name: deploymentCount + globalReference: + name: non-existent-reference + jmesPath: "length(@)" + match: + all: + - resources: + kinds: + - Pod + preconditions: + all: + - key: '{{ request.operation }}' + operator: AnyIn + value: + - CREATE + - UPDATE + validate: + deny: + conditions: + any: + - key: "{{ deploymentCount }}" + operator: Equal + value: 0 diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/gctxentry.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/gctxentry.yaml new file mode 100755 index 0000000000..334874bd89 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/gctxentry.yaml @@ -0,0 +1,10 @@ +apiVersion: kyverno.io/v2alpha1 +kind: GlobalContextEntry +metadata: + name: deployments +spec: + kubernetesResource: + group: apps + version: v1 + resource: deployments + namespace: test-globalcontext diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/main-deployment.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/main-deployment.yaml new file mode 100755 index 0000000000..bd269e4252 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/main-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: main-deployment + namespace: test-globalcontext + labels: + app: main-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: main-deployment + template: + metadata: + labels: + app: main-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/namespace.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/namespace.yaml new file mode 100755 index 0000000000..9310828450 --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-globalcontext diff --git a/test/conformance/chainsaw/globalcontext/resource-not-exist/new-deployment.yaml b/test/conformance/chainsaw/globalcontext/resource-not-exist/new-deployment.yaml new file mode 100755 index 0000000000..343cbc492b --- /dev/null +++ b/test/conformance/chainsaw/globalcontext/resource-not-exist/new-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: new-deployment + namespace: test-globalcontext + labels: + app: new-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: new-deployment + template: + metadata: + labels: + app: new-deployment + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80