From 10ae9e306c5e182a913911a154bf8099086bcf1c Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Fri, 2 Feb 2024 17:36:51 +0530 Subject: [PATCH] feat: update refreshInterval in globalcontext CRD to use a duration (#9615) --- .../v2alpha1/global_context_entry_types.go | 24 ++++++++++++------- api/kyverno/v2alpha1/zz_generated.deepcopy.go | 5 ++++ .../kyverno.io_globalcontextentries.yaml | 12 +++++----- .../kyverno.io_globalcontextentries.yaml | 12 +++++----- config/install-latest-testing.yaml | 12 +++++----- docs/user/crd/index.html | 8 ++++--- .../kyverno/v2alpha1/externalapicall.go | 11 +++++---- pkg/controllers/globalcontext/controller.go | 11 +++------ 8 files changed, 52 insertions(+), 43 deletions(-) diff --git a/api/kyverno/v2alpha1/global_context_entry_types.go b/api/kyverno/v2alpha1/global_context_entry_types.go index e7b5d76d8c56..57ce2f52afb3 100644 --- a/api/kyverno/v2alpha1/global_context_entry_types.go +++ b/api/kyverno/v2alpha1/global_context_entry_types.go @@ -16,6 +16,8 @@ limitations under the License. package v2alpha1 import ( + "time" + kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" @@ -78,7 +80,10 @@ func (c *GlobalContextEntrySpec) IsResource() bool { // Validate implements programmatic validation func (c *GlobalContextEntrySpec) Validate(path *field.Path) (errs field.ErrorList) { if c.IsResource() && c.IsAPICall() { - errs = append(errs, field.Forbidden(path.Child("resource"), "An External API Call entry requires a url")) + errs = append(errs, field.Forbidden(path.Child("kubernetesResource"), "A global context entry should be either have KubernetesResource or APICall")) + } + if !c.IsResource() && !c.IsAPICall() { + errs = append(errs, field.Forbidden(path.Child("kubernetesResource"), "A global context entry should be either have KubernetesResource or APICall")) } if c.IsResource() { errs = append(errs, c.KubernetesResource.Validate(path.Child("resource"))...) @@ -115,13 +120,13 @@ type KubernetesResource struct { // Validate implements programmatic validation func (k *KubernetesResource) Validate(path *field.Path) (errs field.ErrorList) { if k.Group == "" { - errs = append(errs, field.Required(path.Child("group"), "An Resource entry requires a group")) + errs = append(errs, field.Required(path.Child("group"), "A Resource entry requires a group")) } if k.Version == "" { - errs = append(errs, field.Required(path.Child("version"), "An Resource entry requires a version")) + errs = append(errs, field.Required(path.Child("version"), "A Resource entry requires a version")) } if k.Resource == "" { - errs = append(errs, field.Required(path.Child("resource"), "An Resource entry requires a resource")) + errs = append(errs, field.Required(path.Child("resource"), "A Resource entry requires a resource")) } return errs } @@ -129,9 +134,10 @@ func (k *KubernetesResource) Validate(path *field.Path) (errs field.ErrorList) { // ExternalAPICall stores infos about API call that should be cached type ExternalAPICall struct { kyvernov1.APICall `json:",inline,omitempty"` - // RefreshIntervalSeconds defines the interval at which to poll the APICall - // +kubebuilder:default=0 - RefreshIntervalSeconds int64 `json:"refreshIntervalSeconds,omitempty"` + // RefreshInterval defines the interval in duration at which to poll the APICall + // +kubebuilder:validation:Format=duration + // +kubebuilder:default=`10m` + RefreshInterval *metav1.Duration `json:"refreshInterval,omitempty"` } // Validate implements programmatic validation @@ -139,8 +145,8 @@ 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.RefreshIntervalSeconds <= 0 { - errs = append(errs, field.Required(path.Child("refreshIntervalSeconds"), "An Resource entry requires a refresh interval greater than 0 seconds")) + 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")) } return errs } diff --git a/api/kyverno/v2alpha1/zz_generated.deepcopy.go b/api/kyverno/v2alpha1/zz_generated.deepcopy.go index 1739785a1434..e4c182f47516 100644 --- a/api/kyverno/v2alpha1/zz_generated.deepcopy.go +++ b/api/kyverno/v2alpha1/zz_generated.deepcopy.go @@ -153,6 +153,11 @@ func (in *ClusterCleanupPolicyList) DeepCopyObject() runtime.Object { func (in *ExternalAPICall) DeepCopyInto(out *ExternalAPICall) { *out = *in in.APICall.DeepCopyInto(&out.APICall) + if in.RefreshInterval != nil { + in, out := &in.RefreshInterval, &out.RefreshInterval + *out = new(v1.Duration) + **out = **in + } return } diff --git a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_globalcontextentries.yaml b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_globalcontextentries.yaml index 0c0baf012d75..01a62794eee2 100644 --- a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_globalcontextentries.yaml +++ b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_globalcontextentries.yaml @@ -77,12 +77,12 @@ spec: - GET - POST type: string - refreshIntervalSeconds: - default: 0 - description: RefreshIntervalSeconds defines the interval at which - to poll the APICall - format: int64 - type: integer + refreshInterval: + default: 10m + description: RefreshInterval defines the interval in duration + at which to poll the APICall + format: duration + type: string service: description: Service is an API call to a JSON web service properties: diff --git a/config/crds/kyverno/kyverno.io_globalcontextentries.yaml b/config/crds/kyverno/kyverno.io_globalcontextentries.yaml index 7680cc4ebeb4..992e2ec7c0cd 100644 --- a/config/crds/kyverno/kyverno.io_globalcontextentries.yaml +++ b/config/crds/kyverno/kyverno.io_globalcontextentries.yaml @@ -71,12 +71,12 @@ spec: - GET - POST type: string - refreshIntervalSeconds: - default: 0 - description: RefreshIntervalSeconds defines the interval at which - to poll the APICall - format: int64 - type: integer + refreshInterval: + default: 10m + description: RefreshInterval defines the interval in duration + at which to poll the APICall + format: duration + type: string service: description: Service is an API call to a JSON web service properties: diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index baae2cba12a7..264af4f4d3c5 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -28218,12 +28218,12 @@ spec: - GET - POST type: string - refreshIntervalSeconds: - default: 0 - description: RefreshIntervalSeconds defines the interval at which - to poll the APICall - format: int64 - type: integer + refreshInterval: + default: 10m + description: RefreshInterval defines the interval in duration + at which to poll the APICall + format: duration + type: string service: description: Service is an API call to a JSON web service properties: diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 431d63bff600..e1d15fee0719 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -8011,13 +8011,15 @@

ExternalAPICall -refreshIntervalSeconds
+refreshInterval
-int64 + +Kubernetes meta/v1.Duration + -

RefreshIntervalSeconds defines the interval at which to poll the APICall

+

RefreshInterval defines the interval in duration at which to poll the APICall

diff --git a/pkg/client/applyconfigurations/kyverno/v2alpha1/externalapicall.go b/pkg/client/applyconfigurations/kyverno/v2alpha1/externalapicall.go index 5f641a47cce9..b9cd6db2bc4f 100644 --- a/pkg/client/applyconfigurations/kyverno/v2alpha1/externalapicall.go +++ b/pkg/client/applyconfigurations/kyverno/v2alpha1/externalapicall.go @@ -21,13 +21,14 @@ package v2alpha1 import ( kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" v1 "github.com/kyverno/kyverno/pkg/client/applyconfigurations/kyverno/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // ExternalAPICallApplyConfiguration represents an declarative configuration of the ExternalAPICall type for use // with apply. type ExternalAPICallApplyConfiguration struct { v1.APICallApplyConfiguration `json:",omitempty,inline"` - RefreshIntervalSeconds *int64 `json:"refreshIntervalSeconds,omitempty"` + RefreshInterval *metav1.Duration `json:"refreshInterval,omitempty"` } // ExternalAPICallApplyConfiguration constructs an declarative configuration of the ExternalAPICall type for use with @@ -81,10 +82,10 @@ func (b *ExternalAPICallApplyConfiguration) WithJMESPath(value string) *External return b } -// WithRefreshIntervalSeconds sets the RefreshIntervalSeconds field in the declarative configuration to the given value +// WithRefreshInterval sets the RefreshInterval field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the RefreshIntervalSeconds field is set to the value of the last call. -func (b *ExternalAPICallApplyConfiguration) WithRefreshIntervalSeconds(value int64) *ExternalAPICallApplyConfiguration { - b.RefreshIntervalSeconds = &value +// If called multiple times, the RefreshInterval field is set to the value of the last call. +func (b *ExternalAPICallApplyConfiguration) WithRefreshInterval(value metav1.Duration) *ExternalAPICallApplyConfiguration { + b.RefreshInterval = &value return b } diff --git a/pkg/controllers/globalcontext/controller.go b/pkg/controllers/globalcontext/controller.go index b08919a69e5f..1ffa9359c695 100644 --- a/pkg/controllers/globalcontext/controller.go +++ b/pkg/controllers/globalcontext/controller.go @@ -2,7 +2,6 @@ package globalcontext import ( "context" - "errors" "time" "github.com/go-logr/logr" @@ -88,12 +87,8 @@ func (c *controller) getEntry(name string) (*kyvernov2alpha1.GlobalContextEntry, func (c *controller) makeStoreEntry(ctx context.Context, gce *kyvernov2alpha1.GlobalContextEntry) (store.Entry, error) { // TODO: should be done at validation time - if gce.Spec.KubernetesResource == nil && gce.Spec.APICall == nil { - return nil, errors.New("global context entry neither has K8sResource nor APICall") - } - // TODO: should be done at validation time - if gce.Spec.KubernetesResource != nil && gce.Spec.APICall != nil { - return nil, errors.New("global context entry has both K8sResource and APICall") + if err := gce.Validate(); err != nil { + return nil, err.ToAggregate() } if gce.Spec.KubernetesResource != nil { gvr := schema.GroupVersionResource{ @@ -103,5 +98,5 @@ func (c *controller) makeStoreEntry(ctx context.Context, gce *kyvernov2alpha1.Gl } return k8sresource.New(ctx, c.dclient.GetDynamicInterface(), gvr, gce.Spec.KubernetesResource.Namespace) } - return externalapi.New(ctx, logger, adapters.Client(c.dclient), gce.Spec.APICall.APICall, time.Duration(gce.Spec.APICall.RefreshIntervalSeconds)) + return externalapi.New(ctx, logger, adapters.Client(c.dclient), gce.Spec.APICall.APICall, gce.Spec.APICall.RefreshInterval.Duration) }