Repository: kyverno/kyverno
Pull request #2103 (2021-07-07 05:53:08)

Fix Helmchart doesn't respect metricsService.create flag
Signed-off-by: Vyankatesh <vyankateshkd@gmail.com>

## Related issue

closes https://github.com/kyverno/kyverno/issues/1397
<!--
Please link the GitHub issue this pull request resolves in the format of `#1234`. If you discussed this change
with a maintainer, please mention her/him using the `@` syntax (e.g. `@JimBugwadia`).

If this change neither resolves an existing issue nor has sign-off from one of the maintainers, there is a
chance substantial changes will be requested or that the changes will be rejected.

You can discuss changes with maintainers in the [Kyverno Slack Channel](https://kubernetes.slack.com/).
-->

## What type of PR is this
Fix Helmchart doesn't respect metricsService.create flag.
<!--

> Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading white spaces from that line:
>
> /kind api-change
> /kind bug
> /kind cleanup
> /kind design
> /kind documentation
> /kind failing-test
> /kind feature
-->

## Proposed Changes

<!--
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. 

***NOTE***: If this PR results in new or altered behavior which is user facing, you **MUST** read and follow the steps outlined in the [PR documentation guide](pr_documentation.md) and add Proof Manifests as defined below.
-->

### Proof Manifests

Install helmchart with metricsService.create: false in helm values
check kyverno-svc-metrics service should not created
<!--
Read and follow the [PR documentation guide](https://github.com/kyverno/kyverno/blob/main/.github/pr_documentation.md) for more details first. This section is for pasting your YAML manifests (Kubernetes resources and Kyverno policies) which allow maintainers to prove the intended functionality is achieved by your PR. Please use proper fenced code block formatting, for example:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: roles-dictionary
  namespace: default
data:
  allowed-roles: "[\"cluster-admin\", \"cluster-operator\", \"tenant-admin\"]"
```
-->

## Checklist

<!--
Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of
them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.
-->

- [x] I have read the [contributing guidelines](https://github.com/kyverno/kyverno/blob/main/CONTRIBUTING.md).
- [x] I have added tests that prove my fix is effective or that my feature works.
- [x] My PR contains new or altered behavior to Kyverno and
  - [] I have added or changed [the documentation](https://github.com/kyverno/website) myself in an existing PR and the link is:
  <!-- Uncomment to link to the PR -->
  <!-- https://github.com/kyverno/website/pull/123 -->
  - [] I have raised an issue in [kyverno/website](https://github.com/kyverno/website) to track the doc update and the link is:
  <!-- Uncomment to link to the issue -->
  <!-- https://github.com/kyverno/website/issues/1 -->
  - [] I have read the [PR documentation guide](https://github.com/kyverno/kyverno/blob/main/.github/pr_documentation.md) and followed the process including adding proof manifests to this PR.

## Further Comments

<!--
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution
you did and what alternatives you considered, etc...
-->



Patch:
diff --git a/charts/kyverno/README.md b/charts/kyverno/README.md
index 4663ecb78..a07458378 100644
--- a/charts/kyverno/README.md
+++ b/charts/kyverno/README.md
@@ -65,6 +65,7 @@ The following table lists the configurable parameters of the kyverno chart and t
 | Parameter                          | Description                                                                                                                                                                                                                                                  | Default                                                                                                                                                                           |
 | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | `affinity`                         | node/pod affinities                                                                                                                                                                                                                                          | `nil`                                                                                                                                                                             |
+| `topologySpreadConstraints`        | node/pod topology spread constrains                                                                                                                                                                                                                          | `[]`                                                                                                                                                                             |
 | `createSelfSignedCert`             | generate a self signed cert and certificate authority. Kyverno defaults to using kube-controller-manager CA-signed certificate or existing cert secret if false.                                                                                             | `false`                                                                                                                                                                           |
 | `config.existingConfig`            | existing Kubernetes configmap to use for the resource filters configuration                                                                                                                                                                                  | `nil`                                                                                                                                                                             |
 | `config.resourceFilters`           | list of resource types to be skipped by kyverno policy engine. See [documentation](https://kyverno.io/docs/installation/#resource-filters) for details | `[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][SelfSubjectAccessReview,*,*][*,kyverno,*][Binding,*,*][ReplicaSet,*,*][ReportChangeRequest,*,*][ClusterReportChangeRequest,*,*]` |
diff --git a/charts/kyverno/templates/deployment.yaml b/charts/kyverno/templates/deployment.yaml
index 74472e6b5..509937061 100644
--- a/charts/kyverno/templates/deployment.yaml
+++ b/charts/kyverno/templates/deployment.yaml
@@ -35,6 +35,9 @@ spec:
       {{- with .Values.tolerations }}
       tolerations: {{ tpl (toYaml .) $ | nindent 8 }}
       {{- end }}
+      {{- with .Values.topologySpreadConstraints }}
+      topologySpreadConstraints: {{ tpl (toYaml .) $ | nindent 8 }}
+      {{- end }}
       serviceAccountName: {{ template "kyverno.serviceAccountName" . }}
       {{- if .Values.priorityClassName }}
       priorityClassName: {{ .Values.priorityClassName | quote }}
diff --git a/charts/kyverno/templates/service.yaml b/charts/kyverno/templates/service.yaml
index ca167c05e..0f234f74a 100644
--- a/charts/kyverno/templates/service.yaml
+++ b/charts/kyverno/templates/service.yaml
@@ -21,6 +21,7 @@ spec:
     app: kyverno
   type: {{ .Values.service.type }}
 ---
+{{- if .Values.metricsService.create }}
 apiVersion: v1
 kind: Service
 metadata:
@@ -43,3 +44,4 @@ spec:
   selector: {{ include "kyverno.matchLabels" . | nindent 4 }}
     app: kyverno
   type: {{ .Values.metricsService.type }}
+  {{- end -}}
diff --git a/charts/kyverno/values.yaml b/charts/kyverno/values.yaml
index 2b76cbd77..332e250ea 100644
--- a/charts/kyverno/values.yaml
+++ b/charts/kyverno/values.yaml
@@ -160,6 +160,8 @@ service:
   nodePort:
   annotations: {}
 
+topologySpreadConstraints: []
+
 metricsService:
   create: true
   type: ClusterIP
diff --git a/pkg/engine/generation.go b/pkg/engine/generation.go
index a8487170f..866f62249 100644
--- a/pkg/engine/generation.go
+++ b/pkg/engine/generation.go
@@ -108,7 +108,7 @@ func filterRule(rule kyverno.Rule, policyContext *PolicyContext) *response.RuleR
 	}
 
 	// evaluate pre-conditions
-	if !variables.EvaluateConditions(logger, ctx, copyConditions) {
+	if !variables.EvaluateConditions(logger, ctx, copyConditions, true) {
 		logger.V(4).Info("preconditions not satisfied, skipping rule", "rule", rule.Name)
 		return nil
 	}
diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go
index 8d8c44119..e1233d5c0 100644
--- a/pkg/engine/mutation.go
+++ b/pkg/engine/mutation.go
@@ -85,7 +85,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
 		}
 		// evaluate pre-conditions
 		// - handle variable substitutions
-		if !variables.EvaluateConditions(logger, ctx, copyConditions) {
+		if !variables.EvaluateConditions(logger, ctx, copyConditions, true) {
 			logger.V(3).Info("resource fails the preconditions")
 			continue
 		}
diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go
index 382dce347..f64df107c 100644
--- a/pkg/engine/validation.go
+++ b/pkg/engine/validation.go
@@ -7,6 +7,7 @@ import (
 	"time"
 
 	"github.com/go-logr/logr"
+	gojmespath "github.com/jmespath/go-jmespath"
 	kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
 	"github.com/kyverno/kyverno/pkg/engine/common"
 	"github.com/kyverno/kyverno/pkg/engine/context"
@@ -113,7 +114,7 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
 			continue
 		}
 		// evaluate pre-conditions
-		if !variables.EvaluateConditions(log, ctx.JSONContext, preconditionsCopy) {
+		if !variables.EvaluateConditions(log, ctx.JSONContext, preconditionsCopy, true) {
 			log.V(4).Info("resource fails the preconditions")
 			continue
 		}
@@ -129,7 +130,12 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
 			incrementAppliedCount(resp)
 			resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResp)
 
-			log.Error(err, "failed to substitute variables, skip current rule", "rule name", rule.Name)
+			switch err.(type) {
+			case gojmespath.NotFoundError:
+				log.V(2).Info("failed to substitute variables, skip current rule", "info", err.Error(), "rule name", rule.Name)
+			default:
+				log.Error(err, "failed to substitute variables, skip current rule", "rule name", rule.Name)
+			}
 			continue
 		}
 
@@ -147,7 +153,7 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
 				log.V(2).Info("wrongfully configured data", "reason", err.Error())
 				continue
 			}
-			deny := variables.EvaluateConditions(log, ctx.JSONContext, denyConditionsCopy)
+			deny := variables.EvaluateConditions(log, ctx.JSONContext, denyConditionsCopy, false)
 			ruleResp := response.RuleResponse{
 				Name:    rule.Name,
 				Type:    utils.Validation.String(),
diff --git a/pkg/engine/variables/evaluate.go b/pkg/engine/variables/evaluate.go
index c4782d89b..fa7632167 100644
--- a/pkg/engine/variables/evaluate.go
+++ b/pkg/engine/variables/evaluate.go
@@ -8,28 +8,28 @@ import (
 )
 
 //Evaluate evaluates the condition
-func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyverno.Condition) bool {
+func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyverno.Condition, isPreCondition bool) bool {
 	// get handler for the operator
 	handle := operator.CreateOperatorHandler(log, ctx, condition.Operator, SubstituteAll)
 	if handle == nil {
 		return false
 	}
-	return handle.Evaluate(condition.Key, condition.Value)
+	return handle.Evaluate(condition.Key, condition.Value, isPreCondition)
 }
 
 //EvaluateConditions evalues all the conditions present in a slice, in a backwards compatible way
-func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions interface{}) bool {
+func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions interface{}, isPreCondition bool) bool {
 	switch typedConditions := conditions.(type) {
 	case kyverno.AnyAllConditions:
-		return evaluateAnyAllConditions(log, ctx, typedConditions)
+		return evaluateAnyAllConditions(log, ctx, typedConditions, isPreCondition)
 	case []kyverno.Condition: // backwards compatibility
-		return evaluateOldConditions(log, ctx, typedConditions)
+		return evaluateOldConditions(log, ctx, typedConditions, isPreCondition)
 	}
 	return false
 }
 
 //evaluateAnyAllConditions evaluates multiple conditions as a logical AND (all) or OR (any) operation depending on the conditions
-func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions kyverno.AnyAllConditions) bool {
+func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions kyverno.AnyAllConditions, isPreCondition bool) bool {
 	anyConditions, allConditions := conditions.AnyConditions, conditions.AllConditions
 	anyConditionsResult, allConditionsResult := true, true
 
@@ -37,7 +37,7 @@ func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, condit
 	if anyConditions != nil {
 		anyConditionsResult = false
 		for _, condition := range anyConditions {
-			if Evaluate(log, ctx, condition) {
+			if Evaluate(log, ctx, condition, isPreCondition) {
 				anyConditionsResult = true
 				break
 			}
@@ -47,7 +47,7 @@ func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, condit
 	// update the allConditionsResult if they are present
 	if allConditions != nil {
 		for _, condition := range allConditions {
-			if !Evaluate(log, ctx, condition) {
+			if !Evaluate(log, ctx, condition, isPreCondition) {
 				allConditionsResult = false
 				break
 			}
@@ -59,9 +59,9 @@ func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, condit
 }
 
 //evaluateOldConditions evaluates multiple conditions when those conditions are provided in the old manner i.e. without 'any' or 'all'
-func evaluateOldConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition) bool {
+func evaluateOldConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition, isPreCondition bool) bool {
 	for _, condition := range conditions {
-		if !Evaluate(log, ctx, condition) {
+		if !Evaluate(log, ctx, condition, isPreCondition) {
 			return false
 		}
 	}
diff --git a/pkg/engine/variables/operator/equal.go b/pkg/engine/variables/operator/equal.go
index 44f1c5751..df92dfe1b 100644
--- a/pkg/engine/variables/operator/equal.go
+++ b/pkg/engine/variables/operator/equal.go
@@ -2,11 +2,12 @@ package operator
 
 import (
 	"fmt"
-	"github.com/minio/pkg/wildcard"
 	"math"
 	"reflect"
 	"strconv"
 
+	"github.com/minio/pkg/wildcard"
+
 	"github.com/go-logr/logr"
 	"github.com/kyverno/kyverno/pkg/engine/context"
 )
@@ -28,18 +29,26 @@ type EqualHandler struct {
 }
 
 //Evaluate evaluates expression with Equal Operator
-func (eh EqualHandler) Evaluate(key, value interface{}) bool {
+func (eh EqualHandler) Evaluate(key, value interface{}, isPreCondition bool) bool {
 	var err error
 	//TODO: decouple variables from evaluation
 	// substitute the variables
 	if key, err = eh.subHandler(eh.log, eh.ctx, key); err != nil {
 		// Failed to resolve the variable
-		eh.log.Error(err, "Failed to resolve variable", "variable", key)
+		if isPreCondition {
+			eh.log.Info("Failed to resolve variable", "info", err.Error(), "variable", key)
+		} else {
+			eh.log.Error(err, "Failed to resolve variable", "variable", key)
+		}
 		return false
 	}
 	if value, err = eh.subHandler(eh.log, eh.ctx, value); err != nil {
 		// Failed to resolve the variable
-		eh.log.Error(err, "Failed to resolve variable", "variable", value)
+		if isPreCondition {
+			eh.log.Info("Failed to resolve variable", "info", err.Error(), "variable", value)
+		} else {
+			eh.log.Error(err, "Failed to resolve variable", "variable", value)
+		}
 		return false
 	}
 
diff --git a/pkg/engine/variables/operator/in.go b/pkg/engine/variables/operator/in.go
index 2bf23185c..b05d14f8d 100644
--- a/pkg/engine/variables/operator/in.go
+++ b/pkg/engine/variables/operator/in.go
@@ -27,16 +27,24 @@ type InHandler struct {
 }
 
 //Evaluate evaluates expression with In Operator
-func (in InHandler) Evaluate(key, value interface{}) bool {
+func (in InHandler) Evaluate(key, value interface{}, isPreCondition bool) bool {
 	var err error
 	// substitute the variables
 	if key, err = in.subHandler(in.log, in.ctx, key); err != nil {
-		in.log.Error(err, "Failed to resolve variable", "variable", key)
+		if isPreCondition {
+			in.log.Info("Failed to resolve variable", "info", err.Error(), "variable", key)
+		} else {
+			in.log.Error(err, "Failed to resolve variable", "variable", key)
+		}
 		return false
 	}
 
 	if value, err = in.subHandler(in.log, in.ctx, value); err != nil {
-		in.log.Error(err, "Failed to resolve variable", "variable", value)
+		if isPreCondition {
+			in.log.Info("Failed to resolve variable", "info", err.Error(), "variable", value)
+		} else {
+			in.log.Error(err, "Failed to resolve variable", "variable", value)
+		}
 		return false
 	}
 
diff --git a/pkg/engine/variables/operator/notequal.go b/pkg/engine/variables/operator/notequal.go
index 4ef424169..4020e4dbf 100644
--- a/pkg/engine/variables/operator/notequal.go
+++ b/pkg/engine/variables/operator/notequal.go
@@ -2,11 +2,12 @@ package operator
 
 import (
 	"fmt"
-	"github.com/minio/pkg/wildcard"
 	"math"
 	"reflect"
 	"strconv"
 
+	"github.com/minio/pkg/wildcard"
+
 	"github.com/go-logr/logr"
 	"github.com/kyverno/kyverno/pkg/engine/context"
 )
@@ -28,18 +29,26 @@ type NotEqualHandler struct {
 }
 
 //Evaluate evaluates expression with NotEqual Operator
-func (neh NotEqualHandler) Evaluate(key, value interface{}) bool {
+func (neh NotEqualHandler) Evaluate(key, value interface{}, isPreCondition bool) bool {
 	var err error
 	//TODO: decouple variables from evaluation
 	// substitute the variables
 	if key, err = neh.subHandler(neh.log, neh.ctx, key); err != nil {
 		// Failed to resolve the variable
-		neh.log.Error(err, "Failed to resolve variable", "variable", key)
+		if isPreCondition {
+			neh.log.Info("Failed to resolve variable", "info", err.Error(), "variable", key)
+		} else {
+			neh.log.Error(err, "Failed to resolve variable", "variable", key)
+		}
 		return false
 	}
 	if value, err = neh.subHandler(neh.log, neh.ctx, value); err != nil {
 		// Failed to resolve the variable
-		neh.log.Error(err, "Failed to resolve variable", "variable", value)
+		if isPreCondition {
+			neh.log.Info("Failed to resolve variable", "info", err.Error(), "variable", value)
+		} else {
+			neh.log.Error(err, "Failed to resolve variable", "variable", value)
+		}
 		return false
 	}
 	// key and value need to be of same type
diff --git a/pkg/engine/variables/operator/notin.go b/pkg/engine/variables/operator/notin.go
index d604c4b0d..e9cab9f0b 100644
--- a/pkg/engine/variables/operator/notin.go
+++ b/pkg/engine/variables/operator/notin.go
@@ -24,17 +24,25 @@ type NotInHandler struct {
 }
 
 //Evaluate evaluates expression with NotIn Operator
-func (nin NotInHandler) Evaluate(key, value interface{}) bool {
+func (nin NotInHandler) Evaluate(key, value interface{}, isPreCondition bool) bool {
 	var err error
 
 	// substitute the variables
 	if key, err = nin.subHandler(nin.log, nin.ctx, key); err != nil {
-		nin.log.Error(err, "Failed to resolve variable", "variable", key)
+		if isPreCondition {
+			nin.log.Info("Failed to resolve variable", "info", err.Error(), "variable", key)
+		} else {
+			nin.log.Error(err, "Failed to resolve variable", "variable", key)
+		}
 		return false
 	}
 
 	if value, err = nin.subHandler(nin.log, nin.ctx, value); err != nil {
-		nin.log.Error(err, "Failed to resolve variable", "variable", value)
+		if isPreCondition {
+			nin.log.Info("Failed to resolve variable", "info", err.Error(), "variable", value)
+		} else {
+			nin.log.Error(err, "Failed to resolve variable", "variable", value)
+		}
 		return false
 	}
 
diff --git a/pkg/engine/variables/operator/numeric.go b/pkg/engine/variables/operator/numeric.go
index b2f32e5db..b1f57836e 100644
--- a/pkg/engine/variables/operator/numeric.go
+++ b/pkg/engine/variables/operator/numeric.go
@@ -44,16 +44,24 @@ func compareByCondition(key float64, value float64, op kyverno.ConditionOperator
 	}
 }
 
-func (noh NumericOperatorHandler) Evaluate(key, value interface{}) bool {
+func (noh NumericOperatorHandler) Evaluate(key, value interface{}, isPreCondition bool) bool {
 	var err error
 	if key, err = noh.subHandler(noh.log, noh.ctx, key); err != nil {
 		// Failed to resolve the variable
-		noh.log.Error(err, "Failed to resolve variable", "variable", key)
+		if isPreCondition {
+			noh.log.Info("Failed to resolve variable", "info", err.Error(), "variable", key)
+		} else {
+			noh.log.Error(err, "Failed to resolve variable", "variable", key)
+		}
 		return false
 	}
 	if value, err = noh.subHandler(noh.log, noh.ctx, value); err != nil {
 		// Failed to resolve the variable
-		noh.log.Error(err, "Failed to resolve variable", "variable", value)
+		if isPreCondition {
+			noh.log.Info("Failed to resolve variable", "info", err.Error(), "variable", value)
+		} else {
+			noh.log.Error(err, "Failed to resolve variable", "variable", value)
+		}
 		return false
 	}
 
diff --git a/pkg/engine/variables/operator/operator.go b/pkg/engine/variables/operator/operator.go
index 48801105d..3d125e334 100644
--- a/pkg/engine/variables/operator/operator.go
+++ b/pkg/engine/variables/operator/operator.go
@@ -10,7 +10,7 @@ import (
 
 //OperatorHandler provides interface to manage types
 type OperatorHandler interface {
-	Evaluate(key, value interface{}) bool
+	Evaluate(key, value interface{}, isPreCondition bool) bool
 	validateValueWithStringPattern(key string, value interface{}) bool
 	validateValueWithBoolPattern(key bool, value interface{}) bool
 	validateValueWithIntPattern(key int64, value interface{}) bool


Test patch:
diff --git a/pkg/engine/variables/evaluate_test.go b/pkg/engine/variables/evaluate_test.go
index e2b0ea129..4531aecb3 100644
--- a/pkg/engine/variables/evaluate_test.go
+++ b/pkg/engine/variables/evaluate_test.go
@@ -19,7 +19,7 @@ func Test_Eval_Equal_Const_String_Pass(t *testing.T) {
 		Value:    "name",
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -33,7 +33,7 @@ func Test_Eval_Equal_Const_String_Fail(t *testing.T) {
 		Value:    "name1",
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -47,7 +47,7 @@ func Test_Eval_NoEqual_Const_String_Pass(t *testing.T) {
 		Value:    "name1",
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -61,7 +61,7 @@ func Test_Eval_NoEqual_Const_String_Fail(t *testing.T) {
 		Value:    "name",
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -73,7 +73,7 @@ func Test_Eval_GreaterThanOrEquals_Const_string_Equal_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    1.0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -85,7 +85,7 @@ func Test_Eval_GreaterThanOrEquals_Const_string_Greater_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -97,7 +97,7 @@ func Test_Eval_GreaterThanOrEquals_Const_string_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    "2",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -109,7 +109,7 @@ func Test_Eval_GreaterThan_Const_string_Equal_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    1.0,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -121,7 +121,7 @@ func Test_Eval_GreaterThan_Const_string_Greater_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -133,7 +133,7 @@ func Test_Eval_GreaterThan_Const_string_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    "2",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -145,7 +145,7 @@ func Test_Eval_LessThanOrEquals_Const_string_Equal_Pass(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    1.0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -157,7 +157,7 @@ func Test_Eval_LessThanOrEquals_Const_string_Less_Pass(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    1,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -169,7 +169,7 @@ func Test_Eval_LessThanOrEquals_Const_string_Fail(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    "1.1",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -181,7 +181,7 @@ func Test_Eval_LessThan_Const_string_Equal_Pass(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    1.0,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -193,7 +193,7 @@ func Test_Eval_LessThan_Const_string_Less_Pass(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    1,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -205,7 +205,7 @@ func Test_Eval_LessThan_Const_string_Fail(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    "1.1",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -221,7 +221,7 @@ func Test_Eval_Equal_Const_Bool_Pass(t *testing.T) {
 		Value:    true,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -235,7 +235,7 @@ func Test_Eval_Equal_Const_Bool_Fail(t *testing.T) {
 		Value:    false,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -249,7 +249,7 @@ func Test_Eval_NoEqual_Const_Bool_Pass(t *testing.T) {
 		Value:    false,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -263,7 +263,7 @@ func Test_Eval_NoEqual_Const_Bool_Fail(t *testing.T) {
 		Value:    true,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -278,7 +278,7 @@ func Test_Eval_Equal_Const_int_Pass(t *testing.T) {
 		Value:    1,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -292,7 +292,7 @@ func Test_Eval_Equal_Const_int_Fail(t *testing.T) {
 		Value:    2,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -306,7 +306,7 @@ func Test_Eval_NoEqual_Const_int_Pass(t *testing.T) {
 		Value:    2,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -320,7 +320,7 @@ func Test_Eval_NoEqual_Const_int_Fail(t *testing.T) {
 		Value:    1,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -332,7 +332,7 @@ func Test_Eval_GreaterThanOrEquals_Const_int_Equal_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    1.0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -344,7 +344,7 @@ func Test_Eval_GreaterThanOrEquals_Const_int_Greater_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -356,7 +356,7 @@ func Test_Eval_GreaterThanOrEquals_Const_int_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    "2",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -368,7 +368,7 @@ func Test_Eval_GreaterThan_Const_int_Equal_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    1.0,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -380,7 +380,7 @@ func Test_Eval_GreaterThan_Const_int_Greater_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -392,7 +392,7 @@ func Test_Eval_GreaterThan_Const_int_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    "2",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -404,7 +404,7 @@ func Test_Eval_LessThanOrEquals_Const_int_Equal_Pass(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    1.0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -416,7 +416,7 @@ func Test_Eval_LessThanOrEquals_Const_int_Less_Pass(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    1,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -428,7 +428,7 @@ func Test_Eval_LessThanOrEquals_Const_int_Fail(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    "1",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -440,7 +440,7 @@ func Test_Eval_LessThan_Const_int_Equal_Fail(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    1.0,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -452,7 +452,7 @@ func Test_Eval_LessThan_Const_int_Less_Pass(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    1,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -464,7 +464,7 @@ func Test_Eval_LessThan_Const_int_Fail(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    "1",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -479,7 +479,7 @@ func Test_Eval_Equal_Const_int64_Pass(t *testing.T) {
 		Value:    int64(1),
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -493,7 +493,7 @@ func Test_Eval_Equal_Const_int64_Fail(t *testing.T) {
 		Value:    int64(2),
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -507,7 +507,7 @@ func Test_Eval_NoEqual_Const_int64_Pass(t *testing.T) {
 		Value:    int64(2),
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -521,7 +521,7 @@ func Test_Eval_NoEqual_Const_int64_Fail(t *testing.T) {
 		Value:    int64(1),
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -537,7 +537,7 @@ func Test_Eval_Equal_Const_float64_Pass(t *testing.T) {
 		Value:    1.5,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -551,7 +551,7 @@ func Test_Eval_Equal_Const_float64_Fail(t *testing.T) {
 		Value:    1.6,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -565,7 +565,7 @@ func Test_Eval_NoEqual_Const_float64_Pass(t *testing.T) {
 		Value:    1.6,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -579,7 +579,7 @@ func Test_Eval_NoEqual_Const_float64_Fail(t *testing.T) {
 		Value:    1.5,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -591,7 +591,7 @@ func Test_Eval_GreaterThanOrEquals_Const_float64_Equal_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    1.0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -603,7 +603,7 @@ func Test_Eval_GreaterThanOrEquals_Const_float64_Greater_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -615,7 +615,7 @@ func Test_Eval_GreaterThanOrEquals_Const_float64_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThanOrEquals,
 		Value:    "2",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -627,7 +627,7 @@ func Test_Eval_GreaterThan_Const_float64_Equal_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    1.0,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -639,7 +639,7 @@ func Test_Eval_GreaterThan_Const_float64_Greater_Pass(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    "0",
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -651,7 +651,7 @@ func Test_Eval_GreaterThan_Const_float64_Fail(t *testing.T) {
 		Operator: kyverno.GreaterThan,
 		Value:    "2.5",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -663,7 +663,7 @@ func Test_Eval_LessThanOrEquals_Const_float64_Equal_Pass(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    1.0,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -675,7 +675,7 @@ func Test_Eval_LessThanOrEquals_Const_float64_Less_Pass(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    1,
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -687,7 +687,7 @@ func Test_Eval_LessThanOrEquals_Const_float64_Fail(t *testing.T) {
 		Operator: kyverno.LessThanOrEquals,
 		Value:    "1.95",
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -699,7 +699,7 @@ func Test_Eval_LessThan_Const_float64_Equal_Fail(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    1.0,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -711,7 +711,7 @@ func Test_Eval_LessThan_Const_float64_Less_Pass(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    "1.5",
 	}
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -723,7 +723,7 @@ func Test_Eval_LessThan_Const_float64_Fail(t *testing.T) {
 		Operator: kyverno.LessThan,
 		Value:    1.95,
 	}
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -753,7 +753,7 @@ func Test_Eval_Equal_Const_object_Pass(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -781,7 +781,7 @@ func Test_Eval_Equal_Const_object_Fail(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -809,7 +809,7 @@ func Test_Eval_NotEqual_Const_object_Pass(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -837,7 +837,7 @@ func Test_Eval_NotEqual_Const_object_Fail(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -867,7 +867,7 @@ func Test_Eval_Equal_Const_list_Pass(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -893,7 +893,7 @@ func Test_Eval_Equal_Const_list_Fail(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -919,7 +919,7 @@ func Test_Eval_NotEqual_Const_list_Pass(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -945,7 +945,7 @@ func Test_Eval_NotEqual_Const_list_Fail(t *testing.T) {
 		Value:    obj2,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -978,7 +978,7 @@ func Test_Eval_Equal_Var_Pass(t *testing.T) {
 		Value:    "temp",
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -1009,7 +1009,7 @@ func Test_Eval_Equal_Var_Fail(t *testing.T) {
 		Value:    "temp1",
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -1036,7 +1036,7 @@ func Test_Eval_In_String_Set_Pass(t *testing.T) {
 		Value:    valueInterface,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -1061,7 +1061,7 @@ func Test_Eval_In_String_Set_Fail(t *testing.T) {
 		Value:    valueInterface,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }
@@ -1086,7 +1086,7 @@ func Test_Eval_NotIn_String_Set_Pass(t *testing.T) {
 		Value:    valueInterface,
 	}
 
-	if !Evaluate(log.Log, ctx, condition) {
+	if !Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to pass")
 	}
 }
@@ -1111,7 +1111,7 @@ func Test_Eval_NotIn_String_Set_Fail(t *testing.T) {
 		Value:    valueInterface,
 	}
 
-	if Evaluate(log.Log, ctx, condition) {
+	if Evaluate(log.Log, ctx, condition, true) {
 		t.Error("expected to fail")
 	}
 }