diff --git a/api/kyverno/v1/resource_description_types.go b/api/kyverno/v1/resource_description_types.go index 025cf107bc..35f275fd1d 100644 --- a/api/kyverno/v1/resource_description_types.go +++ b/api/kyverno/v1/resource_description_types.go @@ -67,6 +67,14 @@ func (r ResourceDescription) IsEmpty() bool { r.NamespaceSelector == nil } +func (r ResourceDescription) GetOperations() []string { + ops := []string{} + for _, op := range r.Operations { + ops = append(ops, string(op)) + } + return ops +} + // Validate implements programmatic validation func (r *ResourceDescription) Validate(path *field.Path, namespaced bool, clusterResources sets.Set[string]) (errs field.ErrorList) { if r.Name != "" && len(r.Names) > 0 { diff --git a/api/kyverno/v2beta1/resource_description_types.go b/api/kyverno/v2beta1/resource_description_types.go index 199292d8e6..aaa7cb518f 100644 --- a/api/kyverno/v2beta1/resource_description_types.go +++ b/api/kyverno/v2beta1/resource_description_types.go @@ -52,6 +52,14 @@ type ResourceDescription struct { Operations []kyvernov1.AdmissionOperation `json:"operations,omitempty" yaml:"operations,omitempty"` } +func (r ResourceDescription) GetOperations() []string { + ops := []string{} + for _, op := range r.Operations { + ops = append(ops, string(op)) + } + return ops +} + // Validate implements programmatic validation func (r *ResourceDescription) Validate(path *field.Path, namespaced bool, clusterResources sets.Set[string]) (errs field.ErrorList) { if len(r.Names) > 0 { diff --git a/pkg/webhooks/resource/generation/handler.go b/pkg/webhooks/resource/generation/handler.go index 509c05c24c..46025a3fc3 100644 --- a/pkg/webhooks/resource/generation/handler.go +++ b/pkg/webhooks/resource/generation/handler.go @@ -203,11 +203,7 @@ func (h *generationHandler) syncTriggerAction( rules := getAppliedRules(policy, failedRules) for _, rule := range rules { // fire generation on trigger deletion - if (request.Operation == admissionv1.Delete) && precondition(rule, kyvernov1.Condition{ - RawKey: kyvernov1.ToJSON("request.operation"), - Operator: "Equals", - RawValue: kyvernov1.ToJSON("DELETE"), - }) { + if (request.Operation == admissionv1.Delete) && matchDeleteOperation(rule) { h.log.V(4).Info("creating the UR to generate downstream on trigger's deletion", "operation", request.Operation, "rule", rule.Name) ur := buildURSpec(kyvernov1beta1.Generate, pKey, rule.Name, urSpec, false) ur.Context = buildURContext(request, policyContext) diff --git a/pkg/webhooks/resource/generation/utils.go b/pkg/webhooks/resource/generation/utils.go index 0862a14e4a..e31c72a85b 100644 --- a/pkg/webhooks/resource/generation/utils.go +++ b/pkg/webhooks/resource/generation/utils.go @@ -1,17 +1,12 @@ package generation import ( - "strings" - kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1" "github.com/kyverno/kyverno/pkg/background/common" "github.com/kyverno/kyverno/pkg/engine" - utils "github.com/kyverno/kyverno/pkg/engine/utils" - "github.com/kyverno/kyverno/pkg/engine/variables/regex" datautils "github.com/kyverno/kyverno/pkg/utils/data" admissionv1 "k8s.io/api/admission/v1" - apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) func buildURSpec(requestType kyvernov1beta1.RequestType, policyKey, ruleName string, resource kyvernov1.ResourceSpec, deleteDownstream bool) kyvernov1beta1.UpdateRequestSpec { @@ -34,35 +29,13 @@ func buildURContext(request *admissionv1.AdmissionRequest, policyContext *engine } } -func precondition(rule kyvernov1.Rule, expected kyvernov1.Condition) bool { - conditions, err := utils.TransformConditions(rule.GetAnyAllConditions()) - if err != nil { - return false +func matchDeleteOperation(rule kyvernov1.Rule) bool { + ops := rule.MatchResources.GetOperations() + for _, rscFilters := range append(rule.MatchResources.All, rule.MatchResources.Any...) { + ops = append(ops, rscFilters.ResourceDescription.GetOperations()...) } - var conditionsAll []kyvernov1.Condition - switch typedConditions := conditions.(type) { - case kyvernov1.AnyAllConditions: - conditionsAll = append(typedConditions.AllConditions, typedConditions.AnyConditions...) - case []kyvernov1.Condition: - conditionsAll = typedConditions - } - for _, condition := range conditionsAll { - copy := condition.DeepCopy() - copy.RawKey = trimKeySpaces(condition.RawKey) - if datautils.DeepEqual(*copy, expected) { - return true - } - } - return false -} - -func trimKeySpaces(rawKey *apiextv1.JSON) *apiextv1.JSON { - keys := regex.RegexVariableKey.FindAllStringSubmatch(string(rawKey.Raw), -1) - if len(keys) != 0 { - return kyvernov1.ToJSON(strings.TrimSpace(keys[0][1])) - } - return kyvernov1.ToJSON("") + return datautils.SliceContains(ops, string(admissionv1.Delete)) } func compareLabels(new, old map[string]string) bool { diff --git a/test/conformance/kuttl/generate/clusterpolicy/cornercases/cpol-data-create-on-trigger-deletion/01-manifests.yaml b/test/conformance/kuttl/generate/clusterpolicy/cornercases/cpol-data-create-on-trigger-deletion/01-manifests.yaml index a323942f47..240c10f327 100644 --- a/test/conformance/kuttl/generate/clusterpolicy/cornercases/cpol-data-create-on-trigger-deletion/01-manifests.yaml +++ b/test/conformance/kuttl/generate/clusterpolicy/cornercases/cpol-data-create-on-trigger-deletion/01-manifests.yaml @@ -21,11 +21,8 @@ spec: - resources: kinds: - ConfigMap - preconditions: - any: - - key: "{{ request.operation }}" - operator: Equals - value: DELETE + operations: + - DELETE generate: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy