From 8e0251fb4b6d4473122cd6442e0a6a0474fe3f65 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Mon, 29 Jul 2024 12:28:03 +0200 Subject: [PATCH 01/11] feat: kpb refs refactoring Signed-off-by: Mattia Lavacca --- .../v1alpha1/kongpluginbinding_types.go | 36 +++-- .../v1alpha1/zz_generated.deepcopy.go | 103 +++++++------- ...uration.konghq.com_kongpluginbindings.yaml | 130 ++++++++++-------- docs/api-reference.md | 70 +++++----- 4 files changed, 181 insertions(+), 158 deletions(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index c08113c..202d796 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -87,18 +87,15 @@ type KongPluginBindingSpec struct { // KongClusterPlugin can be replaced by kongPluginBindings with no Kong references. This way we'd be // more coherent with the Konnect approach. // https://github.com/Kong/kubernetes-configuration/issues/7 - Kong *KongReferences `json:"kong,omitempty"` - // TODO(mlavacca): let's defer this one to the future as we are not sure about the shape we want to give it. - // https://github.com/Kong/kubernetes-configuration/issues/8 - // EntityReference *GenericEntityRef `json:"genericEntityRef,omitempty"` -} - -type KongReferences struct { - RouteReference *EntityRef `json:"routeRef,omitempty"` - ServiceReference *EntityRef `json:"serviceRef,omitempty"` - ConsumerReference *EntityRef `json:"consumerRef,omitempty"` - ConsumerGroupReference *EntityRef `json:"consumerGroupRef,omitempty"` + // TODO(mlavacca): RouteReference allows references to KongRoute, Ingress, HTTPRoute, or GCPRoute resource. + // TODO(mlavacca): ServiceReference allows Service or KongService resource. + // TODO(mlavacca): In case the routeRef references a KongRoute, the ServiceRef should be unset or set to a KongService. + // The same applies the other way around. + RouteReference *TargetRefWithGroupKind `json:"routeRef,omitempty"` + ServiceReference *TargetRefWithGroupKind `json:"serviceRef,omitempty"` + ConsumerReference *TargetRef `json:"consumerRef,omitempty"` + ConsumerGroupReference *TargetRef `json:"consumerGroupRef,omitempty"` } type PluginRef struct { @@ -115,12 +112,27 @@ type PluginRef struct { Kind *string `json:"kind,omitempty"` } -type EntityRef struct { +type TargetRef struct { // Name is the name of the entity. // +kubebuilder:validation:Required Name string `json:"name"` } +// TODO(mlavacca): add xvalidation between group and kind +type TargetRefWithGroupKind struct { + // Name is the name of the entity. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=KongService;KongRoute;Service;HTTPRoute;GCPRoute;Ingress + Kind string `json:"kind"` + + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum="";core;gateway.networking.k8s.io;networking.k8s.io + Group string `json:"group"` +} + // type GenericEntityRef struct { // // Name is the name of the generic entity. // // +kubebuilder:validation:Required diff --git a/api/configuration/v1alpha1/zz_generated.deepcopy.go b/api/configuration/v1alpha1/zz_generated.deepcopy.go index e801017..57ef064 100644 --- a/api/configuration/v1alpha1/zz_generated.deepcopy.go +++ b/api/configuration/v1alpha1/zz_generated.deepcopy.go @@ -87,21 +87,6 @@ func (in *ControllerReference) DeepCopy() *ControllerReference { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EntityRef) DeepCopyInto(out *EntityRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EntityRef. -func (in *EntityRef) DeepCopy() *EntityRef { - if in == nil { - return nil - } - out := new(EntityRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IngressClassParameters) DeepCopyInto(out *IngressClassParameters) { *out = *in @@ -462,10 +447,25 @@ func (in *KongPluginBindingList) DeepCopyObject() runtime.Object { func (in *KongPluginBindingSpec) DeepCopyInto(out *KongPluginBindingSpec) { *out = *in in.PluginReference.DeepCopyInto(&out.PluginReference) - if in.Kong != nil { - in, out := &in.Kong, &out.Kong - *out = new(KongReferences) - (*in).DeepCopyInto(*out) + if in.RouteReference != nil { + in, out := &in.RouteReference, &out.RouteReference + *out = new(TargetRefWithGroupKind) + **out = **in + } + if in.ServiceReference != nil { + in, out := &in.ServiceReference, &out.ServiceReference + *out = new(TargetRefWithGroupKind) + **out = **in + } + if in.ConsumerReference != nil { + in, out := &in.ConsumerReference, &out.ConsumerReference + *out = new(TargetRef) + **out = **in + } + if in.ConsumerGroupReference != nil { + in, out := &in.ConsumerGroupReference, &out.ConsumerGroupReference + *out = new(TargetRef) + **out = **in } } @@ -506,41 +506,6 @@ func (in *KongPluginBindingStatus) DeepCopy() *KongPluginBindingStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KongReferences) DeepCopyInto(out *KongReferences) { - *out = *in - if in.RouteReference != nil { - in, out := &in.RouteReference, &out.RouteReference - *out = new(EntityRef) - **out = **in - } - if in.ServiceReference != nil { - in, out := &in.ServiceReference, &out.ServiceReference - *out = new(EntityRef) - **out = **in - } - if in.ConsumerReference != nil { - in, out := &in.ConsumerReference, &out.ConsumerReference - *out = new(EntityRef) - **out = **in - } - if in.ConsumerGroupReference != nil { - in, out := &in.ConsumerGroupReference, &out.ConsumerGroupReference - *out = new(EntityRef) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongReferences. -func (in *KongReferences) DeepCopy() *KongReferences { - if in == nil { - return nil - } - out := new(KongReferences) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KongRoute) DeepCopyInto(out *KongRoute) { *out = *in @@ -1132,3 +1097,33 @@ func (in *ServiceRef) DeepCopy() *ServiceRef { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetRef) DeepCopyInto(out *TargetRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetRef. +func (in *TargetRef) DeepCopy() *TargetRef { + if in == nil { + return nil + } + out := new(TargetRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetRefWithGroupKind) DeepCopyInto(out *TargetRefWithGroupKind) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetRefWithGroupKind. +func (in *TargetRefWithGroupKind) DeepCopy() *TargetRefWithGroupKind { + if in == nil { + return nil + } + out := new(TargetRefWithGroupKind) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index 49c76bc..e71c80b 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -53,65 +53,21 @@ spec: spec: description: KongPluginBindingSpec defines specification of a KongPluginBinding. properties: - kong: - description: |- - Kong contains the Kong entity references. It is possible to set multiple combinations - of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence - The complete set of allowed combinations and their order of precedence for plugins - configured to multiple entities is: - - - 1. Consumer + route + service - 2. Consumer group + service + route - 3. Consumer + route - 4. Consumer + service - 5. Consumer group + route - 6. Consumer group + service - 7. Route + service - 8. Consumer - 9. Consumer group - 10. Route - 11. Service - 12. Global - - - TODO(mlavacca): we need to figure out how to deal with global plugins. By means of this new API, - KongClusterPlugin can be replaced by kongPluginBindings with no Kong references. This way we'd be - more coherent with the Konnect approach. - https://github.com/Kong/kubernetes-configuration/issues/7 + consumerGroupRef: properties: - consumerGroupRef: - properties: - name: - description: Name is the name of the entity. - type: string - required: - - name - type: object - consumerRef: - properties: - name: - description: Name is the name of the entity. - type: string - required: - - name - type: object - routeRef: - properties: - name: - description: Name is the name of the entity. - type: string - required: - - name - type: object - serviceRef: - properties: - name: - description: Name is the name of the entity. - type: string - required: - - name - type: object + name: + description: Name is the name of the entity. + type: string + required: + - name + type: object + consumerRef: + properties: + name: + description: Name is the name of the entity. + type: string + required: + - name type: object pluginRef: description: PluginReference is a reference to the KongPlugin or KongClusterPlugin @@ -132,6 +88,64 @@ spec: required: - name type: object + routeRef: + description: |- + TODO(mlavacca): RouteReference allows references to KongRoute, Ingress, HTTPRoute, or GCPRoute resource. + TODO(mlavacca): ServiceReference allows Service or KongService resource. + TODO(mlavacca): In case the routeRef references a KongRoute, the ServiceRef should be unset or set to a KongService. + The same applies the other way around. + properties: + group: + enum: + - "" + - core + - gateway.networking.k8s.io + - networking.k8s.io + type: string + kind: + enum: + - KongService + - KongRoute + - Service + - HTTPRoute + - GCPRoute + - Ingress + type: string + name: + description: Name is the name of the entity. + type: string + required: + - group + - kind + - name + type: object + serviceRef: + description: 'TODO(mlavacca): add xvalidation between group and kind' + properties: + group: + enum: + - "" + - core + - gateway.networking.k8s.io + - networking.k8s.io + type: string + kind: + enum: + - KongService + - KongRoute + - Service + - HTTPRoute + - GCPRoute + - Ingress + type: string + name: + description: Name is the name of the entity. + type: string + required: + - group + - kind + - name + type: object required: - pluginRef type: object diff --git a/docs/api-reference.md b/docs/api-reference.md index 2472130..68c2ed0 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -492,21 +492,6 @@ _Appears in:_ _Appears in:_ - [KongLicenseControllerStatus](#konglicensecontrollerstatus) -#### EntityRef - - - - - - -| Field | Description | -| --- | --- | -| `name` _string_ | Name is the name of the entity. | - - -_Appears in:_ -- [KongReferences](#kongreferences) - #### Group _Underlying type:_ `string` @@ -614,7 +599,10 @@ KongPluginBindingSpec defines specification of a KongPluginBinding. | Field | Description | | --- | --- | | `pluginRef` _[PluginRef](#pluginref)_ | PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required | -| `kong` _[KongReferences](#kongreferences)_ | Kong contains the Kong entity references. It is possible to set multiple combinations of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence The complete set of allowed combinations and their order of precedence for plugins configured to multiple entities is:

1. Consumer + route + service 2. Consumer group + service + route 3. Consumer + route 4. Consumer + service 5. Consumer group + route 6. Consumer group + service 7. Route + service 8. Consumer 9. Consumer group 10. Route 11. Service 12. Global

TODO(mlavacca): we need to figure out how to deal with global plugins. By means of this new API, KongClusterPlugin can be replaced by kongPluginBindings with no Kong references. This way we'd be more coherent with the Konnect approach. https://github.com/Kong/kubernetes-configuration/issues/7 | +| `routeRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | TODO(mlavacca): RouteReference allows references to KongRoute, Ingress, HTTPRoute, or GCPRoute resource. TODO(mlavacca): ServiceReference allows Service or KongService resource. TODO(mlavacca): In case the routeRef references a KongRoute, the ServiceRef should be unset or set to a KongService. The same applies the other way around. | +| `serviceRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | | +| `consumerRef` _[TargetRef](#targetref)_ | | +| `consumerGroupRef` _[TargetRef](#targetref)_ | | _Appears in:_ @@ -622,24 +610,6 @@ _Appears in:_ -#### KongReferences - - - - - - -| Field | Description | -| --- | --- | -| `routeRef` _[EntityRef](#entityref)_ | | -| `serviceRef` _[EntityRef](#entityref)_ | | -| `consumerRef` _[EntityRef](#entityref)_ | | -| `consumerGroupRef` _[EntityRef](#entityref)_ | | - - -_Appears in:_ -- [KongPluginBindingSpec](#kongpluginbindingspec) - #### KongRouteAPISpec @@ -897,6 +867,38 @@ _Appears in:_ _Appears in:_ - [KongRouteSpec](#kongroutespec) +#### TargetRef + + + + + + +| Field | Description | +| --- | --- | +| `name` _string_ | Name is the name of the entity. | + + +_Appears in:_ +- [KongPluginBindingSpec](#kongpluginbindingspec) + +#### TargetRefWithGroupKind + + +TODO(mlavacca): add xvalidation between group and kind + + + +| Field | Description | +| --- | --- | +| `name` _string_ | Name is the name of the entity. | +| `kind` _string_ | | +| `group` _string_ | | + + +_Appears in:_ +- [KongPluginBindingSpec](#kongpluginbindingspec) + ## configuration.konghq.com/v1beta1 From c14503db84ce2a4d96b07df963b58899628259e9 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 09:41:50 +0200 Subject: [PATCH 02/11] feat: kongpoluginbinding API complete Signed-off-by: Mattia Lavacca --- .../v1alpha1/kongpluginbinding_types.go | 54 ++-- .../v1alpha1/zz_generated.deepcopy.go | 61 +++-- ...uration.konghq.com_kongpluginbindings.yaml | 237 ++++++++++-------- config/samples/kongpluginbinding.yaml | 18 +- docs/api-reference.md | 28 ++- 5 files changed, 239 insertions(+), 159 deletions(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index 202d796..f2032a6 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -33,11 +33,11 @@ import ( // +kubebuilder:printcolumn:name="Plugin-kind",type=string,JSONPath=`.spec.pluginReference.kind`,description="Kind of the plugin" // +kubebuilder:printcolumn:name="Plugin-name",type=string,JSONPath=`.spec.pluginReference.name`,description="Name of the plugin" // +kubebuilder:printcolumn:name="Programmed",description="The Resource is Programmed",type=string,JSONPath=`.status.conditions[?(@.type=='Programmed')].status` -// +kubebuilder:validation:XValidation:rule="(has(self.spec.kong.consumerRef) && has(self.spec.kong.routeRef) && has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerGroupRef) && has(self.spec.kong.serviceRef) && has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerRef)) || (has(self.spec.kong.consumerRef) && has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerGroupRef) && !has(self.spec.kong.serviceRef)) || (has(self.spec.kong.consumerRef) && has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerGroupRef) && has(self.spec.kong.routeRef) && !has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef)) || (has(self.spec.kong.consumerGroupRef) && has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef) && !has(self.spec.kong.routeRef)) || (has(self.spec.kong.routeRef) && has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef) && !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerRef) && !has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerGroupRef) && !has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerRef)) || (has(self.spec.kong.routeRef) && !has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef) && !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerGroupRef) && !has(self.spec.kong.consumerRef))", message="The combination of entities set is not allowed" type KongPluginBinding struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` + // +kubebuilder:validation:XValidation:message="One field between global and targets must be set",rule="(((has(self.global) && self.global == true) ? !has(self.targets) : true) && (((!has(self.global) || self.global == false) ? has(self.targets) : true) || (!has(self.targets) ? (has(self.global) && self.global == true) : true)))" Spec KongPluginBindingSpec `json:"spec"` Status KongPluginBindingStatus `json:"status,omitempty"` } @@ -65,6 +65,17 @@ type KongPluginBindingSpec struct { // PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required PluginReference PluginRef `json:"pluginRef"` + // +optional + Global *bool `json:"global,omitempty"` + + // +optional + // +kubebuilder:validation:XValidation:message="The combination of entities set is not allowed",rule="(has(self.consumerRef) && has(self.routeRef) && has(self.serviceRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && has(self.serviceRef) && has(self.routeRef) && !has(self.consumerRef)) || (has(self.consumerRef) && has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.serviceRef)) || (has(self.consumerRef) && has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef)) || (has(self.consumerGroupRef) && has(self.serviceRef) && !has(self.consumerRef) && !has(self.routeRef)) || (has(self.routeRef) && has(self.serviceRef) && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.consumerRef) && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerRef)) || (has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.consumerRef))" + // +kubebuilder:validation:XValidation:message="At least one entity reference must be set",rule="has(self.routeRef) || has(self.serviceRef) || has(self.consumerRef) || has(self.consumerGroupRef)" + // +kubebuilder:validation:XValidation:message="KongRoute can be used only when serviceRef is unset or set to KongService, and viceversa",rule="(has(self.routeRef) && self.routeRef.kind == 'KongRoute') ? (!has(self.serviceRef) || self.serviceRef.kind == 'KongService') : true" + Targets *KongPluginBindingTargets `json:"targets,omitempty"` +} + +type KongPluginBindingTargets struct { // Kong contains the Kong entity references. It is possible to set multiple combinations // of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence // The complete set of allowed combinations and their order of precedence for plugins @@ -81,31 +92,26 @@ type KongPluginBindingSpec struct { // 9. Consumer group // 10. Route // 11. Service - // 12. Global // - // TODO(mlavacca): we need to figure out how to deal with global plugins. By means of this new API, - // KongClusterPlugin can be replaced by kongPluginBindings with no Kong references. This way we'd be - // more coherent with the Konnect approach. - // https://github.com/Kong/kubernetes-configuration/issues/7 - - // TODO(mlavacca): RouteReference allows references to KongRoute, Ingress, HTTPRoute, or GCPRoute resource. - // TODO(mlavacca): ServiceReference allows Service or KongService resource. - // TODO(mlavacca): In case the routeRef references a KongRoute, the ServiceRef should be unset or set to a KongService. - // The same applies the other way around. - RouteReference *TargetRefWithGroupKind `json:"routeRef,omitempty"` + // +optional + // +kubebuilder:validation:XValidation:message="group/kind not allowed for the routeRef",rule="(self.kind == 'KongRoute' && self.group == 'configuration.konghq.com') || (self.kind == 'Ingress' && self.group == 'networking.k8s.io') || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') || (self.kind == 'GCPRoute' && self.group == 'gateway.networking.k8s.io')" + RouteReference *TargetRefWithGroupKind `json:"routeRef,omitempty"` + + // +optional + // +kubebuilder:validation:XValidation:message="group/kind not allowed for the serviceRef",rule="(self.kind == 'KongService' && self.group == 'configuration.konghq.com') || (self.kind == 'Service' && (self.group == '' || self.group == 'core'))" ServiceReference *TargetRefWithGroupKind `json:"serviceRef,omitempty"` ConsumerReference *TargetRef `json:"consumerRef,omitempty"` ConsumerGroupReference *TargetRef `json:"consumerGroupRef,omitempty"` } type PluginRef struct { - // TODO(mattia): What about cross-namespace references? Do we want to introduce a namespace field - // to allow such a reference? We could allow it and require a RefGrant. + // TODO(mattia): cross-namespace references are not supported yet. // https://github.com/Kong/kubernetes-configuration/issues/9 // Name is the name of the KongPlugin or KongClusterPlugin resource. // +kubebuilder:validation:Required Name string `json:"name"` + // kind can be KongPlugin or KongClusterPlugin. If not set, it is assumed to be KongPlugin. // +kubebuilder:validation:Enum=KongPlugin;KongClusterPlugin // +kubebuilder:default:=KongPlugin @@ -128,31 +134,15 @@ type TargetRefWithGroupKind struct { // +kubebuilder:validation:Enum=KongService;KongRoute;Service;HTTPRoute;GCPRoute;Ingress Kind string `json:"kind"` - // +kubebuilder:validation:Required - // +kubebuilder:validation:Enum="";core;gateway.networking.k8s.io;networking.k8s.io + // +kubebuilder:validation:Enum="";core;gateway.networking.k8s.io;networking.k8s.io;configuration.konghq.com Group string `json:"group"` } -// type GenericEntityRef struct { -// // Name is the name of the generic entity. -// // +kubebuilder:validation:Required -// Name string `json:"name"` - -// // kind is the kind of the entity. -// // +kubebuilder:validation:Enum=Service;HTTPRoute;GCPRoute;TLSRoute;TCPRoute;UDPRoute;Ingress -// Kind string `json:"kind"` - -// // TODO(mlavacca): add cross-field validation. Kind can be set depending on the group. -// // Group is the group of the entity. -// // +kubebuilder:validation:Enum="";core;gateway.networking.k8s.io;networking.k8s.io -// Group string `json:"group"` -// } - // KongPluginBindingStatus represents the current status of the KongBinding resource. type KongPluginBindingStatus struct { // Konnect contains the Konnect entity status. // +optional - Konnect *konnectv1alpha1.KonnectEntityStatusWithControlPlaneAndServiceRefs `json:"konnect,omitempty"` + Konnect *konnectv1alpha1.KonnectEntityStatusWithControlPlaneRef `json:"konnect,omitempty"` // Conditions describe the status of the Konnect entity. // +listType=map diff --git a/api/configuration/v1alpha1/zz_generated.deepcopy.go b/api/configuration/v1alpha1/zz_generated.deepcopy.go index 57ef064..b80e82e 100644 --- a/api/configuration/v1alpha1/zz_generated.deepcopy.go +++ b/api/configuration/v1alpha1/zz_generated.deepcopy.go @@ -447,25 +447,15 @@ func (in *KongPluginBindingList) DeepCopyObject() runtime.Object { func (in *KongPluginBindingSpec) DeepCopyInto(out *KongPluginBindingSpec) { *out = *in in.PluginReference.DeepCopyInto(&out.PluginReference) - if in.RouteReference != nil { - in, out := &in.RouteReference, &out.RouteReference - *out = new(TargetRefWithGroupKind) - **out = **in - } - if in.ServiceReference != nil { - in, out := &in.ServiceReference, &out.ServiceReference - *out = new(TargetRefWithGroupKind) - **out = **in - } - if in.ConsumerReference != nil { - in, out := &in.ConsumerReference, &out.ConsumerReference - *out = new(TargetRef) + if in.Global != nil { + in, out := &in.Global, &out.Global + *out = new(bool) **out = **in } - if in.ConsumerGroupReference != nil { - in, out := &in.ConsumerGroupReference, &out.ConsumerGroupReference - *out = new(TargetRef) - **out = **in + if in.Targets != nil { + in, out := &in.Targets, &out.Targets + *out = new(KongPluginBindingTargets) + (*in).DeepCopyInto(*out) } } @@ -484,7 +474,7 @@ func (in *KongPluginBindingStatus) DeepCopyInto(out *KongPluginBindingStatus) { *out = *in if in.Konnect != nil { in, out := &in.Konnect, &out.Konnect - *out = new(konnectv1alpha1.KonnectEntityStatusWithControlPlaneAndServiceRefs) + *out = new(konnectv1alpha1.KonnectEntityStatusWithControlPlaneRef) **out = **in } if in.Conditions != nil { @@ -506,6 +496,41 @@ func (in *KongPluginBindingStatus) DeepCopy() *KongPluginBindingStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KongPluginBindingTargets) DeepCopyInto(out *KongPluginBindingTargets) { + *out = *in + if in.RouteReference != nil { + in, out := &in.RouteReference, &out.RouteReference + *out = new(TargetRefWithGroupKind) + **out = **in + } + if in.ServiceReference != nil { + in, out := &in.ServiceReference, &out.ServiceReference + *out = new(TargetRefWithGroupKind) + **out = **in + } + if in.ConsumerReference != nil { + in, out := &in.ConsumerReference, &out.ConsumerReference + *out = new(TargetRef) + **out = **in + } + if in.ConsumerGroupReference != nil { + in, out := &in.ConsumerGroupReference, &out.ConsumerGroupReference + *out = new(TargetRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongPluginBindingTargets. +func (in *KongPluginBindingTargets) DeepCopy() *KongPluginBindingTargets { + if in == nil { + return nil + } + out := new(KongPluginBindingTargets) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KongRoute) DeepCopyInto(out *KongRoute) { *out = *in diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index e71c80b..06f6d9d 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -53,22 +53,8 @@ spec: spec: description: KongPluginBindingSpec defines specification of a KongPluginBinding. properties: - consumerGroupRef: - properties: - name: - description: Name is the name of the entity. - type: string - required: - - name - type: object - consumerRef: - properties: - name: - description: Name is the name of the entity. - type: string - required: - - name - type: object + global: + type: boolean pluginRef: description: PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required @@ -88,67 +74,144 @@ spec: required: - name type: object - routeRef: - description: |- - TODO(mlavacca): RouteReference allows references to KongRoute, Ingress, HTTPRoute, or GCPRoute resource. - TODO(mlavacca): ServiceReference allows Service or KongService resource. - TODO(mlavacca): In case the routeRef references a KongRoute, the ServiceRef should be unset or set to a KongService. - The same applies the other way around. - properties: - group: - enum: - - "" - - core - - gateway.networking.k8s.io - - networking.k8s.io - type: string - kind: - enum: - - KongService - - KongRoute - - Service - - HTTPRoute - - GCPRoute - - Ingress - type: string - name: - description: Name is the name of the entity. - type: string - required: - - group - - kind - - name - type: object - serviceRef: - description: 'TODO(mlavacca): add xvalidation between group and kind' + targets: properties: - group: - enum: - - "" - - core - - gateway.networking.k8s.io - - networking.k8s.io - type: string - kind: - enum: - - KongService - - KongRoute - - Service - - HTTPRoute - - GCPRoute - - Ingress - type: string - name: - description: Name is the name of the entity. - type: string - required: - - group - - kind - - name + consumerGroupRef: + properties: + name: + description: Name is the name of the entity. + type: string + required: + - name + type: object + consumerRef: + properties: + name: + description: Name is the name of the entity. + type: string + required: + - name + type: object + routeRef: + description: |- + Kong contains the Kong entity references. It is possible to set multiple combinations + of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence + The complete set of allowed combinations and their order of precedence for plugins + configured to multiple entities is: + + + 1. Consumer + route + service + 2. Consumer group + service + route + 3. Consumer + route + 4. Consumer + service + 5. Consumer group + route + 6. Consumer group + service + 7. Route + service + 8. Consumer + 9. Consumer group + 10. Route + 11. Service + properties: + group: + enum: + - "" + - core + - gateway.networking.k8s.io + - networking.k8s.io + - configuration.konghq.com + type: string + kind: + enum: + - KongService + - KongRoute + - Service + - HTTPRoute + - GCPRoute + - Ingress + type: string + name: + description: Name is the name of the entity. + type: string + required: + - group + - kind + - name + type: object + x-kubernetes-validations: + - message: group/kind not allowed for the routeRef + rule: (self.kind == 'KongRoute' && self.group == 'configuration.konghq.com') + || (self.kind == 'Ingress' && self.group == 'networking.k8s.io') + || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') + || (self.kind == 'GCPRoute' && self.group == 'gateway.networking.k8s.io') + serviceRef: + description: 'TODO(mlavacca): add xvalidation between group and + kind' + properties: + group: + enum: + - "" + - core + - gateway.networking.k8s.io + - networking.k8s.io + - configuration.konghq.com + type: string + kind: + enum: + - KongService + - KongRoute + - Service + - HTTPRoute + - GCPRoute + - Ingress + type: string + name: + description: Name is the name of the entity. + type: string + required: + - group + - kind + - name + type: object + x-kubernetes-validations: + - message: group/kind not allowed for the serviceRef + rule: (self.kind == 'KongService' && self.group == 'configuration.konghq.com') + || (self.kind == 'Service' && (self.group == '' || self.group + == 'core')) type: object + x-kubernetes-validations: + - message: The combination of entities set is not allowed + rule: (has(self.consumerRef) && has(self.routeRef) && has(self.serviceRef) + && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) + && has(self.serviceRef) && has(self.routeRef) && !has(self.consumerRef)) + || (has(self.consumerRef) && has(self.routeRef) && !has(self.consumerGroupRef) + && !has(self.serviceRef)) || (has(self.consumerRef) && has(self.serviceRef) + && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) + && has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef)) + || (has(self.consumerGroupRef) && has(self.serviceRef) && !has(self.consumerRef) + && !has(self.routeRef)) || (has(self.routeRef) && has(self.serviceRef) + && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.consumerRef) + && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) + || (has(self.consumerGroupRef) && !has(self.serviceRef) && !has(self.routeRef) + && !has(self.consumerRef)) || (has(self.routeRef) && !has(self.serviceRef) + && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.serviceRef) + && !has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.consumerRef)) + - message: At least one entity reference must be set + rule: has(self.routeRef) || has(self.serviceRef) || has(self.consumerRef) + || has(self.consumerGroupRef) + - message: KongRoute can be used only when serviceRef is unset or + set to KongService, and viceversa + rule: '(has(self.routeRef) && self.routeRef.kind == ''KongRoute'') + ? (!has(self.serviceRef) || self.serviceRef.kind == ''KongService'') + : true' required: - pluginRef type: object + x-kubernetes-validations: + - message: One field between global and targets must be set + rule: '(((has(self.global) && self.global == true) ? !has(self.targets) + : true) && (((!has(self.global) || self.global == false) ? has(self.targets) + : true) || (!has(self.targets) ? (has(self.global) && self.global + == true) : true)))' status: description: KongPluginBindingStatus represents the current status of the KongBinding resource. @@ -239,7 +302,7 @@ spec: properties: controlPlaneID: description: ControlPlaneID is the Konnect ID of the ControlPlane - this entity is associated with. + this Route is associated with. type: string id: description: |- @@ -254,39 +317,11 @@ spec: description: ServerURL is the URL of the Konnect server in which the entity exists. type: string - serviceID: - description: ServiceID is the Konnect ID of the Service this entity - is associated with. - type: string type: object type: object required: - spec type: object - x-kubernetes-validations: - - message: The combination of entities set is not allowed - rule: (has(self.spec.kong.consumerRef) && has(self.spec.kong.routeRef) && - has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerGroupRef)) - || (has(self.spec.kong.consumerGroupRef) && has(self.spec.kong.serviceRef) - && has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerRef)) || - (has(self.spec.kong.consumerRef) && has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerGroupRef) - && !has(self.spec.kong.serviceRef)) || (has(self.spec.kong.consumerRef) - && has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && - !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerGroupRef) - && has(self.spec.kong.routeRef) && !has(self.spec.kong.serviceRef) && - !has(self.spec.kong.consumerRef)) || (has(self.spec.kong.consumerGroupRef) - && has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef) - && !has(self.spec.kong.routeRef)) || (has(self.spec.kong.routeRef) && - has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef) && - !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerRef) - && !has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && - !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.consumerGroupRef) - && !has(self.spec.kong.serviceRef) && !has(self.spec.kong.routeRef) && - !has(self.spec.kong.consumerRef)) || (has(self.spec.kong.routeRef) && - !has(self.spec.kong.serviceRef) && !has(self.spec.kong.consumerRef) && - !has(self.spec.kong.consumerGroupRef)) || (has(self.spec.kong.serviceRef) - && !has(self.spec.kong.routeRef) && !has(self.spec.kong.consumerGroupRef) - && !has(self.spec.kong.consumerRef)) served: true storage: true subresources: diff --git a/config/samples/kongpluginbinding.yaml b/config/samples/kongpluginbinding.yaml index 346a650..706232a 100644 --- a/config/samples/kongpluginbinding.yaml +++ b/config/samples/kongpluginbinding.yaml @@ -2,14 +2,28 @@ apiVersion: configuration.konghq.com/v1alpha1 kind: KongPluginBinding metadata: generation: 1 - name: sample-1 + name: targeted-binding spec: pluginRef: name: plugin-sample - kong: + targets: consumerRef: name: consumer-sample serviceRef: name: service-sample + kind: KongService + group: configuration.konghq.com routeRef: name: route-sample + kind: KongRoute + group: configuration.konghq.com +--- +apiVersion: configuration.konghq.com/v1alpha1 +kind: KongPluginBinding +metadata: + generation: 1 + name: global-binding +spec: + pluginRef: + name: plugin-sample + global: true diff --git a/docs/api-reference.md b/docs/api-reference.md index 68c2ed0..1ec3f87 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -599,10 +599,8 @@ KongPluginBindingSpec defines specification of a KongPluginBinding. | Field | Description | | --- | --- | | `pluginRef` _[PluginRef](#pluginref)_ | PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required | -| `routeRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | TODO(mlavacca): RouteReference allows references to KongRoute, Ingress, HTTPRoute, or GCPRoute resource. TODO(mlavacca): ServiceReference allows Service or KongService resource. TODO(mlavacca): In case the routeRef references a KongRoute, the ServiceRef should be unset or set to a KongService. The same applies the other way around. | -| `serviceRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | | -| `consumerRef` _[TargetRef](#targetref)_ | | -| `consumerGroupRef` _[TargetRef](#targetref)_ | | +| `global` _boolean_ | | +| `targets` _[KongPluginBindingTargets](#kongpluginbindingtargets)_ | | _Appears in:_ @@ -610,6 +608,24 @@ _Appears in:_ +#### KongPluginBindingTargets + + + + + + +| Field | Description | +| --- | --- | +| `routeRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | Kong contains the Kong entity references. It is possible to set multiple combinations of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence The complete set of allowed combinations and their order of precedence for plugins configured to multiple entities is:

1. Consumer + route + service 2. Consumer group + service + route 3. Consumer + route 4. Consumer + service 5. Consumer group + route 6. Consumer group + service 7. Route + service 8. Consumer 9. Consumer group 10. Route 11. Service | +| `serviceRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | | +| `consumerRef` _[TargetRef](#targetref)_ | | +| `consumerGroupRef` _[TargetRef](#targetref)_ | | + + +_Appears in:_ +- [KongPluginBindingSpec](#kongpluginbindingspec) + #### KongRouteAPISpec @@ -880,7 +896,7 @@ _Appears in:_ _Appears in:_ -- [KongPluginBindingSpec](#kongpluginbindingspec) +- [KongPluginBindingTargets](#kongpluginbindingtargets) #### TargetRefWithGroupKind @@ -897,7 +913,7 @@ TODO(mlavacca): add xvalidation between group and kind _Appears in:_ -- [KongPluginBindingSpec](#kongpluginbindingspec) +- [KongPluginBindingTargets](#kongpluginbindingtargets) ## configuration.konghq.com/v1beta1 From d06e961e78345ad46b1a882c995062b8dfce22a3 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 13:39:20 +0200 Subject: [PATCH 03/11] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk Małek --- config/samples/kongpluginbinding.yaml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/config/samples/kongpluginbinding.yaml b/config/samples/kongpluginbinding.yaml index 706232a..11976ac 100644 --- a/config/samples/kongpluginbinding.yaml +++ b/config/samples/kongpluginbinding.yaml @@ -2,7 +2,7 @@ apiVersion: configuration.konghq.com/v1alpha1 kind: KongPluginBinding metadata: generation: 1 - name: targeted-binding + name: plugin-binding-kongservice-kongroute-kongconsumer spec: pluginRef: name: plugin-sample @@ -18,6 +18,21 @@ spec: kind: KongRoute group: configuration.konghq.com --- +kind: KongPluginBinding +metadata: + generation: 1 + name: plugin-binding-kongservice-kongconsumer +spec: + pluginRef: + name: plugin-sample + targets: + consumerRef: + name: consumer-sample + serviceRef: + name: service-sample + kind: KongService + group: configuration.konghq.com +--- apiVersion: configuration.konghq.com/v1alpha1 kind: KongPluginBinding metadata: From c341796c745d7b0e473d800e2f922cb40a3536b4 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 13:41:13 +0200 Subject: [PATCH 04/11] chore: remove out of date comment Signed-off-by: Mattia Lavacca --- api/configuration/v1alpha1/kongpluginbinding_types.go | 1 - .../crd/bases/configuration.konghq.com_kongpluginbindings.yaml | 2 -- docs/api-reference.md | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index f2032a6..e3c5512 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -124,7 +124,6 @@ type TargetRef struct { Name string `json:"name"` } -// TODO(mlavacca): add xvalidation between group and kind type TargetRefWithGroupKind struct { // Name is the name of the entity. // +kubebuilder:validation:Required diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index 06f6d9d..dc53e82 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -144,8 +144,6 @@ spec: || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') || (self.kind == 'GCPRoute' && self.group == 'gateway.networking.k8s.io') serviceRef: - description: 'TODO(mlavacca): add xvalidation between group and - kind' properties: group: enum: diff --git a/docs/api-reference.md b/docs/api-reference.md index 1ec3f87..72d5fc5 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -901,7 +901,7 @@ _Appears in:_ #### TargetRefWithGroupKind -TODO(mlavacca): add xvalidation between group and kind + From 085feef2ead84161b6df16e34f6e6afb322b6457 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 13:43:01 +0200 Subject: [PATCH 05/11] complex rule split into two simpler ones Signed-off-by: Mattia Lavacca --- api/configuration/v1alpha1/kongpluginbinding_types.go | 3 ++- .../configuration.konghq.com_kongpluginbindings.yaml | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index e3c5512..7c57ebd 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -37,7 +37,8 @@ type KongPluginBinding struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - // +kubebuilder:validation:XValidation:message="One field between global and targets must be set",rule="(((has(self.global) && self.global == true) ? !has(self.targets) : true) && (((!has(self.global) || self.global == false) ? has(self.targets) : true) || (!has(self.targets) ? (has(self.global) && self.global == true) : true)))" + // +kubebuilder:validation:XValidation:message="When global is set, target refs cannot be used",rule="(has(self.global) && self.global == true) ? !has(self.targets) : true" + // +kubebuilder:validation:XValidation:message="When global is unset, target refs have to be used",rule="(!has(self.global) || self.global == false) ? has(self.targets) : true" Spec KongPluginBindingSpec `json:"spec"` Status KongPluginBindingStatus `json:"status,omitempty"` } diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index dc53e82..126e442 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -205,11 +205,12 @@ spec: - pluginRef type: object x-kubernetes-validations: - - message: One field between global and targets must be set - rule: '(((has(self.global) && self.global == true) ? !has(self.targets) - : true) && (((!has(self.global) || self.global == false) ? has(self.targets) - : true) || (!has(self.targets) ? (has(self.global) && self.global - == true) : true)))' + - message: When global is set, target refs cannot be used + rule: '(has(self.global) && self.global == true) ? !has(self.targets) + : true' + - message: When global is unset, target refs have to be used + rule: '(!has(self.global) || self.global == false) ? has(self.targets) + : true' status: description: KongPluginBindingStatus represents the current status of the KongBinding resource. From bbeb8d1abd590607df197520424dc255390c9289 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 13:47:40 +0200 Subject: [PATCH 06/11] fix: add ApiVersion to sample Signed-off-by: Mattia Lavacca --- config/samples/kongpluginbinding.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/samples/kongpluginbinding.yaml b/config/samples/kongpluginbinding.yaml index 11976ac..27e8f06 100644 --- a/config/samples/kongpluginbinding.yaml +++ b/config/samples/kongpluginbinding.yaml @@ -18,6 +18,7 @@ spec: kind: KongRoute group: configuration.konghq.com --- +apiVersion: configuration.konghq.com/v1alpha1 kind: KongPluginBinding metadata: generation: 1 From ad1b249300651aef57f9ee41228e2a018c976cb0 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 13:53:52 +0200 Subject: [PATCH 07/11] chore: removed redundant "required" directive Signed-off-by: Mattia Lavacca --- api/configuration/v1alpha1/kongpluginbinding_types.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index 7c57ebd..59af8f6 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -130,7 +130,6 @@ type TargetRefWithGroupKind struct { // +kubebuilder:validation:Required Name string `json:"name"` - // +kubebuilder:validation:Required // +kubebuilder:validation:Enum=KongService;KongRoute;Service;HTTPRoute;GCPRoute;Ingress Kind string `json:"kind"` From 7c4ef3d4851e7bb13a3f20e397f9ec9eb792102e Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 15:55:37 +0200 Subject: [PATCH 08/11] Update api/configuration/v1alpha1/kongpluginbinding_types.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk Małek --- api/configuration/v1alpha1/kongpluginbinding_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index 59af8f6..e0f1581 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -95,7 +95,7 @@ type KongPluginBindingTargets struct { // 11. Service // // +optional - // +kubebuilder:validation:XValidation:message="group/kind not allowed for the routeRef",rule="(self.kind == 'KongRoute' && self.group == 'configuration.konghq.com') || (self.kind == 'Ingress' && self.group == 'networking.k8s.io') || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') || (self.kind == 'GCPRoute' && self.group == 'gateway.networking.k8s.io')" + // +kubebuilder:validation:XValidation:message="group/kind not allowed for the routeRef",rule="(self.kind == 'KongRoute' && self.group == 'configuration.konghq.com') || (self.kind == 'Ingress' && self.group == 'networking.k8s.io') || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') || (self.kind == 'GRPCRoute' && self.group == 'gateway.networking.k8s.io')" RouteReference *TargetRefWithGroupKind `json:"routeRef,omitempty"` // +optional From 86ac6fe50f08c0a38fc7fe9e9626ff13a1f7ab5d Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 16:10:39 +0200 Subject: [PATCH 09/11] chore: comments improved Signed-off-by: Mattia Lavacca --- .../v1alpha1/kongpluginbinding_types.go | 52 +++++++++---- ...uration.konghq.com_kongpluginbindings.yaml | 74 +++++++++++-------- docs/api-reference.md | 20 ++--- 3 files changed, 92 insertions(+), 54 deletions(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index e0f1581..1ef7271 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -43,10 +43,12 @@ type KongPluginBinding struct { Status KongPluginBindingStatus `json:"status,omitempty"` } +// GetKonnectStatus returns the Konnect status contained in the KongPluginBinding status. func (c *KongPluginBinding) GetKonnectStatus() *konnectv1alpha1.KonnectEntityStatus { return &c.Status.Konnect.KonnectEntityStatus } +// GetTypeName return the KongPluginBinding Kind name func (c KongPluginBinding) GetTypeName() string { return "KongPluginBinding" } @@ -69,15 +71,7 @@ type KongPluginBindingSpec struct { // +optional Global *bool `json:"global,omitempty"` - // +optional - // +kubebuilder:validation:XValidation:message="The combination of entities set is not allowed",rule="(has(self.consumerRef) && has(self.routeRef) && has(self.serviceRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && has(self.serviceRef) && has(self.routeRef) && !has(self.consumerRef)) || (has(self.consumerRef) && has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.serviceRef)) || (has(self.consumerRef) && has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef)) || (has(self.consumerGroupRef) && has(self.serviceRef) && !has(self.consumerRef) && !has(self.routeRef)) || (has(self.routeRef) && has(self.serviceRef) && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.consumerRef) && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerRef)) || (has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.consumerRef))" - // +kubebuilder:validation:XValidation:message="At least one entity reference must be set",rule="has(self.routeRef) || has(self.serviceRef) || has(self.consumerRef) || has(self.consumerGroupRef)" - // +kubebuilder:validation:XValidation:message="KongRoute can be used only when serviceRef is unset or set to KongService, and viceversa",rule="(has(self.routeRef) && self.routeRef.kind == 'KongRoute') ? (!has(self.serviceRef) || self.serviceRef.kind == 'KongService') : true" - Targets *KongPluginBindingTargets `json:"targets,omitempty"` -} - -type KongPluginBindingTargets struct { - // Kong contains the Kong entity references. It is possible to set multiple combinations + // Targets contains the targets references. It is possible to set multiple combinations // of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence // The complete set of allowed combinations and their order of precedence for plugins // configured to multiple entities is: @@ -95,16 +89,42 @@ type KongPluginBindingTargets struct { // 11. Service // // +optional + // +kubebuilder:validation:XValidation:message="The combination of entities set is not allowed",rule="(has(self.consumerRef) && has(self.routeRef) && has(self.serviceRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && has(self.serviceRef) && has(self.routeRef) && !has(self.consumerRef)) || (has(self.consumerRef) && has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.serviceRef)) || (has(self.consumerRef) && has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef)) || (has(self.consumerGroupRef) && has(self.serviceRef) && !has(self.consumerRef) && !has(self.routeRef)) || (has(self.routeRef) && has(self.serviceRef) && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.consumerRef) && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef)) || (has(self.consumerGroupRef) && !has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerRef)) || (has(self.routeRef) && !has(self.serviceRef) && !has(self.consumerRef) && !has(self.consumerGroupRef)) || (has(self.serviceRef) && !has(self.routeRef) && !has(self.consumerGroupRef) && !has(self.consumerRef))" + // +kubebuilder:validation:XValidation:message="At least one entity reference must be set",rule="has(self.routeRef) || has(self.serviceRef) || has(self.consumerRef) || has(self.consumerGroupRef)" + // +kubebuilder:validation:XValidation:message="KongRoute can be used only when serviceRef is unset or set to KongService, and viceversa",rule="(has(self.routeRef) && self.routeRef.kind == 'KongRoute') ? (!has(self.serviceRef) || self.serviceRef.kind == 'KongService') : true" + Targets *KongPluginBindingTargets `json:"targets,omitempty"` +} + +// KongPluginBindingTargets contains the targets references. +type KongPluginBindingTargets struct { + // RouteReference can be used to reference one of the following resouces: + // - networking.k8s.io/Ingress + // - gateway.networking.k8s.io/HTTPRoute + // - gateway.networking.k8s.io/GRPCRoute + // - configuration.konghq.com/KongRoute + // + // +optional // +kubebuilder:validation:XValidation:message="group/kind not allowed for the routeRef",rule="(self.kind == 'KongRoute' && self.group == 'configuration.konghq.com') || (self.kind == 'Ingress' && self.group == 'networking.k8s.io') || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') || (self.kind == 'GRPCRoute' && self.group == 'gateway.networking.k8s.io')" RouteReference *TargetRefWithGroupKind `json:"routeRef,omitempty"` + // ServiceReference can be used to reference one of the following resouces: + // - core/Service or /Service + // - configuration.konghq.com/KongService + // // +optional // +kubebuilder:validation:XValidation:message="group/kind not allowed for the serviceRef",rule="(self.kind == 'KongService' && self.group == 'configuration.konghq.com') || (self.kind == 'Service' && (self.group == '' || self.group == 'core'))" - ServiceReference *TargetRefWithGroupKind `json:"serviceRef,omitempty"` - ConsumerReference *TargetRef `json:"consumerRef,omitempty"` - ConsumerGroupReference *TargetRef `json:"consumerGroupRef,omitempty"` + ServiceReference *TargetRefWithGroupKind `json:"serviceRef,omitempty"` + + // ConsumerReference is used to reference a configuration.konghq.com/Consumer resource. + // The group/kind is fixed, therefore the reference is performed only by name. + ConsumerReference *TargetRef `json:"consumerRef,omitempty"` + + // ConsumerGroupReference is used to reference a configuration.konghq.com/ConsumerGroup resource. + // The group/kind is fixed, therefore the reference is performed only by name. + ConsumerGroupReference *TargetRef `json:"consumerGroupRef,omitempty"` } +// PluginRef is a reference to a KongPlugin or KongClusterPlugin resource. type PluginRef struct { // TODO(mattia): cross-namespace references are not supported yet. // https://github.com/Kong/kubernetes-configuration/issues/9 @@ -113,27 +133,29 @@ type PluginRef struct { // +kubebuilder:validation:Required Name string `json:"name"` - // kind can be KongPlugin or KongClusterPlugin. If not set, it is assumed to be KongPlugin. + // Kind can be KongPlugin or KongClusterPlugin. If not set, it is assumed to be KongPlugin. // +kubebuilder:validation:Enum=KongPlugin;KongClusterPlugin // +kubebuilder:default:=KongPlugin Kind *string `json:"kind,omitempty"` } +// TargetRef is a reference based on the object's name. type TargetRef struct { // Name is the name of the entity. // +kubebuilder:validation:Required Name string `json:"name"` } +// TargetRefWithGroupKind is a reference based on the object's group, kind, and name. type TargetRefWithGroupKind struct { // Name is the name of the entity. // +kubebuilder:validation:Required Name string `json:"name"` - // +kubebuilder:validation:Enum=KongService;KongRoute;Service;HTTPRoute;GCPRoute;Ingress + // +kubebuilder:validation:Enum=Service;Ingress;HTTPRoute;GRPCRoute;KongService;KongRoute Kind string `json:"kind"` - // +kubebuilder:validation:Enum="";core;gateway.networking.k8s.io;networking.k8s.io;configuration.konghq.com + // +kubebuilder:validation:Enum="";core;networking.k8s.io;gateway.networking.k8s.io;configuration.konghq.com Group string `json:"group"` } diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index 126e442..e23f6f9 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -61,7 +61,7 @@ spec: properties: kind: default: KongPlugin - description: kind can be KongPlugin or KongClusterPlugin. If not + description: Kind can be KongPlugin or KongClusterPlugin. If not set, it is assumed to be KongPlugin. enum: - KongPlugin @@ -75,8 +75,29 @@ spec: - name type: object targets: + description: |- + Targets contains the targets references. It is possible to set multiple combinations + of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence + The complete set of allowed combinations and their order of precedence for plugins + configured to multiple entities is: + + + 1. Consumer + route + service + 2. Consumer group + service + route + 3. Consumer + route + 4. Consumer + service + 5. Consumer group + route + 6. Consumer group + service + 7. Route + service + 8. Consumer + 9. Consumer group + 10. Route + 11. Service properties: consumerGroupRef: + description: |- + ConsumerGroupReference is used to reference a configuration.konghq.com/ConsumerGroup resource. + The group/kind is fixed, therefore the reference is performed only by name. properties: name: description: Name is the name of the entity. @@ -85,6 +106,9 @@ spec: - name type: object consumerRef: + description: |- + ConsumerReference is used to reference a configuration.konghq.com/Consumer resource. + The group/kind is fixed, therefore the reference is performed only by name. properties: name: description: Name is the name of the entity. @@ -94,40 +118,28 @@ spec: type: object routeRef: description: |- - Kong contains the Kong entity references. It is possible to set multiple combinations - of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence - The complete set of allowed combinations and their order of precedence for plugins - configured to multiple entities is: - - - 1. Consumer + route + service - 2. Consumer group + service + route - 3. Consumer + route - 4. Consumer + service - 5. Consumer group + route - 6. Consumer group + service - 7. Route + service - 8. Consumer - 9. Consumer group - 10. Route - 11. Service + RouteReference can be used to reference one of the following resouces: + - networking.k8s.io/Ingress + - gateway.networking.k8s.io/HTTPRoute + - gateway.networking.k8s.io/GRPCRoute + - configuration.konghq.com/KongRoute properties: group: enum: - "" - core - - gateway.networking.k8s.io - networking.k8s.io + - gateway.networking.k8s.io - configuration.konghq.com type: string kind: enum: - - KongService - - KongRoute - Service - - HTTPRoute - - GCPRoute - Ingress + - HTTPRoute + - GRPCRoute + - KongService + - KongRoute type: string name: description: Name is the name of the entity. @@ -142,25 +154,29 @@ spec: rule: (self.kind == 'KongRoute' && self.group == 'configuration.konghq.com') || (self.kind == 'Ingress' && self.group == 'networking.k8s.io') || (self.kind == 'HTTPRoute' && self.group == 'gateway.networking.k8s.io') - || (self.kind == 'GCPRoute' && self.group == 'gateway.networking.k8s.io') + || (self.kind == 'GRPCRoute' && self.group == 'gateway.networking.k8s.io') serviceRef: + description: |- + ServiceReference can be used to reference one of the following resouces: + - core/Service or /Service + - configuration.konghq.com/KongService properties: group: enum: - "" - core - - gateway.networking.k8s.io - networking.k8s.io + - gateway.networking.k8s.io - configuration.konghq.com type: string kind: enum: - - KongService - - KongRoute - Service - - HTTPRoute - - GCPRoute - Ingress + - HTTPRoute + - GRPCRoute + - KongService + - KongRoute type: string name: description: Name is the name of the entity. diff --git a/docs/api-reference.md b/docs/api-reference.md index 72d5fc5..3cf03ce 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -600,7 +600,7 @@ KongPluginBindingSpec defines specification of a KongPluginBinding. | --- | --- | | `pluginRef` _[PluginRef](#pluginref)_ | PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required | | `global` _boolean_ | | -| `targets` _[KongPluginBindingTargets](#kongpluginbindingtargets)_ | | +| `targets` _[KongPluginBindingTargets](#kongpluginbindingtargets)_ | Targets contains the targets references. It is possible to set multiple combinations of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence The complete set of allowed combinations and their order of precedence for plugins configured to multiple entities is:

1. Consumer + route + service 2. Consumer group + service + route 3. Consumer + route 4. Consumer + service 5. Consumer group + route 6. Consumer group + service 7. Route + service 8. Consumer 9. Consumer group 10. Route 11. Service | _Appears in:_ @@ -611,16 +611,16 @@ _Appears in:_ #### KongPluginBindingTargets - +KongPluginBindingTargets contains the targets references. | Field | Description | | --- | --- | -| `routeRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | Kong contains the Kong entity references. It is possible to set multiple combinations of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence The complete set of allowed combinations and their order of precedence for plugins configured to multiple entities is:

1. Consumer + route + service 2. Consumer group + service + route 3. Consumer + route 4. Consumer + service 5. Consumer group + route 6. Consumer group + service 7. Route + service 8. Consumer 9. Consumer group 10. Route 11. Service | -| `serviceRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | | -| `consumerRef` _[TargetRef](#targetref)_ | | -| `consumerGroupRef` _[TargetRef](#targetref)_ | | +| `routeRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | RouteReference can be used to reference one of the following resouces: - networking.k8s.io/Ingress - gateway.networking.k8s.io/HTTPRoute - gateway.networking.k8s.io/GRPCRoute - configuration.konghq.com/KongRoute | +| `serviceRef` _[TargetRefWithGroupKind](#targetrefwithgroupkind)_ | ServiceReference can be used to reference one of the following resouces: - core/Service or /Service - configuration.konghq.com/KongService | +| `consumerRef` _[TargetRef](#targetref)_ | ConsumerReference is used to reference a configuration.konghq.com/Consumer resource. The group/kind is fixed, therefore the reference is performed only by name. | +| `consumerGroupRef` _[TargetRef](#targetref)_ | ConsumerGroupReference is used to reference a configuration.konghq.com/ConsumerGroup resource. The group/kind is fixed, therefore the reference is performed only by name. | _Appears in:_ @@ -854,14 +854,14 @@ _Appears in:_ #### PluginRef - +PluginRef is a reference to a KongPlugin or KongClusterPlugin resource. | Field | Description | | --- | --- | | `name` _string_ | Name is the name of the KongPlugin or KongClusterPlugin resource. | -| `kind` _string_ | kind can be KongPlugin or KongClusterPlugin. If not set, it is assumed to be KongPlugin. | +| `kind` _string_ | Kind can be KongPlugin or KongClusterPlugin. If not set, it is assumed to be KongPlugin. | _Appears in:_ @@ -886,7 +886,7 @@ _Appears in:_ #### TargetRef - +TargetRef is a reference based on the object's name. @@ -901,7 +901,7 @@ _Appears in:_ #### TargetRefWithGroupKind - +TargetRefWithGroupKind is a reference based on the object's group, kind, and name. From 925b84b4978b0814a7e682cba749db2b085f2daa Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 16:21:07 +0200 Subject: [PATCH 10/11] Update api/configuration/v1alpha1/kongpluginbinding_types.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk Małek --- api/configuration/v1alpha1/kongpluginbinding_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index 1ef7271..3b90948 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -48,7 +48,7 @@ func (c *KongPluginBinding) GetKonnectStatus() *konnectv1alpha1.KonnectEntitySta return &c.Status.Konnect.KonnectEntityStatus } -// GetTypeName return the KongPluginBinding Kind name +// GetTypeName returns the KongPluginBinding Kind name func (c KongPluginBinding) GetTypeName() string { return "KongPluginBinding" } From 8add837b7df826d9ab2c6032d2689140f497c7e2 Mon Sep 17 00:00:00 2001 From: Mattia Lavacca Date: Thu, 8 Aug 2024 16:26:44 +0200 Subject: [PATCH 11/11] chore: added godoc for Global Signed-off-by: Mattia Lavacca --- api/configuration/v1alpha1/kongpluginbinding_types.go | 2 ++ .../crd/bases/configuration.konghq.com_kongpluginbindings.yaml | 3 +++ docs/api-reference.md | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/api/configuration/v1alpha1/kongpluginbinding_types.go b/api/configuration/v1alpha1/kongpluginbinding_types.go index 3b90948..0e9168f 100644 --- a/api/configuration/v1alpha1/kongpluginbinding_types.go +++ b/api/configuration/v1alpha1/kongpluginbinding_types.go @@ -68,6 +68,8 @@ type KongPluginBindingSpec struct { // PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required PluginReference PluginRef `json:"pluginRef"` + // Global can be set to automatically target all the entities in the Kong cluster. When set to true, + // all the services, routes and consumers in the Kong cluster are targeted by the plugin. // +optional Global *bool `json:"global,omitempty"` diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index e23f6f9..9ea4ed0 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -54,6 +54,9 @@ spec: description: KongPluginBindingSpec defines specification of a KongPluginBinding. properties: global: + description: |- + Global can be set to automatically target all the entities in the Kong cluster. When set to true, + all the services, routes and consumers in the Kong cluster are targeted by the plugin. type: boolean pluginRef: description: PluginReference is a reference to the KongPlugin or KongClusterPlugin diff --git a/docs/api-reference.md b/docs/api-reference.md index 3cf03ce..e0ae892 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -599,7 +599,7 @@ KongPluginBindingSpec defines specification of a KongPluginBinding. | Field | Description | | --- | --- | | `pluginRef` _[PluginRef](#pluginref)_ | PluginReference is a reference to the KongPlugin or KongClusterPlugin resource. It is required | -| `global` _boolean_ | | +| `global` _boolean_ | Global can be set to automatically target all the entities in the Kong cluster. When set to true, all the services, routes and consumers in the Kong cluster are targeted by the plugin. | | `targets` _[KongPluginBindingTargets](#kongpluginbindingtargets)_ | Targets contains the targets references. It is possible to set multiple combinations of references, as described in https://docs.konghq.com/gateway/latest/key-concepts/plugins/#precedence The complete set of allowed combinations and their order of precedence for plugins configured to multiple entities is:

1. Consumer + route + service 2. Consumer group + service + route 3. Consumer + route 4. Consumer + service 5. Consumer group + route 6. Consumer group + service 7. Route + service 8. Consumer 9. Consumer group 10. Route 11. Service |