diff --git a/api/kyverno/v1/resource_spec_types.go b/api/kyverno/v1/resource_spec_types.go index 59890fea7a..88aada79c0 100644 --- a/api/kyverno/v1/resource_spec_types.go +++ b/api/kyverno/v1/resource_spec_types.go @@ -1,5 +1,7 @@ package v1 +import "strings" + type ResourceSpec struct { // APIVersion specifies resource apiVersion. // +optional @@ -18,3 +20,7 @@ func (s ResourceSpec) GetName() string { return s.Name } func (s ResourceSpec) GetNamespace() string { return s.Namespace } func (s ResourceSpec) GetKind() string { return s.Kind } func (s ResourceSpec) GetAPIVersion() string { return s.APIVersion } + +func (s ResourceSpec) String() string { + return strings.Join([]string{s.APIVersion, s.Kind, s.Namespace, s.Name}, "/") +} diff --git a/api/kyverno/v1beta1/updaterequest_types.go b/api/kyverno/v1beta1/updaterequest_types.go index b036b5729b..c017a0c5dd 100644 --- a/api/kyverno/v1beta1/updaterequest_types.go +++ b/api/kyverno/v1beta1/updaterequest_types.go @@ -83,6 +83,13 @@ type UpdateRequestSpec struct { // Specifies the name of the policy. Policy string `json:"policy" yaml:"policy"` + // Rule is the associate rule name of the current UR. + Rule string `json:"rule" yaml:"rule"` + + // Synchronize represents the sync behavior of the corresponding rule + // Optional. Defaults to "false" if not specified. + Synchronize bool `json:"synchronize,omitempty" yaml:"synchronize,omitempty"` + // ResourceSpec is the information to identify the update request. Resource kyvernov1.ResourceSpec `json:"resource" yaml:"resource"` @@ -152,3 +159,19 @@ type UpdateRequestList struct { func (s *UpdateRequestSpec) GetRequestType() RequestType { return s.Type } + +func (s *UpdateRequestSpec) GetPolicyKey() string { + return s.Policy +} + +func (s *UpdateRequestSpec) GetRuleName() string { + return s.Rule +} + +func (s *UpdateRequestSpec) GetSynchronize() bool { + return s.Synchronize +} + +func (s *UpdateRequestSpec) GetResource() kyvernov1.ResourceSpec { + return s.Resource +} diff --git a/charts/kyverno/templates/crds/crds.yaml b/charts/kyverno/templates/crds/crds.yaml index be58e2af04..be7c1a4a1f 100644 --- a/charts/kyverno/templates/crds/crds.yaml +++ b/charts/kyverno/templates/crds/crds.yaml @@ -30532,10 +30532,18 @@ spec: description: Namespace specifies resource namespace. type: string type: object + rule: + description: Rule is the associate rule name of the current UR. + type: string + synchronize: + description: Synchronize represents the sync behavior of the corresponding + rule Optional. Defaults to "false" if not specified. + type: boolean required: - context - policy - resource + - rule type: object status: description: Status contains statistics related to update request. diff --git a/config/crds/kyverno.io_updaterequests.yaml b/config/crds/kyverno.io_updaterequests.yaml index 485a2eec80..4eb72ab294 100644 --- a/config/crds/kyverno.io_updaterequests.yaml +++ b/config/crds/kyverno.io_updaterequests.yaml @@ -341,10 +341,18 @@ spec: description: Namespace specifies resource namespace. type: string type: object + rule: + description: Rule is the associate rule name of the current UR. + type: string + synchronize: + description: Synchronize represents the sync behavior of the corresponding + rule Optional. Defaults to "false" if not specified. + type: boolean required: - context - policy - resource + - rule type: object status: description: Status contains statistics related to update request. diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 95d915fa71..ca9b9f5a20 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -4386,6 +4386,29 @@ string +rule
+ +string + + + +

Rule is the associate rule name of the current UR.

+ + + + +synchronize
+ +bool + + + +

Synchronize represents the sync behavior of the corresponding rule +Optional. Defaults to “false” if not specified.

+ + + + resource
@@ -4585,6 +4608,29 @@ string +rule
+ +string + + + +

Rule is the associate rule name of the current UR.

+ + + + +synchronize
+ +bool + + + +

Synchronize represents the sync behavior of the corresponding rule +Optional. Defaults to “false” if not specified.

+ + + + resource
diff --git a/pkg/background/common/context.go b/pkg/background/common/context.go index a317c25497..0efb5cefef 100644 --- a/pkg/background/common/context.go +++ b/pkg/background/common/context.go @@ -39,7 +39,7 @@ func NewBackgroundContext(dclient dclient.Interface, ur *kyvernov1beta1.UpdateRe if !reflect.DeepEqual(new, unstructured.Unstructured{}) { if !check(&new, trigger) { err := fmt.Errorf("resources don't match") - return nil, false, fmt.Errorf("resource %v: %w", ur.Spec.Resource, err) + return nil, false, fmt.Errorf("resource %v: %w", ur.Spec.GetResource().String(), err) } } } diff --git a/pkg/background/common/resource.go b/pkg/background/common/resource.go index 1220fa24f1..44345c2f3f 100644 --- a/pkg/background/common/resource.go +++ b/pkg/background/common/resource.go @@ -16,7 +16,7 @@ import ( ) func GetResource(client dclient.Interface, urSpec kyvernov1beta1.UpdateRequestSpec, log logr.Logger) (*unstructured.Unstructured, error) { - resourceSpec := urSpec.Resource + resourceSpec := urSpec.GetResource() get := func() (*unstructured.Unstructured, error) { if resourceSpec.Kind == "Namespace" { @@ -24,7 +24,7 @@ func GetResource(client dclient.Interface, urSpec kyvernov1beta1.UpdateRequestSp } resource, err := client.GetResource(context.TODO(), resourceSpec.APIVersion, resourceSpec.Kind, resourceSpec.Namespace, resourceSpec.Name) if err != nil { - if urSpec.Type == kyvernov1beta1.Mutate && errors.IsNotFound(err) && urSpec.Context.AdmissionRequestInfo.Operation == admissionv1.Delete { + if urSpec.GetRequestType() == kyvernov1beta1.Mutate && errors.IsNotFound(err) && urSpec.Context.AdmissionRequestInfo.Operation == admissionv1.Delete { log.V(4).Info("trigger resource does not exist for mutateExisting rule", "operation", urSpec.Context.AdmissionRequestInfo.Operation) return nil, nil } diff --git a/pkg/background/generate/generate.go b/pkg/background/generate/generate.go index a31f85ee34..f6244277be 100644 --- a/pkg/background/generate/generate.go +++ b/pkg/background/generate/generate.go @@ -86,7 +86,7 @@ func NewGenerateController( } func (c *GenerateController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error { - logger := c.log.WithValues("name", ur.Name, "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name) + logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String()) var err error var resource *unstructured.Unstructured var genResources []kyvernov1.ResourceSpec @@ -148,7 +148,7 @@ func (c *GenerateController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error { const doesNotApply = "policy does not apply to resource" func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur kyvernov1beta1.UpdateRequest, namespaceLabels map[string]string) ([]kyvernov1.ResourceSpec, bool, error) { - logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name) + logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String()) logger.V(3).Info("applying generate policy rule") policy, err := c.getPolicySpec(ur) diff --git a/pkg/background/mutate/mutate.go b/pkg/background/mutate/mutate.go index f722c1e3ab..8346335a25 100644 --- a/pkg/background/mutate/mutate.go +++ b/pkg/background/mutate/mutate.go @@ -70,7 +70,7 @@ func NewMutateExistingController( } func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) error { - logger := c.log.WithValues("name", ur.Name, "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name) + logger := c.log.WithValues("name", ur.GetName(), "policy", ur.Spec.GetPolicyKey(), "resource", ur.Spec.GetResource().String()) var errs []error policy, err := c.getPolicy(ur.Spec.Policy) diff --git a/pkg/background/update_request_controller.go b/pkg/background/update_request_controller.go index e8259a9c02..34c1b040ee 100644 --- a/pkg/background/update_request_controller.go +++ b/pkg/background/update_request_controller.go @@ -195,7 +195,7 @@ func (c *controller) syncUpdateRequest(key string) error { } // try to get the linked policy if _, err := c.getPolicy(ur.Spec.Policy); err != nil { - if apierrors.IsNotFound(err) && ur.Spec.Type == kyvernov1beta1.Mutate { + if apierrors.IsNotFound(err) && ur.Spec.GetRequestType() == kyvernov1beta1.Mutate { // here only takes care of mutateExisting policies // generate cleanup controller handles policy deletion selector := &metav1.LabelSelector{ @@ -387,7 +387,7 @@ func (c *controller) deleteUR(obj interface{}) { func (c *controller) processUR(ur *kyvernov1beta1.UpdateRequest) error { statusControl := common.NewStatusControl(c.kyvernoClient, c.urLister) - switch ur.Spec.Type { + switch ur.Spec.GetRequestType() { case kyvernov1beta1.Mutate: ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.engine, c.cpolLister, c.polLister, c.nsLister, c.configuration, c.eventGen, logger) return ctrl.ProcessUR(ur) @@ -399,7 +399,7 @@ func (c *controller) processUR(ur *kyvernov1beta1.UpdateRequest) error { } func (c *controller) cleanUR(ur *kyvernov1beta1.UpdateRequest) error { - if ur.Spec.Type == kyvernov1beta1.Mutate && ur.Status.State == kyvernov1beta1.Completed { + if ur.Spec.GetRequestType() == kyvernov1beta1.Mutate && ur.Status.State == kyvernov1beta1.Completed { return c.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace()).Delete(context.TODO(), ur.GetName(), metav1.DeleteOptions{}) } return nil diff --git a/pkg/client/listers/kyverno/v1beta1/updaterequest_expansion.go b/pkg/client/listers/kyverno/v1beta1/updaterequest_expansion.go index 48b83dce68..da1cf6c62f 100644 --- a/pkg/client/listers/kyverno/v1beta1/updaterequest_expansion.go +++ b/pkg/client/listers/kyverno/v1beta1/updaterequest_expansion.go @@ -33,7 +33,7 @@ func (s updateRequestNamespaceLister) GetUpdateRequestsForClusterPolicy(policy s return nil, err } for idx, ur := range urs { - if ur.Spec.Policy == policy { + if ur.Spec.GetPolicyKey() == policy { list = append(list, urs[idx]) } } diff --git a/pkg/policy/policy_controller.go b/pkg/policy/policy_controller.go index 527399664a..8afb6e7d5e 100644 --- a/pkg/policy/policy_controller.go +++ b/pkg/policy/policy_controller.go @@ -567,7 +567,7 @@ func generateTriggers(client dclient.Interface, rule kyvernov1.Rule, log logr.Lo func updateUR(kyvernoClient versioned.Interface, urLister kyvernov1beta1listers.UpdateRequestNamespaceLister, policyKey string, urList []*kyvernov1beta1.UpdateRequest, logger logr.Logger) { for _, ur := range urList { - if policyKey == ur.Spec.Policy { + if policyKey == ur.Spec.GetPolicyKey() { _, err := backgroundcommon.Update(kyvernoClient, urLister, ur.GetName(), func(ur *kyvernov1beta1.UpdateRequest) { urLabels := ur.Labels if len(urLabels) == 0 { diff --git a/pkg/webhooks/resource/handlers.go b/pkg/webhooks/resource/handlers.go index 04c65bcaad..5436702b75 100644 --- a/pkg/webhooks/resource/handlers.go +++ b/pkg/webhooks/resource/handlers.go @@ -212,7 +212,7 @@ func (h *handlers) handleDelete(logger logr.Logger, request *admissionv1.Admissi return } - if ur.Spec.Type == kyvernov1beta1.Mutate { + if ur.Spec.GetRequestType() == kyvernov1beta1.Mutate { return } h.urUpdater.UpdateAnnotation(logger, ur.GetName()) diff --git a/pkg/webhooks/updaterequest/generator.go b/pkg/webhooks/updaterequest/generator.go index 9747096dc3..f72cdfdd33 100644 --- a/pkg/webhooks/updaterequest/generator.go +++ b/pkg/webhooks/updaterequest/generator.go @@ -41,7 +41,7 @@ func NewGenerator(client versioned.Interface, urInformer kyvernov1beta1informers // Apply creates update request resource func (g *generator) Apply(ctx context.Context, ur kyvernov1beta1.UpdateRequestSpec, action admissionv1.Operation) error { logger.V(4).Info("reconcile Update Request", "request", ur) - if action == admissionv1.Delete && ur.Type == kyvernov1beta1.Generate { + if action == admissionv1.Delete && ur.GetRequestType() == kyvernov1beta1.Generate { return nil } go g.applyResource(context.TODO(), ur) @@ -64,17 +64,17 @@ func (g *generator) applyResource(ctx context.Context, urSpec kyvernov1beta1.Upd } func (g *generator) tryApplyResource(ctx context.Context, urSpec kyvernov1beta1.UpdateRequestSpec) error { - l := logger.WithValues("ruleType", urSpec.Type, "kind", urSpec.Resource.Kind, "name", urSpec.Resource.Name, "namespace", urSpec.Resource.Namespace) + l := logger.WithValues("ruleType", urSpec.GetRequestType(), "resource", urSpec.GetResource().String()) var queryLabels labels.Set - if urSpec.Type == kyvernov1beta1.Mutate { - queryLabels = common.MutateLabelsSet(urSpec.Policy, urSpec.Resource) - } else if urSpec.Type == kyvernov1beta1.Generate { - queryLabels = common.GenerateLabelsSet(urSpec.Policy, urSpec.Resource) + if urSpec.GetRequestType() == kyvernov1beta1.Mutate { + queryLabels = common.MutateLabelsSet(urSpec.Policy, urSpec.GetResource()) + } else if urSpec.GetRequestType() == kyvernov1beta1.Generate { + queryLabels = common.GenerateLabelsSet(urSpec.Policy, urSpec.GetResource()) } urList, err := g.urLister.List(labels.SelectorFromSet(queryLabels)) if err != nil { - l.Error(err, "failed to get update request for the resource", "kind", urSpec.Resource.Kind, "name", urSpec.Resource.Name, "namespace", urSpec.Resource.Namespace) + l.Error(err, "failed to get update request for the resource", "resource", urSpec.GetResource().String()) return err } for _, v := range urList {