From faa7ee90c1095fecb3b2b7b37fb325fea7622cd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?=
 <charled.breteche@gmail.com>
Date: Mon, 30 Jan 2023 17:19:12 +0100
Subject: [PATCH] test: add more engine api package tests (#6161)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
---
 api/kyverno/v1/spec_types.go          |  16 +-
 pkg/engine/api/engineresponse_test.go | 273 ++++++++++++++++++++++++++
 2 files changed, 283 insertions(+), 6 deletions(-)

diff --git a/api/kyverno/v1/spec_types.go b/api/kyverno/v1/spec_types.go
index 4b76600ace..f94614d5df 100644
--- a/api/kyverno/v1/spec_types.go
+++ b/api/kyverno/v1/spec_types.go
@@ -14,15 +14,20 @@ type ValidationFailureAction string
 
 // Policy Reporting Modes
 const (
+	// auditOld doesn't block the request on failure
+	// DEPRECATED: use Audit instead
+	auditOld ValidationFailureAction = "audit"
 	// enforceOld blocks the request on failure
-	// DEPRECATED: use enforce instead
+	// DEPRECATED: use Enforce instead
 	enforceOld ValidationFailureAction = "enforce"
-	// enforce blocks the request on failure
-	enforce ValidationFailureAction = "Enforce"
+	// Enforce blocks the request on failure
+	Enforce ValidationFailureAction = "Enforce"
+	// Audit doesn't block the request on failure
+	Audit ValidationFailureAction = "Audit"
 )
 
 func (a ValidationFailureAction) Enforce() bool {
-	return a == enforce || a == enforceOld
+	return a == Enforce || a == enforceOld
 }
 
 func (a ValidationFailureAction) Audit() bool {
@@ -30,8 +35,7 @@ func (a ValidationFailureAction) Audit() bool {
 }
 
 func (a ValidationFailureAction) IsValid() bool {
-	// ValidationFailureAction should either be enforce / audit
-	return a.Enforce() || a.Audit()
+	return a == enforceOld || a == auditOld || a == Enforce || a == Audit
 }
 
 type ValidationFailureActionOverride struct {
diff --git a/pkg/engine/api/engineresponse_test.go b/pkg/engine/api/engineresponse_test.go
index ba12ec66a8..4c0e21b6bc 100644
--- a/pkg/engine/api/engineresponse_test.go
+++ b/pkg/engine/api/engineresponse_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 )
 
@@ -719,3 +720,275 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
 		})
 	}
 }
+
+func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
+	resource := unstructured.Unstructured{}
+	resource.SetNamespace("foo")
+	type fields struct {
+		PatchedResource unstructured.Unstructured
+		Policy          kyvernov1.PolicyInterface
+		PolicyResponse  PolicyResponse
+		NamespaceLabels map[string]string
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   kyvernov1.ValidationFailureAction
+	}{{
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Audit,
+			},
+		},
+		want: kyvernov1.Audit,
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+			},
+		},
+		want: kyvernov1.Enforce,
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"*"},
+				}},
+			},
+		},
+		want: kyvernov1.Audit,
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     "invalid",
+					Namespaces: []string{"*"},
+				}},
+			},
+		},
+		want: kyvernov1.Enforce,
+	}, {
+		fields: fields{
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"foo"},
+				}},
+			},
+		},
+		want: kyvernov1.Audit,
+	}, {
+		fields: fields{
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"bar"},
+				}},
+			},
+		},
+		want: kyvernov1.Enforce,
+	}, {
+		fields: fields{
+			NamespaceLabels: map[string]string{
+				"foo": "bar",
+			},
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action: kyvernov1.Audit,
+					NamespaceSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"bar": "foo",
+						},
+					},
+				}},
+			},
+		},
+		want: kyvernov1.Enforce,
+	}, {
+		fields: fields{
+			NamespaceLabels: map[string]string{
+				"foo": "bar",
+			},
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action: kyvernov1.Audit,
+					NamespaceSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"foo": "bar",
+						},
+					},
+				}},
+			},
+		},
+		want: kyvernov1.Audit,
+	}, {
+		fields: fields{
+			NamespaceLabels: map[string]string{
+				"foo": "bar",
+			},
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"foo"},
+					NamespaceSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"bar": "foo",
+						},
+					},
+				}},
+			},
+		},
+		want: kyvernov1.Enforce,
+	}, {
+		fields: fields{
+			NamespaceLabels: map[string]string{
+				"foo": "bar",
+			},
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"bar"},
+					NamespaceSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"foo": "bar",
+						},
+					},
+				}},
+			},
+		},
+		want: kyvernov1.Enforce,
+	}, {
+		fields: fields{
+			NamespaceLabels: map[string]string{
+				"foo": "bar",
+			},
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"foo"},
+					NamespaceSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"foo": "bar",
+						},
+					},
+				}},
+			},
+		},
+		want: kyvernov1.Audit,
+	}, {
+		fields: fields{
+			NamespaceLabels: map[string]string{
+				"foo": "bar",
+			},
+			PatchedResource: resource,
+			PolicyResponse: PolicyResponse{
+				ValidationFailureAction: kyvernov1.Enforce,
+				ValidationFailureActionOverrides: []ValidationFailureActionOverride{{
+					Action:     kyvernov1.Audit,
+					Namespaces: []string{"*"},
+					NamespaceSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"foo": "bar",
+						},
+					},
+				}},
+			},
+		},
+		want: kyvernov1.Audit,
+	}}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			er := &EngineResponse{
+				PatchedResource: tt.fields.PatchedResource,
+				Policy:          tt.fields.Policy,
+				PolicyResponse:  tt.fields.PolicyResponse,
+				NamespaceLabels: tt.fields.NamespaceLabels,
+			}
+			if got := er.GetValidationFailureAction(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("EngineResponse.GetValidationFailureAction() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestEngineResponse_GetPatches(t *testing.T) {
+	type fields struct {
+		PatchedResource unstructured.Unstructured
+		Policy          kyvernov1.PolicyInterface
+		PolicyResponse  PolicyResponse
+		NamespaceLabels map[string]string
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   [][]byte
+	}{{}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				Rules: nil,
+			},
+		},
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				Rules: []RuleResponse{},
+			},
+		},
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				Rules: []RuleResponse{{}},
+			},
+		},
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				Rules: []RuleResponse{{}, {
+					Patches: [][]byte{{0, 1, 2}, {3, 4, 5}},
+				}},
+			},
+		},
+		want: [][]byte{{0, 1, 2}, {3, 4, 5}},
+	}, {
+		fields: fields{
+			PolicyResponse: PolicyResponse{
+				Rules: []RuleResponse{{}, {
+					Patches: [][]byte{{0, 1, 2}, {3, 4, 5}},
+				}, {
+					Patches: [][]byte{{7, 8, 9}},
+				}},
+			},
+		},
+		want: [][]byte{{0, 1, 2}, {3, 4, 5}, {7, 8, 9}},
+	}}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			er := EngineResponse{
+				PatchedResource: tt.fields.PatchedResource,
+				Policy:          tt.fields.Policy,
+				PolicyResponse:  tt.fields.PolicyResponse,
+				NamespaceLabels: tt.fields.NamespaceLabels,
+			}
+			if got := er.GetPatches(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("EngineResponse.GetPatches() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}