diff --git a/Makefile b/Makefile index f7422d169..a2c5e74d9 100644 --- a/Makefile +++ b/Makefile @@ -295,7 +295,7 @@ endef .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) crd paths="./api/v1alpha1;./api/v1beta1;./api/v1beta2" output:crd:artifacts:config=config/crd/bases + $(CONTROLLER_GEN) crd paths="./api/v1alpha1;./api/v1beta1;./api/v1beta2;./api/v1beta3" output:crd:artifacts:config=config/crd/bases $(CONTROLLER_GEN) rbac:roleName=manager-role webhook paths="./..." .PHONY: dependencies-manifests diff --git a/api/v1beta2/topology.go b/api/v1beta2/topology.go index 25b398e29..2b6efe9bd 100644 --- a/api/v1beta2/topology.go +++ b/api/v1beta2/topology.go @@ -8,10 +8,8 @@ import ( ) var ( - AuthPoliciesResource = GroupVersion.WithResource("authpolicies") - AuthPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "AuthPolicy"} - RateLimitPoliciesResource = GroupVersion.WithResource("ratelimitpolicies") - RateLimitPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "RateLimitPolicy"} + AuthPoliciesResource = GroupVersion.WithResource("authpolicies") + AuthPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "AuthPolicy"} ) var _ machinery.Policy = &AuthPolicy{} @@ -38,28 +36,3 @@ func (ap *AuthPolicy) Merge(other machinery.Policy) machinery.Policy { func (ap *AuthPolicy) GetLocator() string { return machinery.LocatorFromObject(ap) } - -var _ machinery.Policy = &RateLimitPolicy{} - -func (r *RateLimitPolicy) GetTargetRefs() []machinery.PolicyTargetReference { - return []machinery.PolicyTargetReference{ - machinery.LocalPolicyTargetReference{ - LocalPolicyTargetReference: r.Spec.TargetRef, - PolicyNamespace: r.Namespace, - }, - } -} - -func (r *RateLimitPolicy) GetMergeStrategy() machinery.MergeStrategy { - return func(policy machinery.Policy, _ machinery.Policy) machinery.Policy { - return policy - } -} - -func (r *RateLimitPolicy) Merge(other machinery.Policy) machinery.Policy { - return other -} - -func (r *RateLimitPolicy) GetLocator() string { - return machinery.LocatorFromObject(r) -} diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 3ca4e42ef..bcdb917cb 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -322,43 +322,6 @@ func (in *HeaderSuccessResponseSpec) DeepCopy() *HeaderSuccessResponseSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Limit) DeepCopyInto(out *Limit) { - *out = *in - if in.RouteSelectors != nil { - in, out := &in.RouteSelectors, &out.RouteSelectors - *out = make([]RouteSelector, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.When != nil { - in, out := &in.When, &out.When - *out = make([]WhenCondition, len(*in)) - copy(*out, *in) - } - if in.Counters != nil { - in, out := &in.Counters, &out.Counters - *out = make([]ContextSelector, len(*in)) - copy(*out, *in) - } - if in.Rates != nil { - in, out := &in.Rates, &out.Rates - *out = make([]Rate, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Limit. -func (in *Limit) DeepCopy() *Limit { - if in == nil { - return nil - } - out := new(Limit) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetadataSpec) DeepCopyInto(out *MetadataSpec) { *out = *in @@ -376,152 +339,6 @@ func (in *MetadataSpec) DeepCopy() *MetadataSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Rate) DeepCopyInto(out *Rate) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rate. -func (in *Rate) DeepCopy() *Rate { - if in == nil { - return nil - } - out := new(Rate) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitPolicy) DeepCopyInto(out *RateLimitPolicy) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicy. -func (in *RateLimitPolicy) DeepCopy() *RateLimitPolicy { - if in == nil { - return nil - } - out := new(RateLimitPolicy) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *RateLimitPolicy) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitPolicyCommonSpec) DeepCopyInto(out *RateLimitPolicyCommonSpec) { - *out = *in - if in.Limits != nil { - in, out := &in.Limits, &out.Limits - *out = make(map[string]Limit, len(*in)) - for key, val := range *in { - (*out)[key] = *val.DeepCopy() - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicyCommonSpec. -func (in *RateLimitPolicyCommonSpec) DeepCopy() *RateLimitPolicyCommonSpec { - if in == nil { - return nil - } - out := new(RateLimitPolicyCommonSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitPolicyList) DeepCopyInto(out *RateLimitPolicyList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]RateLimitPolicy, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicyList. -func (in *RateLimitPolicyList) DeepCopy() *RateLimitPolicyList { - if in == nil { - return nil - } - out := new(RateLimitPolicyList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *RateLimitPolicyList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitPolicySpec) DeepCopyInto(out *RateLimitPolicySpec) { - *out = *in - out.TargetRef = in.TargetRef - if in.Defaults != nil { - in, out := &in.Defaults, &out.Defaults - *out = new(RateLimitPolicyCommonSpec) - (*in).DeepCopyInto(*out) - } - if in.Overrides != nil { - in, out := &in.Overrides, &out.Overrides - *out = new(RateLimitPolicyCommonSpec) - (*in).DeepCopyInto(*out) - } - in.RateLimitPolicyCommonSpec.DeepCopyInto(&out.RateLimitPolicyCommonSpec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicySpec. -func (in *RateLimitPolicySpec) DeepCopy() *RateLimitPolicySpec { - if in == nil { - return nil - } - out := new(RateLimitPolicySpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RateLimitPolicyStatus) DeepCopyInto(out *RateLimitPolicyStatus) { - *out = *in - out.StatusMeta = in.StatusMeta - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicyStatus. -func (in *RateLimitPolicyStatus) DeepCopy() *RateLimitPolicyStatus { - if in == nil { - return nil - } - out := new(RateLimitPolicyStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResponseSpec) DeepCopyInto(out *ResponseSpec) { *out = *in @@ -592,21 +409,6 @@ func (in *SuccessResponseSpec) DeepCopy() *SuccessResponseSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *WhenCondition) DeepCopyInto(out *WhenCondition) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhenCondition. -func (in *WhenCondition) DeepCopy() *WhenCondition { - if in == nil { - return nil - } - out := new(WhenCondition) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WrappedSuccessResponseSpec) DeepCopyInto(out *WrappedSuccessResponseSpec) { *out = *in diff --git a/api/v1beta3/groupversion_info.go b/api/v1beta3/groupversion_info.go new file mode 100644 index 000000000..518ca630c --- /dev/null +++ b/api/v1beta3/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1beta3 contains API Schema definitions for the kuadrant v1beta3 API group +// +kubebuilder:object:generate=true +// +groupName=kuadrant.io +package v1beta3 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "kuadrant.io", Version: "v1beta3"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1beta2/ratelimitpolicy_types.go b/api/v1beta3/ratelimitpolicy_types.go similarity index 93% rename from api/v1beta2/ratelimitpolicy_types.go rename to api/v1beta3/ratelimitpolicy_types.go index 8dbe8e5f0..587ae0dbf 100644 --- a/api/v1beta2/ratelimitpolicy_types.go +++ b/api/v1beta3/ratelimitpolicy_types.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta2 +package v1beta3 import ( "context" @@ -87,7 +87,7 @@ type Rate struct { Unit TimeUnit `json:"unit"` } -// RouteSelector defines semantics for matching an HTTP request based on conditions +// WhenCondition defines semantics for matching an HTTP request based on conditions // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec type WhenCondition struct { // Selector defines one item from the well known selectors @@ -104,11 +104,6 @@ type WhenCondition struct { // Limit represents a complete rate limit configuration type Limit struct { - // RouteSelectors defines semantics for matching an HTTP request based on conditions - // +optional - // +kubebuilder:validation:MaxItems=15 - RouteSelectors []RouteSelector `json:"routeSelectors,omitempty"` - // When holds the list of conditions for the policy to be enforced. // Called also "soft" conditions as route selectors must also match // +optional @@ -132,7 +127,6 @@ func (l Limit) CountersAsStringList() []string { } // RateLimitPolicySpec defines the desired state of RateLimitPolicy -// +kubebuilder:validation:XValidation:rule="self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, has(self.limits[x].routeSelectors))",message="route selectors not supported when targeting a Gateway" // +kubebuilder:validation:XValidation:rule="!(has(self.defaults) && has(self.limits))",message="Implicit and explicit defaults are mutually exclusive" // +kubebuilder:validation:XValidation:rule="!(has(self.defaults) && has(self.overrides))",message="Overrides and explicit defaults are mutually exclusive" // +kubebuilder:validation:XValidation:rule="!(has(self.overrides) && has(self.limits))",message="Overrides and implicit defaults are mutually exclusive" @@ -266,18 +260,6 @@ func (r *RateLimitPolicy) GetWrappedNamespace() gatewayapiv1.Namespace { func (r *RateLimitPolicy) GetRulesHostnames() (ruleHosts []string) { ruleHosts = make([]string, 0) - for _, limit := range r.Spec.CommonSpec().Limits { - for _, routeSelector := range limit.RouteSelectors { - convertHostnamesToString := func(gwHostnames []gatewayapiv1.Hostname) []string { - hostnames := make([]string, 0, len(gwHostnames)) - for _, gwHostName := range gwHostnames { - hostnames = append(hostnames, string(gwHostName)) - } - return hostnames - } - ruleHosts = append(ruleHosts, convertHostnamesToString(routeSelector.Hostnames)...) - } - } return } diff --git a/api/v1beta2/ratelimitpolicy_types_test.go b/api/v1beta3/ratelimitpolicy_types_test.go similarity index 99% rename from api/v1beta2/ratelimitpolicy_types_test.go rename to api/v1beta3/ratelimitpolicy_types_test.go index 73605e161..4e5e28781 100644 --- a/api/v1beta2/ratelimitpolicy_types_test.go +++ b/api/v1beta3/ratelimitpolicy_types_test.go @@ -1,6 +1,6 @@ //go:build unit -package v1beta2 +package v1beta3 import ( "testing" diff --git a/api/v1beta3/topology.go b/api/v1beta3/topology.go new file mode 100644 index 000000000..aa6672910 --- /dev/null +++ b/api/v1beta3/topology.go @@ -0,0 +1,38 @@ +package v1beta3 + +// Contains of this file allow the AuthPolicy and RateLimitPolicy to adhere to the machinery.Policy interface + +import ( + "github.com/kuadrant/policy-machinery/machinery" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + RateLimitPoliciesResource = GroupVersion.WithResource("ratelimitpolicies") + RateLimitPolicyGroupKind = schema.GroupKind{Group: GroupVersion.Group, Kind: "RateLimitPolicy"} +) + +var _ machinery.Policy = &RateLimitPolicy{} + +func (r *RateLimitPolicy) GetTargetRefs() []machinery.PolicyTargetReference { + return []machinery.PolicyTargetReference{ + machinery.LocalPolicyTargetReference{ + LocalPolicyTargetReference: r.Spec.TargetRef, + PolicyNamespace: r.Namespace, + }, + } +} + +func (r *RateLimitPolicy) GetMergeStrategy() machinery.MergeStrategy { + return func(policy machinery.Policy, _ machinery.Policy) machinery.Policy { + return policy + } +} + +func (r *RateLimitPolicy) Merge(other machinery.Policy) machinery.Policy { + return other +} + +func (r *RateLimitPolicy) GetLocator() string { + return machinery.LocatorFromObject(r) +} diff --git a/api/v1beta3/zz_generated.deepcopy.go b/api/v1beta3/zz_generated.deepcopy.go new file mode 100644 index 000000000..1af900e7b --- /dev/null +++ b/api/v1beta3/zz_generated.deepcopy.go @@ -0,0 +1,217 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta3 + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Limit) DeepCopyInto(out *Limit) { + *out = *in + if in.When != nil { + in, out := &in.When, &out.When + *out = make([]WhenCondition, len(*in)) + copy(*out, *in) + } + if in.Counters != nil { + in, out := &in.Counters, &out.Counters + *out = make([]ContextSelector, len(*in)) + copy(*out, *in) + } + if in.Rates != nil { + in, out := &in.Rates, &out.Rates + *out = make([]Rate, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Limit. +func (in *Limit) DeepCopy() *Limit { + if in == nil { + return nil + } + out := new(Limit) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Rate) DeepCopyInto(out *Rate) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rate. +func (in *Rate) DeepCopy() *Rate { + if in == nil { + return nil + } + out := new(Rate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimitPolicy) DeepCopyInto(out *RateLimitPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicy. +func (in *RateLimitPolicy) DeepCopy() *RateLimitPolicy { + if in == nil { + return nil + } + out := new(RateLimitPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RateLimitPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimitPolicyCommonSpec) DeepCopyInto(out *RateLimitPolicyCommonSpec) { + *out = *in + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = make(map[string]Limit, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicyCommonSpec. +func (in *RateLimitPolicyCommonSpec) DeepCopy() *RateLimitPolicyCommonSpec { + if in == nil { + return nil + } + out := new(RateLimitPolicyCommonSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimitPolicyList) DeepCopyInto(out *RateLimitPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RateLimitPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicyList. +func (in *RateLimitPolicyList) DeepCopy() *RateLimitPolicyList { + if in == nil { + return nil + } + out := new(RateLimitPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RateLimitPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimitPolicySpec) DeepCopyInto(out *RateLimitPolicySpec) { + *out = *in + out.TargetRef = in.TargetRef + if in.Defaults != nil { + in, out := &in.Defaults, &out.Defaults + *out = new(RateLimitPolicyCommonSpec) + (*in).DeepCopyInto(*out) + } + if in.Overrides != nil { + in, out := &in.Overrides, &out.Overrides + *out = new(RateLimitPolicyCommonSpec) + (*in).DeepCopyInto(*out) + } + in.RateLimitPolicyCommonSpec.DeepCopyInto(&out.RateLimitPolicyCommonSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicySpec. +func (in *RateLimitPolicySpec) DeepCopy() *RateLimitPolicySpec { + if in == nil { + return nil + } + out := new(RateLimitPolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RateLimitPolicyStatus) DeepCopyInto(out *RateLimitPolicyStatus) { + *out = *in + out.StatusMeta = in.StatusMeta + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RateLimitPolicyStatus. +func (in *RateLimitPolicyStatus) DeepCopy() *RateLimitPolicyStatus { + if in == nil { + return nil + } + out := new(RateLimitPolicyStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WhenCondition) DeepCopyInto(out *WhenCondition) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WhenCondition. +func (in *WhenCondition) DeepCopy() *WhenCondition { + if in == nil { + return nil + } + out := new(WhenCondition) + in.DeepCopyInto(out) + return out +} diff --git a/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml b/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml index 46dd88642..25b2b124d 100644 --- a/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml +++ b/bundle/manifests/kuadrant-operator.clusterserviceversion.yaml @@ -78,7 +78,7 @@ metadata: } }, { - "apiVersion": "kuadrant.io/v1beta2", + "apiVersion": "kuadrant.io/v1beta3", "kind": "RateLimitPolicy", "metadata": { "name": "toystore" @@ -106,7 +106,7 @@ metadata: capabilities: Basic Install categories: Integration & Delivery containerImage: quay.io/kuadrant/kuadrant-operator:latest - createdAt: "2024-10-04T10:00:39Z" + createdAt: "2024-10-04T10:37:57Z" description: A Kubernetes Operator to manage the lifecycle of the Kuadrant system operators.operatorframework.io/builder: operator-sdk-v1.32.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 @@ -141,7 +141,7 @@ spec: displayName: RateLimitPolicy kind: RateLimitPolicy name: ratelimitpolicies.kuadrant.io - version: v1beta2 + version: v1beta3 - description: TLSPolicy provides tls for gateway listeners by managing the lifecycle of tls certificates displayName: TLSPolicy diff --git a/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml b/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml index dfa90662a..043dec0fa 100644 --- a/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml +++ b/bundle/manifests/kuadrant.io_ratelimitpolicies.yaml @@ -41,7 +41,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1beta2 + name: v1beta3 schema: openAPIV3Schema: description: RateLimitPolicy enables rate limiting for service workloads in @@ -121,309 +121,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -510,307 +214,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching an - HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate used - to match requests to a given\naction. Multiple match - types are ANDed together, i.e. the match will\nevaluate - to true only if all conditions are satisfied.\n\n\nFor - example, the match below will match a HTTP request - only if its path\nstarts with `/foo` AND it contains - the `version: v1` header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t - \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and start - with '/' when type one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] || self.type - == 'RegularExpression' - - message: must only contain valid characters (matching - ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP query - param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -901,309 +311,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -1275,9 +389,6 @@ spec: - targetRef type: object x-kubernetes-validations: - - message: route selectors not supported when targeting a Gateway - rule: self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, - has(self.limits[x].routeSelectors)) - message: Implicit and explicit defaults are mutually exclusive rule: '!(has(self.defaults) && has(self.limits))' - message: Overrides and explicit defaults are mutually exclusive diff --git a/charts/kuadrant-operator/templates/manifests.yaml b/charts/kuadrant-operator/templates/manifests.yaml index 5e012d2a2..2dc8b8be0 100644 --- a/charts/kuadrant-operator/templates/manifests.yaml +++ b/charts/kuadrant-operator/templates/manifests.yaml @@ -13934,7 +13934,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1beta2 + name: v1beta3 schema: openAPIV3Schema: description: RateLimitPolicy enables rate limiting for service workloads in @@ -14014,325 +14014,29 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions + when: + description: |- + When holds the list of conditions for the policy to be enforced. + Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: - hostnames: + operator: description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array - when: - description: |- - When holds the list of conditions for the policy to be enforced. - Called also "soft" conditions as route selectors must also match - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - operator: - description: |- - The binary operator to be applied to the content fetched from the selector - Possible values are: "eq" (equal to), "neq" (not equal to) - enum: - - eq - - neq - - startswith - - endswith - - incl - - excl - - matches - type: string - selector: + The binary operator to be applied to the content fetched from the selector + Possible values are: "eq" (equal to), "neq" (not equal to) + enum: + - eq + - neq + - startswith + - endswith + - incl + - excl + - matches + type: string + selector: description: |- Selector defines one item from the well known selectors TODO Document properly "Well-known selector" https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors @@ -14403,307 +14107,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching an - HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate used - to match requests to a given\naction. Multiple match - types are ANDed together, i.e. the match will\nevaluate - to true only if all conditions are satisfied.\n\n\nFor - example, the match below will match a HTTP request - only if its path\nstarts with `/foo` AND it contains - the `version: v1` header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t - \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and start - with '/' when type one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] || self.type - == 'RegularExpression' - - message: must only contain valid characters (matching - ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP query - param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -14794,309 +14204,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -15168,9 +14282,6 @@ spec: - targetRef type: object x-kubernetes-validations: - - message: route selectors not supported when targeting a Gateway - rule: self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, - has(self.limits[x].routeSelectors)) - message: Implicit and explicit defaults are mutually exclusive rule: '!(has(self.defaults) && has(self.limits))' - message: Overrides and explicit defaults are mutually exclusive diff --git a/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml b/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml index 35a23e824..88b591b84 100644 --- a/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml +++ b/config/crd/bases/kuadrant.io_ratelimitpolicies.yaml @@ -40,7 +40,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1beta2 + name: v1beta3 schema: openAPIV3Schema: description: RateLimitPolicy enables rate limiting for service workloads in @@ -120,309 +120,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -509,307 +213,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching an - HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate used - to match requests to a given\naction. Multiple match - types are ANDed together, i.e. the match will\nevaluate - to true only if all conditions are satisfied.\n\n\nFor - example, the match below will match a HTTP request - only if its path\nstarts with `/foo` AND it contains - the `version: v1` header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t - \ value: \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and start - with '/' when type one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one of - ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] || self.type - == 'RegularExpression' - - message: must only contain valid characters (matching - ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP query - param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -900,309 +310,13 @@ spec: - unit type: object type: array - routeSelectors: - description: RouteSelectors defines semantics for matching - an HTTP request based on conditions - items: - description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - properties: - hostnames: - description: |- - Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: |- - Hostname is the fully qualified domain name of a network host. This matches - the RFC 1123 definition of a hostname with 2 notable exceptions: - - - 1. IPs are not allowed. - 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard - label must appear by itself as the first label. - - - Hostname can be "precise" which is a domain name without the terminating - dot of a network host (e.g. "foo.example.com") or "wildcard", which is a - domain name prefixed with a single wildcard label (e.g. `*.example.com`). - - - Note that as per RFC1035 and RFC1123, a *label* must consist of lower case - alphanumeric characters or '-', and must start and end with an alphanumeric - character. No other punctuation is allowed. - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - type: array - matches: - description: |- - Matches define conditions used for matching the rule against incoming HTTP requests. - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate - used to match requests to a given\naction. Multiple - match types are ANDed together, i.e. the match - will\nevaluate to true only if all conditions - are satisfied.\n\n\nFor example, the match below - will match a HTTP request only if its path\nstarts - with `/foo` AND it contains the `version: v1` - header:\n\n\n```\nmatch:\n\n\n\tpath:\n\t value: - \"/foo\"\n\theaders:\n\t- name: \"version\"\n\t - \ value \"v1\"\n\n\n```" - properties: - headers: - description: |- - Headers specifies HTTP request header matchers. Multiple match values are - ANDed together, meaning, a request must match all the specified headers - to select the route. - items: - description: |- - HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request - headers. - properties: - name: - description: |- - Name is the name of the HTTP Header to be matched. Name matching MUST be - case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - - - If multiple entries specify equivalent header names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be ignored. Due to the - case-insensitivity of header names, "foo" and "Foo" are considered - equivalent. - - - When a header is repeated in an HTTP request, it is - implementation-specific behavior as to how this is represented. - Generally, proxies should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding - processing a repeated header, with special handling for "Set-Cookie". - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the header. - - - Support: Core (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression HeaderMatchType has implementation-specific - conformance, implementations can support POSIX, PCRE or any other dialects - of regular expressions. Please read the implementation's documentation to - determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: |- - Method specifies HTTP method matcher. - When specified, this route will be matched only if the request has the - specified method. - - - Support: Extended - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: - type: PathPrefix - value: / - description: |- - Path specifies a HTTP request path matcher. If this field is not - specified, a default prefix match on the "/" path is provided. - properties: - type: - default: PathPrefix - description: |- - Type specifies how to match against the path Value. - - - Support: Core (Exact, PathPrefix) - - - Support: Implementation-specific (RegularExpression) - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match - against. - maxLength: 1024 - type: string - type: object - x-kubernetes-validations: - - message: value must be an absolute path and - start with '/' when type one of ['Exact', - 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.startsWith(''/'') : true' - - message: must not contain '//' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''//'') : true' - - message: must not contain '/./' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/./'') : true' - - message: must not contain '/../' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''/../'') : true' - - message: must not contain '%2f' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2f'') : true' - - message: must not contain '%2F' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''%2F'') : true' - - message: must not contain '#' when type one - of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.contains(''#'') : true' - - message: must not end with '/..' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/..'') : true' - - message: must not end with '/.' when type - one of ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? !self.value.endsWith(''/.'') : true' - - message: type must be one of ['Exact', 'PathPrefix', - 'RegularExpression'] - rule: self.type in ['Exact','PathPrefix'] - || self.type == 'RegularExpression' - - message: must only contain valid characters - (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) - for types ['Exact', 'PathPrefix'] - rule: '(self.type in [''Exact'',''PathPrefix'']) - ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") - : true' - queryParams: - description: |- - QueryParams specifies HTTP query parameter matchers. Multiple match - values are ANDed together, meaning, a request must match all the - specified query parameters to select the route. - - - Support: Extended - items: - description: |- - HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP - query parameters. - properties: - name: - description: |- - Name is the name of the HTTP query param to be matched. This must be an - exact string match. (See - https://tools.ietf.org/html/rfc7230#section-2.7.3). - - - If multiple entries specify equivalent query param names, only the first - entry with an equivalent name MUST be considered for a match. Subsequent - entries with an equivalent query param name MUST be ignored. - - - If a query param is repeated in an HTTP request, the behavior is - purposely left undefined, since different data planes have different - capabilities. However, it is *recommended* that implementations should - match against the first value of the param if the data plane supports it, - as this behavior is expected in other load balancing contexts outside of - the Gateway API. - - - Users SHOULD NOT route traffic based on repeated query params to guard - themselves against potential differences in the implementations. - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - type: - default: Exact - description: |- - Type specifies how to match against the value of the query parameter. - - - Support: Extended (Exact) - - - Support: Implementation-specific (RegularExpression) - - - Since RegularExpression QueryParamMatchType has Implementation-specific - conformance, implementations can support POSIX, PCRE or any other - dialects of regular expressions. Please read the implementation's - documentation to determine the supported dialect. - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP - query param to be matched. - maxLength: 1024 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 15 - type: array when: description: |- When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match items: description: |- - RouteSelector defines semantics for matching an HTTP request based on conditions + WhenCondition defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteSpec properties: operator: @@ -1274,9 +388,6 @@ spec: - targetRef type: object x-kubernetes-validations: - - message: route selectors not supported when targeting a Gateway - rule: self.targetRef.kind != 'Gateway' || !has(self.limits) || !self.limits.exists(x, - has(self.limits[x].routeSelectors)) - message: Implicit and explicit defaults are mutually exclusive rule: '!(has(self.defaults) && has(self.limits))' - message: Overrides and explicit defaults are mutually exclusive diff --git a/config/manifests/bases/kuadrant-operator.clusterserviceversion.yaml b/config/manifests/bases/kuadrant-operator.clusterserviceversion.yaml index b4757b0ec..dcf47101d 100644 --- a/config/manifests/bases/kuadrant-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/kuadrant-operator.clusterserviceversion.yaml @@ -31,7 +31,7 @@ spec: displayName: RateLimitPolicy kind: RateLimitPolicy name: ratelimitpolicies.kuadrant.io - version: v1beta2 + version: v1beta3 - description: DNSHealthCheckProbe enables performing health checks against a DNS endpoint (A or CNAME record) displayName: DNSHealthCheckProbe kind: DNSHealthCheckProbe diff --git a/config/samples/kuadrant_v1beta2_ratelimitpolicy.yaml b/config/samples/kuadrant_v1beta3_ratelimitpolicy.yaml similarity index 88% rename from config/samples/kuadrant_v1beta2_ratelimitpolicy.yaml rename to config/samples/kuadrant_v1beta3_ratelimitpolicy.yaml index 6fa97658a..a6ec4819f 100644 --- a/config/samples/kuadrant_v1beta2_ratelimitpolicy.yaml +++ b/config/samples/kuadrant_v1beta3_ratelimitpolicy.yaml @@ -1,5 +1,5 @@ --- -apiVersion: kuadrant.io/v1beta2 +apiVersion: kuadrant.io/v1beta3 kind: RateLimitPolicy metadata: name: toystore diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index da3dca9b6..ea729496b 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -2,7 +2,7 @@ resources: - kuadrant_v1beta1_kuadrant.yaml - kuadrant_v1beta2_authpolicy.yaml -- kuadrant_v1beta2_ratelimitpolicy.yaml +- kuadrant_v1beta3_ratelimitpolicy.yaml - kuadrant_v1alpha1_dnspolicy.yaml - kuadrant_v1alpha1_tlspolicy.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/controllers/envoygateway_wasm_controller.go b/controllers/envoygateway_wasm_controller.go index 7ef87496c..ce2881995 100644 --- a/controllers/envoygateway_wasm_controller.go +++ b/controllers/envoygateway_wasm_controller.go @@ -16,7 +16,7 @@ import ( gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" kuadrantenvoygateway "github.com/kuadrant/kuadrant-operator/pkg/envoygateway" "github.com/kuadrant/kuadrant-operator/pkg/kuadranttools" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" @@ -55,7 +55,7 @@ func (r *EnvoyGatewayWasmReconciler) Reconcile(eventCtx context.Context, req ctr return ctrl.Result{}, err } - rawTopology, err := kuadranttools.TopologyForPolicies(ctx, r.Client(), kuadrantv1beta2.NewRateLimitPolicyType()) + rawTopology, err := kuadranttools.TopologyForPolicies(ctx, r.Client(), kuadrantv1beta3.NewRateLimitPolicyType()) if err != nil { return ctrl.Result{}, err } @@ -206,7 +206,7 @@ func (r *EnvoyGatewayWasmReconciler) SetupWithManager(mgr ctrl.Manager) error { handler.EnqueueRequestsFromMapFunc(kuadrantListEventMapper.Map), ). Watches( - &kuadrantv1beta2.RateLimitPolicy{}, + &kuadrantv1beta3.RateLimitPolicy{}, handler.EnqueueRequestsFromMapFunc(policyToKuadrantEventMapper.Map), ). Watches( diff --git a/controllers/httprouteparentrefs_eventmapper.go b/controllers/httprouteparentrefs_eventmapper.go index 410b43882..6e7b83a4e 100644 --- a/controllers/httprouteparentrefs_eventmapper.go +++ b/controllers/httprouteparentrefs_eventmapper.go @@ -10,7 +10,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - api "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" ) @@ -24,11 +25,11 @@ type HTTPRouteParentRefsEventMapper struct { } func (m *HTTPRouteParentRefsEventMapper) MapToRateLimitPolicy(obj client.Object) []reconcile.Request { - return m.mapToPolicyRequest(obj, "ratelimitpolicy", &api.RateLimitPolicyList{}) + return m.mapToPolicyRequest(obj, "ratelimitpolicy", &kuadrantv1beta3.RateLimitPolicyList{}) } func (m *HTTPRouteParentRefsEventMapper) MapToAuthPolicy(obj client.Object) []reconcile.Request { - return m.mapToPolicyRequest(obj, "authpolicy", &api.AuthPolicyList{}) + return m.mapToPolicyRequest(obj, "authpolicy", &kuadrantv1beta2.AuthPolicyList{}) } func (m *HTTPRouteParentRefsEventMapper) mapToPolicyRequest(obj client.Object, policyKind string, policyList client.ObjectList) []reconcile.Request { diff --git a/controllers/limitador_cluster_envoyfilter_controller.go b/controllers/limitador_cluster_envoyfilter_controller.go index 9ef3968d0..689221dcf 100644 --- a/controllers/limitador_cluster_envoyfilter_controller.go +++ b/controllers/limitador_cluster_envoyfilter_controller.go @@ -34,7 +34,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" kuadrantistioutils "github.com/kuadrant/kuadrant-operator/pkg/istio" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" @@ -124,7 +124,7 @@ func (r *LimitadorClusterEnvoyFilterReconciler) desiredRateLimitingClusterEnvoyF }, } - gateway := kuadrant.GatewayWrapper{Gateway: gw, Referrer: &v1beta2.RateLimitPolicy{}} + gateway := kuadrant.GatewayWrapper{Gateway: gw, Referrer: &kuadrantv1beta3.RateLimitPolicy{}} rlpRefs := gateway.PolicyRefs() logger.V(1).Info("desiredRateLimitingClusterEnvoyFilter", "rlpRefs", rlpRefs) diff --git a/controllers/limitador_status_to_rlp_gateway_event_handler.go b/controllers/limitador_status_to_rlp_gateway_event_handler.go index d7a6ed9ba..a3562a342 100644 --- a/controllers/limitador_status_to_rlp_gateway_event_handler.go +++ b/controllers/limitador_status_to_rlp_gateway_event_handler.go @@ -12,7 +12,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" "github.com/kuadrant/kuadrant-operator/pkg/library/mappers" ) @@ -71,7 +71,7 @@ func (eh limitadorStatusRLPGatewayEventHandler) IsKuadrantInstalled(ctx context. } func (eh limitadorStatusRLPGatewayEventHandler) enqueue(ctx context.Context, limitingInterface workqueue.RateLimitingInterface) { // List all RLPs as there's been an event from Limitador which may affect RLP status - rlpList := &kuadrantv1beta2.RateLimitPolicyList{} + rlpList := &kuadrantv1beta3.RateLimitPolicyList{} if err := eh.Client.List(ctx, rlpList); err != nil { eh.Logger.V(1).Error(err, "failed to list RLPs") } diff --git a/controllers/rate_limiting_istio_wasmplugin_controller.go b/controllers/rate_limiting_istio_wasmplugin_controller.go index cebd6f218..f0b84e54f 100644 --- a/controllers/rate_limiting_istio_wasmplugin_controller.go +++ b/controllers/rate_limiting_istio_wasmplugin_controller.go @@ -33,7 +33,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" kuadrantistioutils "github.com/kuadrant/kuadrant-operator/pkg/istio" "github.com/kuadrant/kuadrant-operator/pkg/kuadranttools" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" @@ -154,7 +154,7 @@ func (r *RateLimitingIstioWASMPluginReconciler) desiredRateLimitingWASMPlugin(ct } func (r *RateLimitingIstioWASMPluginReconciler) wasmPluginConfig(ctx context.Context, gw *gatewayapiv1.Gateway) (*wasm.Config, error) { - rawTopology, err := kuadranttools.TopologyFromGateway(ctx, r.Client(), gw, kuadrantv1beta2.NewRateLimitPolicyType()) + rawTopology, err := kuadranttools.TopologyFromGateway(ctx, r.Client(), gw, kuadrantv1beta3.NewRateLimitPolicyType()) if err != nil { return nil, err } @@ -216,7 +216,7 @@ func (r *RateLimitingIstioWASMPluginReconciler) SetupWithManager(mgr ctrl.Manage handler.EnqueueRequestsFromMapFunc(httpRouteToParentGatewaysEventMapper.Map), ). Watches( - &kuadrantv1beta2.RateLimitPolicy{}, + &kuadrantv1beta3.RateLimitPolicy{}, handler.EnqueueRequestsFromMapFunc(rlpToParentGatewaysEventMapper.Map), ). Complete(r) diff --git a/controllers/ratelimitpolicy_controller.go b/controllers/ratelimitpolicy_controller.go index 7ff89970a..0a390eee2 100644 --- a/controllers/ratelimitpolicy_controller.go +++ b/controllers/ratelimitpolicy_controller.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" "github.com/kuadrant/kuadrant-operator/pkg/library/mappers" @@ -66,7 +66,7 @@ func (r *RateLimitPolicyReconciler) Reconcile(eventCtx context.Context, req ctrl ctx := logr.NewContext(eventCtx, logger) // fetch the ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{} + rlp := &kuadrantv1beta3.RateLimitPolicy{} if err := r.Client().Get(ctx, req.NamespacedName, rlp); err != nil { if apierrors.IsNotFound(err) { logger.Info("no RateLimitPolicy found") @@ -153,7 +153,7 @@ func (r *RateLimitPolicyReconciler) Reconcile(eventCtx context.Context, req ctrl } // validate performs validation before proceeding with the reconcile loop, returning a common.ErrInvalid on failing validation -func (r *RateLimitPolicyReconciler) validate(rlp *kuadrantv1beta2.RateLimitPolicy, targetNetworkObject client.Object) error { +func (r *RateLimitPolicyReconciler) validate(rlp *kuadrantv1beta3.RateLimitPolicy, targetNetworkObject client.Object) error { if err := kuadrant.ValidateHierarchicalRules(rlp, targetNetworkObject); err != nil { return kuadrant.NewErrInvalid(rlp.Kind(), err) } @@ -161,7 +161,7 @@ func (r *RateLimitPolicyReconciler) validate(rlp *kuadrantv1beta2.RateLimitPolic return nil } -func (r *RateLimitPolicyReconciler) reconcileResources(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy, targetNetworkObject client.Object) error { +func (r *RateLimitPolicyReconciler) reconcileResources(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy, targetNetworkObject client.Object) error { if err := r.validate(rlp, targetNetworkObject); err != nil { return err } @@ -189,7 +189,7 @@ func (r *RateLimitPolicyReconciler) reconcileResources(ctx context.Context, rlp return nil } -func (r *RateLimitPolicyReconciler) deleteResources(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy, targetNetworkObject client.Object) error { +func (r *RateLimitPolicyReconciler) deleteResources(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy, targetNetworkObject client.Object) error { // delete based on gateway diffs gatewayDiffObj, err := reconcilers.ComputeGatewayDiffs(ctx, r.Client(), rlp, targetNetworkObject) if err != nil { @@ -212,11 +212,11 @@ func (r *RateLimitPolicyReconciler) deleteResources(ctx context.Context, rlp *ku } // Ensures only one RLP targets the network resource -func (r *RateLimitPolicyReconciler) reconcileNetworkResourceDirectBackReference(ctx context.Context, policy *kuadrantv1beta2.RateLimitPolicy, targetNetworkObject client.Object) error { +func (r *RateLimitPolicyReconciler) reconcileNetworkResourceDirectBackReference(ctx context.Context, policy *kuadrantv1beta3.RateLimitPolicy, targetNetworkObject client.Object) error { return r.TargetRefReconciler.ReconcileTargetBackReference(ctx, policy, targetNetworkObject, policy.DirectReferenceAnnotationName()) } -func (r *RateLimitPolicyReconciler) deleteNetworkResourceDirectBackReference(ctx context.Context, targetNetworkObject client.Object, policy *kuadrantv1beta2.RateLimitPolicy) error { +func (r *RateLimitPolicyReconciler) deleteNetworkResourceDirectBackReference(ctx context.Context, targetNetworkObject client.Object, policy *kuadrantv1beta3.RateLimitPolicy) error { return r.TargetRefReconciler.DeleteTargetBackReference(ctx, targetNetworkObject, policy.DirectReferenceAnnotationName()) } @@ -233,17 +233,17 @@ func (r *RateLimitPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { httpRouteEventMapper := mappers.NewHTTPRouteEventMapper(mappers.WithLogger(r.Logger().WithName("httproute.mapper")), mappers.WithClient(mgr.GetClient())) gatewayEventMapper := mappers.NewGatewayEventMapper( - kuadrantv1beta2.NewRateLimitPolicyType(), + kuadrantv1beta3.NewRateLimitPolicyType(), mappers.WithLogger(r.Logger().WithName("gateway.mapper")), mappers.WithClient(mgr.GetClient()), ) return ctrl.NewControllerManagedBy(mgr). - For(&kuadrantv1beta2.RateLimitPolicy{}). + For(&kuadrantv1beta3.RateLimitPolicy{}). Watches( &gatewayapiv1.HTTPRoute{}, handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, object client.Object) []reconcile.Request { - return httpRouteEventMapper.MapToPolicy(ctx, object, kuadrantv1beta2.NewRateLimitPolicyType()) + return httpRouteEventMapper.MapToPolicy(ctx, object, kuadrantv1beta3.NewRateLimitPolicyType()) }), ). // Currently the purpose is to generate events when rlp references change in gateways diff --git a/controllers/ratelimitpolicy_enforced_status_controller.go b/controllers/ratelimitpolicy_enforced_status_controller.go index aea1a36c8..d446262d0 100644 --- a/controllers/ratelimitpolicy_enforced_status_controller.go +++ b/controllers/ratelimitpolicy_enforced_status_controller.go @@ -8,7 +8,6 @@ import ( "github.com/go-logr/logr" "github.com/google/uuid" - limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" "github.com/samber/lo" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -23,7 +22,9 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" + + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/fieldindexers" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" @@ -82,7 +83,7 @@ func (r *RateLimitPolicyEnforcedStatusReconciler) Reconcile(eventCtx context.Con for i := range policies { policy := policies[i] rlpKey := client.ObjectKeyFromObject(policy) - rlp := policy.(*kuadrantv1beta2.RateLimitPolicy) + rlp := policy.(*kuadrantv1beta3.RateLimitPolicy) conditions := rlp.GetStatus().GetConditions() // skip policy if accepted condition is false @@ -136,7 +137,7 @@ func (r *RateLimitPolicyEnforcedStatusReconciler) Reconcile(eventCtx context.Con var gatewayParentOverridePolicies []kuadrantgatewayapi.Policy gatewayParentsWithOverrides := utils.Filter(gatewayParents, func(gatewayParent *gatewayapiv1.Gateway) bool { _, found := utils.Find(indexes.PoliciesFromGateway(gatewayParent), func(p kuadrantgatewayapi.Policy) bool { - rlp := p.(*kuadrantv1beta2.RateLimitPolicy) + rlp := p.(*kuadrantv1beta3.RateLimitPolicy) if kuadrantgatewayapi.IsTargetRefGateway(p.GetTargetRef()) && rlp != nil && rlp.Spec.Overrides != nil { gatewayParentOverridePolicies = append(gatewayParentOverridePolicies, p) return true @@ -192,7 +193,7 @@ func (r *RateLimitPolicyEnforcedStatusReconciler) buildTopology(ctx context.Cont return nil, err } - policyList := &kuadrantv1beta2.RateLimitPolicyList{} + policyList := &kuadrantv1beta3.RateLimitPolicyList{} err = r.Client().List(ctx, policyList) logger.V(1).Info("list rate limit policies", "#policies", len(policyList.Items), "err", err) if err != nil { @@ -203,12 +204,12 @@ func (r *RateLimitPolicyEnforcedStatusReconciler) buildTopology(ctx context.Cont kuadrantgatewayapi.WithAcceptedRoutesLinkedOnly(), kuadrantgatewayapi.WithGateways(utils.Map(gatewayList.Items, ptr.To[gatewayapiv1.Gateway])), kuadrantgatewayapi.WithRoutes(utils.Map(routeList.Items, ptr.To[gatewayapiv1.HTTPRoute])), - kuadrantgatewayapi.WithPolicies(utils.Map(policyList.Items, func(p kuadrantv1beta2.RateLimitPolicy) kuadrantgatewayapi.Policy { return &p })), + kuadrantgatewayapi.WithPolicies(utils.Map(policyList.Items, func(p kuadrantv1beta3.RateLimitPolicy) kuadrantgatewayapi.Policy { return &p })), kuadrantgatewayapi.WithLogger(logger), ) } -func (r *RateLimitPolicyEnforcedStatusReconciler) hasErrCondOnSubResource(ctx context.Context, p *kuadrantv1beta2.RateLimitPolicy) *metav1.Condition { +func (r *RateLimitPolicyEnforcedStatusReconciler) hasErrCondOnSubResource(ctx context.Context, p *kuadrantv1beta3.RateLimitPolicy) *metav1.Condition { logger, err := logr.FromContext(ctx) logger.WithName("hasErrCondOnSubResource") if err != nil { @@ -229,7 +230,7 @@ func (r *RateLimitPolicyEnforcedStatusReconciler) hasErrCondOnSubResource(ctx co return nil } -func (r *RateLimitPolicyEnforcedStatusReconciler) setCondition(ctx context.Context, p *kuadrantv1beta2.RateLimitPolicy, conditions *[]metav1.Condition, cond metav1.Condition) error { +func (r *RateLimitPolicyEnforcedStatusReconciler) setCondition(ctx context.Context, p *kuadrantv1beta3.RateLimitPolicy, conditions *[]metav1.Condition, cond metav1.Condition) error { logger, err := logr.FromContext(ctx) logger.WithName("setCondition") if err != nil { @@ -301,7 +302,7 @@ func (r *RateLimitPolicyEnforcedStatusReconciler) SetupWithManager(mgr ctrl.Mana handler.EnqueueRequestsFromMapFunc(httpRouteToParentGatewaysEventMapper.Map), ). Watches( - &kuadrantv1beta2.RateLimitPolicy{}, + &kuadrantv1beta3.RateLimitPolicy{}, handler.EnqueueRequestsFromMapFunc(policyToParentGatewaysEventMapper.Map), builder.WithPredicates(policyStatusChangedPredicate), ). diff --git a/controllers/ratelimitpolicy_limits.go b/controllers/ratelimitpolicy_limits.go index 2a704309f..442df9b87 100644 --- a/controllers/ratelimitpolicy_limits.go +++ b/controllers/ratelimitpolicy_limits.go @@ -13,7 +13,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" @@ -21,7 +21,7 @@ import ( "github.com/kuadrant/kuadrant-operator/pkg/rlptools" ) -func (r *RateLimitPolicyReconciler) reconcileLimits(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy) error { +func (r *RateLimitPolicyReconciler) reconcileLimits(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy) error { policies, err := r.getPolicies(ctx) if err != nil { return err @@ -33,7 +33,7 @@ func (r *RateLimitPolicyReconciler) reconcileLimits(ctx context.Context, rlp *ku return r.reconcileLimitador(ctx, rlp, topology) } -func (r *RateLimitPolicyReconciler) deleteLimits(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy) error { +func (r *RateLimitPolicyReconciler) deleteLimits(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy) error { policies, err := r.getPolicies(ctx) if err != nil { return err @@ -48,7 +48,7 @@ func (r *RateLimitPolicyReconciler) deleteLimits(ctx context.Context, rlp *kuadr return r.reconcileLimitador(ctx, rlp, topology) } -func (r *RateLimitPolicyReconciler) reconcileLimitador(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy, topology *kuadrantgatewayapi.Topology) error { +func (r *RateLimitPolicyReconciler) reconcileLimitador(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy, topology *kuadrantgatewayapi.Topology) error { logger, _ := logr.FromContext(ctx) logger = logger.WithName("reconcileLimitador") @@ -76,7 +76,7 @@ func (r *RateLimitPolicyReconciler) reconcileLimitador(ctx context.Context, rlp return nil } -func GetLimitador(ctx context.Context, k8sclient client.Client, rlp *kuadrantv1beta2.RateLimitPolicy) (*limitadorv1alpha1.Limitador, error) { +func GetLimitador(ctx context.Context, k8sclient client.Client, rlp *kuadrantv1beta3.RateLimitPolicy) (*limitadorv1alpha1.Limitador, error) { logger, _ := logr.FromContext(ctx) logger.V(1).Info("get kuadrant namespace") @@ -110,14 +110,14 @@ func GetLimitador(ctx context.Context, k8sclient client.Client, rlp *kuadrantv1b func (r *RateLimitPolicyReconciler) getPolicies(ctx context.Context) ([]kuadrantgatewayapi.Policy, error) { logger, _ := logr.FromContext(ctx) - rlpList := &kuadrantv1beta2.RateLimitPolicyList{} + rlpList := &kuadrantv1beta3.RateLimitPolicyList{} err := r.Client().List(ctx, rlpList) logger.V(1).Info("topology: list rate limit policies", "#RLPS", len(rlpList.Items), "err", err) if err != nil { return nil, err } - policies := utils.Map(rlpList.Items, func(p kuadrantv1beta2.RateLimitPolicy) kuadrantgatewayapi.Policy { return &p }) + policies := utils.Map(rlpList.Items, func(p kuadrantv1beta3.RateLimitPolicy) kuadrantgatewayapi.Policy { return &p }) return policies, nil } @@ -189,7 +189,7 @@ func (r *RateLimitPolicyReconciler) buildRateLimitIndex(ctx context.Context, top logger.Error(fmt.Errorf("unexpected duplicate rate limit policy key found"), "failed do add rate limit policy to index", "RateLimitPolicy", rlpKey.String(), "Gateway", gatewayKey) continue } - rlp := policy.(*kuadrantv1beta2.RateLimitPolicy) + rlp := policy.(*kuadrantv1beta3.RateLimitPolicy) rateLimitIndex.Set(key, rlptools.LimitadorRateLimitsFromRLP(rlp)) } } diff --git a/controllers/ratelimitpolicy_status.go b/controllers/ratelimitpolicy_status.go index 980906a8e..6ece9605b 100644 --- a/controllers/ratelimitpolicy_status.go +++ b/controllers/ratelimitpolicy_status.go @@ -12,18 +12,18 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" ) -func (r *RateLimitPolicyReconciler) reconcileStatus(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy, specErr error) (ctrl.Result, error) { +func (r *RateLimitPolicyReconciler) reconcileStatus(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy, specErr error) (ctrl.Result, error) { logger, _ := logr.FromContext(ctx) newStatus := r.calculateStatus(rlp, specErr) if err := r.ReconcileResourceStatus( ctx, client.ObjectKeyFromObject(rlp), - &kuadrantv1beta2.RateLimitPolicy{}, - kuadrantv1beta2.RateLimitPolicyStatusMutator(newStatus, logger), + &kuadrantv1beta3.RateLimitPolicy{}, + kuadrantv1beta3.RateLimitPolicyStatusMutator(newStatus, logger), ); err != nil { // Ignore conflicts, resource might just be outdated. if apierrors.IsConflict(err) { @@ -37,8 +37,8 @@ func (r *RateLimitPolicyReconciler) reconcileStatus(ctx context.Context, rlp *ku return ctrl.Result{}, nil } -func (r *RateLimitPolicyReconciler) calculateStatus(rlp *kuadrantv1beta2.RateLimitPolicy, specErr error) *kuadrantv1beta2.RateLimitPolicyStatus { - newStatus := &kuadrantv1beta2.RateLimitPolicyStatus{ +func (r *RateLimitPolicyReconciler) calculateStatus(rlp *kuadrantv1beta3.RateLimitPolicy, specErr error) *kuadrantv1beta3.RateLimitPolicyStatus { + newStatus := &kuadrantv1beta3.RateLimitPolicyStatus{ // Copy initial conditions. Otherwise, status will always be updated Conditions: slices.Clone(rlp.Status.Conditions), } diff --git a/controllers/ratelimitpolicy_status_test.go b/controllers/ratelimitpolicy_status_test.go index effc0c93b..d1ebe7ea9 100644 --- a/controllers/ratelimitpolicy_status_test.go +++ b/controllers/ratelimitpolicy_status_test.go @@ -10,25 +10,25 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" ) func TestRateLimitPolicyReconciler_calculateStatus(t *testing.T) { type args struct { - rlp *kuadrantv1beta2.RateLimitPolicy + rlp *kuadrantv1beta3.RateLimitPolicy specErr error } tests := []struct { name string args args - want *kuadrantv1beta2.RateLimitPolicyStatus + want *kuadrantv1beta3.RateLimitPolicyStatus }{ { name: "Enforced status block removed if policy not Accepted. (Regression test)", // https://github.com/Kuadrant/kuadrant-operator/issues/588 args: args{ - rlp: &kuadrantv1beta2.RateLimitPolicy{ - Status: kuadrantv1beta2.RateLimitPolicyStatus{ + rlp: &kuadrantv1beta3.RateLimitPolicy{ + Status: kuadrantv1beta3.RateLimitPolicyStatus{ Conditions: []metav1.Condition{ { Message: "not accepted", @@ -47,7 +47,7 @@ func TestRateLimitPolicyReconciler_calculateStatus(t *testing.T) { }, specErr: kuadrant.NewErrInvalid("RateLimitPolicy", errors.New("policy Error")), }, - want: &kuadrantv1beta2.RateLimitPolicyStatus{ + want: &kuadrantv1beta3.RateLimitPolicyStatus{ Conditions: []metav1.Condition{ { Message: "RateLimitPolicy target is invalid: policy Error", diff --git a/controllers/state_of_the_world.go b/controllers/state_of_the_world.go index ddc6c7517..ad38d7d98 100644 --- a/controllers/state_of_the_world.go +++ b/controllers/state_of_the_world.go @@ -23,6 +23,7 @@ import ( kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/envoygateway" "github.com/kuadrant/kuadrant-operator/pkg/istio" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" @@ -45,7 +46,7 @@ func NewPolicyMachineryController(manager ctrlruntime.Manager, client *dynamic.D controller.WithRunnable("dnspolicy watcher", controller.Watch(&kuadrantv1alpha1.DNSPolicy{}, kuadrantv1alpha1.DNSPoliciesResource, metav1.NamespaceAll)), controller.WithRunnable("tlspolicy watcher", controller.Watch(&kuadrantv1alpha1.TLSPolicy{}, kuadrantv1alpha1.TLSPoliciesResource, metav1.NamespaceAll)), controller.WithRunnable("authpolicy watcher", controller.Watch(&kuadrantv1beta2.AuthPolicy{}, kuadrantv1beta2.AuthPoliciesResource, metav1.NamespaceAll)), - controller.WithRunnable("ratelimitpolicy watcher", controller.Watch(&kuadrantv1beta2.RateLimitPolicy{}, kuadrantv1beta2.RateLimitPoliciesResource, metav1.NamespaceAll)), + controller.WithRunnable("ratelimitpolicy watcher", controller.Watch(&kuadrantv1beta3.RateLimitPolicy{}, kuadrantv1beta3.RateLimitPoliciesResource, metav1.NamespaceAll)), controller.WithRunnable("topology configmap watcher", controller.Watch(&corev1.ConfigMap{}, controller.ConfigMapsResource, operatorNamespace, controller.FilterResourcesByLabel[*corev1.ConfigMap](fmt.Sprintf("%s=true", kuadrant.TopologyLabel)))), controller.WithRunnable("limitador watcher", controller.Watch(&limitadorv1alpha1.Limitador{}, kuadrantv1beta1.LimitadorsResource, metav1.NamespaceAll)), controller.WithRunnable("authorino watcher", controller.Watch(&authorinov1beta1.Authorino{}, kuadrantv1beta1.AuthorinosResource, metav1.NamespaceAll)), @@ -53,7 +54,7 @@ func NewPolicyMachineryController(manager ctrlruntime.Manager, client *dynamic.D kuadrantv1alpha1.DNSPolicyGroupKind, kuadrantv1alpha1.TLSPolicyGroupKind, kuadrantv1beta2.AuthPolicyGroupKind, - kuadrantv1beta2.RateLimitPolicyGroupKind, + kuadrantv1beta3.RateLimitPolicyGroupKind, ), controller.WithObjectKinds( kuadrantv1beta1.KuadrantGroupKind, diff --git a/controllers/target_status_controller.go b/controllers/target_status_controller.go index 4e65693c9..799a73131 100644 --- a/controllers/target_status_controller.go +++ b/controllers/target_status_controller.go @@ -40,6 +40,7 @@ import ( kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/fieldindexers" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" @@ -83,7 +84,7 @@ func (r *TargetStatusReconciler) reconcileResources(ctx context.Context, gw *gat &kuadrantv1beta2.AuthPolicy{TypeMeta: ctrl.TypeMeta{Kind: "AuthPolicy"}}: &kuadrantv1beta2.AuthPolicyList{}, &kuadrantv1alpha1.DNSPolicy{TypeMeta: ctrl.TypeMeta{Kind: "DNSPolicy"}}: &kuadrantv1alpha1.DNSPolicyList{}, &kuadrantv1alpha1.TLSPolicy{TypeMeta: ctrl.TypeMeta{Kind: "TLSPolicy"}}: &kuadrantv1alpha1.TLSPolicyList{}, - &kuadrantv1beta2.RateLimitPolicy{TypeMeta: ctrl.TypeMeta{Kind: "RateLimitPolicy"}}: &kuadrantv1beta2.RateLimitPolicyList{}, + &kuadrantv1beta3.RateLimitPolicy{TypeMeta: ctrl.TypeMeta{Kind: "RateLimitPolicy"}}: &kuadrantv1beta3.RateLimitPolicyList{}, } var errs error @@ -387,7 +388,7 @@ func (r *TargetStatusReconciler) SetupWithManager(mgr ctrl.Manager) error { builder.WithPredicates(policyStatusChangedPredicate), ). Watches( - &kuadrantv1beta2.RateLimitPolicy{}, + &kuadrantv1beta3.RateLimitPolicy{}, handler.EnqueueRequestsFromMapFunc(policyToParentGatewaysEventMapper.Map), builder.WithPredicates(policyStatusChangedPredicate), ). diff --git a/controllers/test_common.go b/controllers/test_common.go index 41bab5e64..494d5e344 100644 --- a/controllers/test_common.go +++ b/controllers/test_common.go @@ -53,6 +53,7 @@ import ( kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/fieldindexers" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" "github.com/kuadrant/kuadrant-operator/pkg/library/reconcilers" @@ -293,6 +294,7 @@ func BootstrapScheme() *runtime.Scheme { kuadrantv1alpha1.AddToScheme, kuadrantv1beta1.AddToScheme, kuadrantv1beta2.AddToScheme, + kuadrantv1beta3.AddToScheme, gatewayapiv1.Install, gatewayapiv1beta1.Install, authorinoopapi.AddToScheme, diff --git a/doc/rate-limiting.md b/doc/rate-limiting.md index 8398a982b..40dc06afc 100644 --- a/doc/rate-limiting.md +++ b/doc/rate-limiting.md @@ -30,7 +30,6 @@ The `RateLimitPolicy` spec includes, basically, two parts: Each limit definition includes: * A set of rate limits (`spec.limits..rates[]`) * (Optional) A set of dynamic counter qualifiers (`spec.limits..counters[]`) -* (Optional) A set of route selectors, to further qualify the specific routing rules when to activate the limit (`spec.limits..routeSelectors[]`) * (Optional) A set of additional dynamic conditions to activate the limit (`spec.limits..when[]`) The limit definitions (`limits`) can be declared at the top-level level of the spec (with the semantics of _defaults_) or alternatively within explicit `defaults` or `overrides` blocks. @@ -73,12 +72,6 @@ spec: # Check out Kuadrant RFC 0002 (https://github.com/Kuadrant/architecture/blob/main/rfcs/0002-well-known-attributes.md) to learn more about the Well-known Attributes that can be used in this field. counters: […] - # Further qualification of the scpecific HTTPRouteRules within the targeted HTTPRoute that should trigger the limit. - # Each element contains a HTTPRouteMatch object that will be used to select HTTPRouteRules that include at least one identical HTTPRouteMatch. - # The HTTPRouteMatch part does not have to be fully identical, but the what's stated in the selector must be identically stated in the HTTPRouteRule. - # Do not use it on RateLimitPolicies that target a Gateway. - routeSelectors: […] - # Additional dynamic conditions to trigger the limit. # Use it for filtering attributes not supported by HTTPRouteRule or with RateLimitPolicies that target a Gateway. # Check out Kuadrant RFC 0002 (https://github.com/Kuadrant/architecture/blob/main/rfcs/0002-well-known-attributes.md) to learn more about the Well-known Attributes that can be used in this field. @@ -103,8 +96,6 @@ spec: When a RateLimitPolicy targets a HTTPRoute, the policy is enforced to all traffic routed according to the rules and hostnames specified in the HTTPRoute, across all Gateways referenced in the `spec.parentRefs` field of the HTTPRoute. -The targeted HTTPRoute's rules and/or hostnames to which the policy must be enforced can be filtered to specific subsets, by specifying the [`routeSelectors`](reference/route-selectors.md#the-routeselectors-field) field of the limit definition. - Target a HTTPRoute by setting the `spec.targetRef` field of the RateLimitPolicy as follows: ```yaml @@ -195,7 +186,6 @@ Expected behavior: ### Limit definition A limit will be activated whenever a request comes in and the request matches: -- any of the route rules selected by the limit (via [`routeSelectors`](reference/route-selectors.md#the-routeselectors-field) or implicit "catch-all" selector), and - all of the `when` conditions specified in the limit. A limit can define: @@ -225,19 +215,20 @@ spec: unit: minute counters: - auth.identity.username - routeSelectors: - hostnames: - - api.toystore.com + when: + - selector: request.host + operator: eq + value: "api.toystore.com" "toystore-admin-unverified-users": rates: - limit: 250 duration: 1 unit: second - routeSelectors: - hostnames: - - admin.toystore.com when: + - selector: request.host + operator: eq + value: "admin.toystore.com" - selector: auth.identity.email_verified operator: eq value: "false" @@ -249,15 +240,9 @@ spec: | `admin.toystore.com` | 250rps | | `other.toystore.com` | 5000rps | -### Route selectors - -Route selectors allow targeting sections of a HTTPRoute, by specifying sets of HTTPRouteMatches and/or hostnames that make the policy controller look up within the HTTPRoute spec for compatible declarations, and select the corresponding HTTPRouteRules and hostnames, to then build conditions that activate the policy or policy rule. - -Check out [Route selectors](reference/route-selectors.md) for a full description, semantics and API reference. - #### `when` conditions -`when` conditions can be used to scope a limit (i.e. to filter the traffic to which a limit definition applies) without any coupling to the underlying network topology, i.e. without making direct references to HTTPRouteRules via [`routeSelectors`](reference/route-selectors.md#the-routeselectors-field). +`when` conditions can be used to scope a limit (i.e. to filter the traffic to which a limit definition applies) without any coupling to the underlying network topology, i.e. without making direct references to HTTPRouteRules. Use `when` conditions to conditionally activate limits based on attributes that cannot be expressed in the HTTPRoutes' `spec.hostnames` and `spec.rules.matches` fields, or in general in RateLimitPolicies that target a Gateway. diff --git a/doc/reference/ratelimitpolicy.md b/doc/reference/ratelimitpolicy.md index 6a6c98744..3b31c0d4c 100644 --- a/doc/reference/ratelimitpolicy.md +++ b/doc/reference/ratelimitpolicy.md @@ -37,7 +37,6 @@ |------------------|-----------------------------------------------------|:------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `rates` | [][RateLimit](#ratelimit) | No | List of rate limits associated with the limit definition | | `counters` | []String | No | List of rate limit counter qualifiers. Items must be a valid [Well-known attribute](https://github.com/Kuadrant/architecture/blob/main/rfcs/0002-well-known-attributes.md). Each distinct value resolved in the data plane starts a separate counter for each rate limit. | -| `routeSelectors` | [][RouteSelector](route-selectors.md#routeselector) | No | List of selectors of HTTPRouteRules whose matching rules activate the limit. At least one HTTPRouteRule must be selected to activate the limit. If omitted, all HTTPRouteRules of the targeted HTTPRoute activate the limit. Do not use it in policies targeting a Gateway. | | `when` | [][WhenCondition](#whencondition) | No | List of additional dynamic conditions (expressions) to activate the limit. All expression must evaluate to true for the limit to be applied. Use it for filtering attributes that cannot be expressed in the targeted HTTPRoute's `spec.hostnames` and `spec.rules.matches` fields, or when targeting a Gateway. | #### RateLimit diff --git a/doc/user-guides/simple-rl-for-app-developers.md b/doc/user-guides/simple-rl-for-app-developers.md index a978320fb..aaa7e862a 100644 --- a/doc/user-guides/simple-rl-for-app-developers.md +++ b/doc/user-guides/simple-rl-for-app-developers.md @@ -136,12 +136,10 @@ spec: - limit: 5 duration: 10 unit: second - routeSelectors: - - matches: # selects the 2nd HTTPRouteRule of the targeted route - - method: POST - path: - type: Exact - value: "/toys" + when: + - selector: request.method + operator: eq + value: "POST" EOF ``` diff --git a/examples/toystore/ratelimitpolicy_httproute.yaml b/examples/toystore/ratelimitpolicy_httproute.yaml index de10f7143..c11ac81f6 100644 --- a/examples/toystore/ratelimitpolicy_httproute.yaml +++ b/examples/toystore/ratelimitpolicy_httproute.yaml @@ -19,12 +19,6 @@ spec: - limit: 5 duration: 30 unit: second - routeSelectors: - - matches: - - path: - type: Exact - value: "/toy" - method: GET "admin-post-or-delete-toy-per-user": rates: diff --git a/main.go b/main.go index 347f02985..05f5ba7cc 100644 --- a/main.go +++ b/main.go @@ -52,6 +52,7 @@ import ( kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/controllers" "github.com/kuadrant/kuadrant-operator/pkg/library/fieldindexers" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" @@ -88,6 +89,7 @@ func init() { utilruntime.Must(kuadrantv1alpha1.AddToScheme(scheme)) utilruntime.Must(kuadrantv1beta1.AddToScheme(scheme)) utilruntime.Must(kuadrantv1beta2.AddToScheme(scheme)) + utilruntime.Must(kuadrantv1beta3.AddToScheme(scheme)) utilruntime.Must(kuadrantdnsv1alpha1.AddToScheme(scheme)) utilruntime.Must(certmanv1.AddToScheme(scheme)) utilruntime.Must(egv1alpha1.AddToScheme(scheme)) diff --git a/pkg/library/mappers/gateway_test.go b/pkg/library/mappers/gateway_test.go index 7017e549b..6de310348 100644 --- a/pkg/library/mappers/gateway_test.go +++ b/pkg/library/mappers/gateway_test.go @@ -16,7 +16,7 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/fieldindexers" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" @@ -36,7 +36,7 @@ func TestNewGatewayEventMapper(t *testing.T) { t.Fatal(err) } - err = kuadrantv1beta2.AddToScheme(testScheme) + err = kuadrantv1beta3.AddToScheme(testScheme) if err != nil { t.Fatal(err) } @@ -63,7 +63,7 @@ func TestNewGatewayEventMapper(t *testing.T) { t.Run("not gateway related event", func(subT *testing.T) { objs := []runtime.Object{} cl := clientBuilder(objs) - em := NewGatewayEventMapper(kuadrantv1beta2.NewRateLimitPolicyType(), WithClient(cl), WithLogger(log.NewLogger())) + em := NewGatewayEventMapper(kuadrantv1beta3.NewRateLimitPolicyType(), WithClient(cl), WithLogger(log.NewLogger())) requests := em.Map(ctx, &gatewayapiv1.HTTPRoute{}) assert.DeepEqual(subT, []reconcile.Request{}, requests) }) @@ -71,7 +71,7 @@ func TestNewGatewayEventMapper(t *testing.T) { t.Run("gateway related event - no policies - no requests", func(subT *testing.T) { objs := []runtime.Object{} cl := clientBuilder(objs) - em := NewGatewayEventMapper(kuadrantv1beta2.NewRateLimitPolicyType(), WithClient(cl), WithLogger(log.NewLogger())) + em := NewGatewayEventMapper(kuadrantv1beta3.NewRateLimitPolicyType(), WithClient(cl), WithLogger(log.NewLogger())) requests := em.Map(ctx, &gatewayapiv1.Gateway{}) assert.DeepEqual(subT, []reconcile.Request{}, requests) }) @@ -91,7 +91,7 @@ func TestNewGatewayEventMapper(t *testing.T) { }) objs := []runtime.Object{gw, route, pGw, pRoute} cl := clientBuilder(objs) - em := NewGatewayEventMapper(kuadrantv1beta2.NewRateLimitPolicyType(), WithClient(cl), WithLogger(log.NewLogger())) + em := NewGatewayEventMapper(kuadrantv1beta3.NewRateLimitPolicyType(), WithClient(cl), WithLogger(log.NewLogger())) requests := em.Map(ctx, gw) assert.Equal(subT, len(requests), 2) assert.Assert(subT, utils.Index(requests, func(r reconcile.Request) bool { diff --git a/pkg/library/mappers/utils_test.go b/pkg/library/mappers/utils_test.go index eedf7a204..a7fbb0b11 100644 --- a/pkg/library/mappers/utils_test.go +++ b/pkg/library/mappers/utils_test.go @@ -7,7 +7,7 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" ) func gatewayFactory(ns, name string) *gatewayapiv1.Gateway { @@ -30,10 +30,10 @@ func routeFactory(ns, name string, parentRef gatewayapiv1.ParentReference) *gate } } -func policyFactory(ns, name string, targetRef gatewayapiv1alpha2.LocalPolicyTargetReference) *kuadrantv1beta2.RateLimitPolicy { - return &kuadrantv1beta2.RateLimitPolicy{ - TypeMeta: metav1.TypeMeta{Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String()}, +func policyFactory(ns, name string, targetRef gatewayapiv1alpha2.LocalPolicyTargetReference) *kuadrantv1beta3.RateLimitPolicy { + return &kuadrantv1beta3.RateLimitPolicy{ + TypeMeta: metav1.TypeMeta{Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String()}, ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{TargetRef: targetRef}, + Spec: kuadrantv1beta3.RateLimitPolicySpec{TargetRef: targetRef}, } } diff --git a/pkg/rlptools/overrides.go b/pkg/rlptools/overrides.go index 5dc47fb3a..f361ef16f 100644 --- a/pkg/rlptools/overrides.go +++ b/pkg/rlptools/overrides.go @@ -7,7 +7,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) @@ -22,9 +22,9 @@ func ApplyOverrides(topology *kuadrantgatewayapi.Topology, gateway *gatewayapiv1 return topology, nil } - overridePolicies := lo.FilterMap(gatewayNode.AttachedPolicies(), func(pNode kuadrantgatewayapi.PolicyNode, _ int) (*kuadrantv1beta2.RateLimitPolicy, bool) { + overridePolicies := lo.FilterMap(gatewayNode.AttachedPolicies(), func(pNode kuadrantgatewayapi.PolicyNode, _ int) (*kuadrantv1beta3.RateLimitPolicy, bool) { policy := pNode.Policy - rlp, ok := policy.(*kuadrantv1beta2.RateLimitPolicy) + rlp, ok := policy.(*kuadrantv1beta3.RateLimitPolicy) if !ok || rlp.Spec.Overrides == nil { return nil, false } @@ -35,7 +35,7 @@ func ApplyOverrides(topology *kuadrantgatewayapi.Topology, gateway *gatewayapiv1 return topology, nil } - overriddenPolicies := lo.Map(overridePolicies, func(p *kuadrantv1beta2.RateLimitPolicy, _ int) kuadrantgatewayapi.Policy { return p }) + overriddenPolicies := lo.Map(overridePolicies, func(p *kuadrantv1beta3.RateLimitPolicy, _ int) kuadrantgatewayapi.Policy { return p }) for _, route := range topology.Routes() { if !slices.Contains(kuadrantgatewayapi.GetRouteAcceptedGatewayParentKeys(route.HTTPRoute), client.ObjectKeyFromObject(gateway)) { @@ -45,7 +45,7 @@ func ApplyOverrides(topology *kuadrantgatewayapi.Topology, gateway *gatewayapiv1 } for _, policy := range route.AttachedPolicies() { - overriddenPolicy := policy.DeepCopyObject().(*kuadrantv1beta2.RateLimitPolicy) + overriddenPolicy := policy.DeepCopyObject().(*kuadrantv1beta3.RateLimitPolicy) overriddenPolicy.Spec.CommonSpec().Limits = overridePolicies[0].Spec.Overrides.Limits overriddenPolicies = append(overriddenPolicies, overriddenPolicy) } diff --git a/pkg/rlptools/utils.go b/pkg/rlptools/utils.go index a8ca94d92..f5472e695 100644 --- a/pkg/rlptools/utils.go +++ b/pkg/rlptools/utils.go @@ -6,25 +6,25 @@ import ( limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" "sigs.k8s.io/controller-runtime/pkg/client" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" "github.com/kuadrant/kuadrant-operator/pkg/rlptools/wasm" ) -func LimitsNameFromRLP(rlp *kuadrantv1beta2.RateLimitPolicy) string { +func LimitsNameFromRLP(rlp *kuadrantv1beta3.RateLimitPolicy) string { return wasm.LimitsNamespaceFromRLP(rlp) } -var timeUnitMap = map[kuadrantv1beta2.TimeUnit]int{ - kuadrantv1beta2.TimeUnit("second"): 1, - kuadrantv1beta2.TimeUnit("minute"): 60, - kuadrantv1beta2.TimeUnit("hour"): 60 * 60, - kuadrantv1beta2.TimeUnit("day"): 60 * 60 * 24, +var timeUnitMap = map[kuadrantv1beta3.TimeUnit]int{ + kuadrantv1beta3.TimeUnit("second"): 1, + kuadrantv1beta3.TimeUnit("minute"): 60, + kuadrantv1beta3.TimeUnit("hour"): 60 * 60, + kuadrantv1beta3.TimeUnit("day"): 60 * 60 * 24, } // LimitadorRateLimitsFromRLP converts rate limits from a Kuadrant RateLimitPolicy into a list of Limitador rate limit // objects -func LimitadorRateLimitsFromRLP(rlp *kuadrantv1beta2.RateLimitPolicy) []limitadorv1alpha1.RateLimit { +func LimitadorRateLimitsFromRLP(rlp *kuadrantv1beta3.RateLimitPolicy) []limitadorv1alpha1.RateLimit { limitsNamespace := wasm.LimitsNamespaceFromRLP(rlp) rlpKey := client.ObjectKeyFromObject(rlp) @@ -48,7 +48,7 @@ func LimitadorRateLimitsFromRLP(rlp *kuadrantv1beta2.RateLimitPolicy) []limitado // rateToSeconds converts from RLP Rate API (limit, duration and unit) // to Limitador's Limit format (maxValue, Seconds) -func rateToSeconds(rate kuadrantv1beta2.Rate) (maxValue int, seconds int) { +func rateToSeconds(rate kuadrantv1beta3.Rate) (maxValue int, seconds int) { maxValue = rate.Limit seconds = 0 diff --git a/pkg/rlptools/utils_test.go b/pkg/rlptools/utils_test.go index 3bb10fbbb..8d414847a 100644 --- a/pkg/rlptools/utils_test.go +++ b/pkg/rlptools/utils_test.go @@ -6,28 +6,29 @@ import ( "reflect" "testing" - limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" + + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" ) -func testRLP_1Limit_1Rate(ns, name string) *kuadrantv1beta2.RateLimitPolicy { - return &kuadrantv1beta2.RateLimitPolicy{ +func testRLP_1Limit_1Rate(ns, name string) *kuadrantv1beta3.RateLimitPolicy { + return &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: ns, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 5, Duration: 10, @@ -41,21 +42,21 @@ func testRLP_1Limit_1Rate(ns, name string) *kuadrantv1beta2.RateLimitPolicy { } } -func testRLP_2Limits_1Rate(ns, name string) *kuadrantv1beta2.RateLimitPolicy { - return &kuadrantv1beta2.RateLimitPolicy{ +func testRLP_2Limits_1Rate(ns, name string) *kuadrantv1beta3.RateLimitPolicy { + return &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: ns, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 5, Duration: 10, @@ -64,7 +65,7 @@ func testRLP_2Limits_1Rate(ns, name string) *kuadrantv1beta2.RateLimitPolicy { }, }, "l2": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 3, Duration: 1, @@ -78,21 +79,21 @@ func testRLP_2Limits_1Rate(ns, name string) *kuadrantv1beta2.RateLimitPolicy { } } -func testRLP_1Limit_2Rates(ns, name string) *kuadrantv1beta2.RateLimitPolicy { - return &kuadrantv1beta2.RateLimitPolicy{ +func testRLP_1Limit_2Rates(ns, name string) *kuadrantv1beta3.RateLimitPolicy { + return &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: ns, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 5, Duration: 10, @@ -111,24 +112,24 @@ func testRLP_1Limit_2Rates(ns, name string) *kuadrantv1beta2.RateLimitPolicy { } } -func testRLP_1Limit_1Rate_1Counter(ns, name string) *kuadrantv1beta2.RateLimitPolicy { - return &kuadrantv1beta2.RateLimitPolicy{ +func testRLP_1Limit_1Rate_1Counter(ns, name string) *kuadrantv1beta3.RateLimitPolicy { + return &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: ns, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Counters: []kuadrantv1beta2.ContextSelector{ + Counters: []kuadrantv1beta3.ContextSelector{ "request.path", }, - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 5, Duration: 10, @@ -145,7 +146,7 @@ func testRLP_1Limit_1Rate_1Counter(ns, name string) *kuadrantv1beta2.RateLimitPo func TestLimitadorRateLimitsFromRLP(t *testing.T) { testCases := []struct { name string - rlp *kuadrantv1beta2.RateLimitPolicy + rlp *kuadrantv1beta3.RateLimitPolicy expected []limitadorv1alpha1.RateLimit }{ { @@ -244,78 +245,78 @@ func TestLimitadorRateLimitsFromRLP(t *testing.T) { func TestConvertRateIntoSeconds(t *testing.T) { testCases := []struct { name string - rate kuadrantv1beta2.Rate + rate kuadrantv1beta3.Rate expectedMaxValue int expectedSeconds int }{ { name: "seconds", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("second"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("second"), }, expectedMaxValue: 5, expectedSeconds: 2, }, { name: "minutes", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("minute"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("minute"), }, expectedMaxValue: 5, expectedSeconds: 2 * 60, }, { name: "hours", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("hour"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("hour"), }, expectedMaxValue: 5, expectedSeconds: 2 * 60 * 60, }, { name: "day", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("day"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("day"), }, expectedMaxValue: 5, expectedSeconds: 2 * 60 * 60 * 24, }, { name: "negative limit", - rate: kuadrantv1beta2.Rate{ - Limit: -5, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("second"), + rate: kuadrantv1beta3.Rate{ + Limit: -5, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("second"), }, expectedMaxValue: 0, expectedSeconds: 2, }, { name: "negative duration", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: -2, Unit: kuadrantv1beta2.TimeUnit("second"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: -2, Unit: kuadrantv1beta3.TimeUnit("second"), }, expectedMaxValue: 5, expectedSeconds: 0, }, { name: "limit is 0", - rate: kuadrantv1beta2.Rate{ - Limit: 0, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("second"), + rate: kuadrantv1beta3.Rate{ + Limit: 0, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("second"), }, expectedMaxValue: 0, expectedSeconds: 2, }, { name: "rate is 0", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: 0, Unit: kuadrantv1beta2.TimeUnit("second"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: 0, Unit: kuadrantv1beta3.TimeUnit("second"), }, expectedMaxValue: 5, expectedSeconds: 0, }, { name: "unexpected time unit", - rate: kuadrantv1beta2.Rate{ - Limit: 5, Duration: 2, Unit: kuadrantv1beta2.TimeUnit("unknown"), + rate: kuadrantv1beta3.Rate{ + Limit: 5, Duration: 2, Unit: kuadrantv1beta3.TimeUnit("unknown"), }, expectedMaxValue: 5, expectedSeconds: 0, diff --git a/pkg/rlptools/wasm/types.go b/pkg/rlptools/wasm/types.go index fd716dd4c..b3a1bcf87 100644 --- a/pkg/rlptools/wasm/types.go +++ b/pkg/rlptools/wasm/types.go @@ -9,21 +9,21 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" ) var ( PathMatchTypeMap = map[gatewayapiv1.PathMatchType]PatternOperator{ - gatewayapiv1.PathMatchExact: PatternOperator(kuadrantv1beta2.EqualOperator), - gatewayapiv1.PathMatchPathPrefix: PatternOperator(kuadrantv1beta2.StartsWithOperator), - gatewayapiv1.PathMatchRegularExpression: PatternOperator(kuadrantv1beta2.MatchesOperator), + gatewayapiv1.PathMatchExact: PatternOperator(kuadrantv1beta3.EqualOperator), + gatewayapiv1.PathMatchPathPrefix: PatternOperator(kuadrantv1beta3.StartsWithOperator), + gatewayapiv1.PathMatchRegularExpression: PatternOperator(kuadrantv1beta3.MatchesOperator), } ) type SelectorSpec struct { // Selector of an attribute from the contextual properties provided by kuadrant // during request and connection processing - Selector kuadrantv1beta2.ContextSelector `json:"selector"` + Selector kuadrantv1beta3.ContextSelector `json:"selector"` // If not set it defaults to `selector` field value as the descriptor key. // +optional @@ -85,12 +85,12 @@ func (d *DataType) MarshalJSON() ([]byte, error) { } } -type PatternOperator kuadrantv1beta2.WhenConditionOperator +type PatternOperator kuadrantv1beta3.WhenConditionOperator type PatternExpression struct { // Selector of an attribute from the contextual properties provided by kuadrant // during request and connection processing - Selector kuadrantv1beta2.ContextSelector `json:"selector"` + Selector kuadrantv1beta3.ContextSelector `json:"selector"` // The binary operator to be applied to the content fetched from context, for comparison with "value". // Possible values are: "eq" (equal to), "neq" (not equal to), "incl" (includes; for arrays), "excl" (excludes; for arrays), "matches" (regex) diff --git a/pkg/rlptools/wasm/types_test.go b/pkg/rlptools/wasm/types_test.go index a22c8f467..0a589734c 100644 --- a/pkg/rlptools/wasm/types_test.go +++ b/pkg/rlptools/wasm/types_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "sigs.k8s.io/yaml" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" ) @@ -184,7 +184,7 @@ func testBasicConfigExample() *Config { AllOf: []PatternExpression{ { Selector: "request.host", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), Value: "cars.toystore.com", }, }, diff --git a/pkg/rlptools/wasm/utils.go b/pkg/rlptools/wasm/utils.go index 75d3025c8..dc5ce74b3 100644 --- a/pkg/rlptools/wasm/utils.go +++ b/pkg/rlptools/wasm/utils.go @@ -8,7 +8,6 @@ import ( "fmt" "slices" "sort" - "strings" "unicode" "github.com/go-logr/logr" @@ -18,7 +17,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" @@ -33,14 +32,14 @@ var ( WASMFilterImageURL = env.GetString("RELATED_IMAGE_WASMSHIM", "oci://quay.io/kuadrant/wasm-shim:latest") ) -func LimitsNamespaceFromRLP(rlp *kuadrantv1beta2.RateLimitPolicy) string { +func LimitsNamespaceFromRLP(rlp *kuadrantv1beta3.RateLimitPolicy) string { return fmt.Sprintf("%s/%s", rlp.GetNamespace(), rlp.GetName()) } // Rules computes WASM rules from the policy and the targeted route. // It returns an empty list of wasm rules if the policy specifies no limits or if all limits specified in the policy // fail to match any route rule according to the limits route selectors. -func Rules(rlp *kuadrantv1beta2.RateLimitPolicy, route *gatewayapiv1.HTTPRoute) []Rule { +func Rules(rlp *kuadrantv1beta3.RateLimitPolicy, route *gatewayapiv1.HTTPRoute) []Rule { rules := make([]Rule, 0) if rlp == nil { return rules @@ -85,7 +84,7 @@ func LimitNameToLimitadorIdentifier(rlpKey types.NamespacedName, uniqueLimitName return identifier } -func ruleFromLimit(rlp *kuadrantv1beta2.RateLimitPolicy, limitIdentifier string, limit *kuadrantv1beta2.Limit, route *gatewayapiv1.HTTPRoute) (Rule, error) { +func ruleFromLimit(rlp *kuadrantv1beta3.RateLimitPolicy, limitIdentifier string, limit *kuadrantv1beta3.Limit, route *gatewayapiv1.HTTPRoute) (Rule, error) { rule := Rule{} conditions, err := conditionsFromLimit(limit, route) @@ -108,31 +107,16 @@ func ruleFromLimit(rlp *kuadrantv1beta2.RateLimitPolicy, limitIdentifier string, return rule, nil } -func conditionsFromLimit(limit *kuadrantv1beta2.Limit, route *gatewayapiv1.HTTPRoute) ([]Condition, error) { +func conditionsFromLimit(limit *kuadrantv1beta3.Limit, route *gatewayapiv1.HTTPRoute) ([]Condition, error) { if limit == nil { return nil, errors.New("limit should not be nil") } routeConditions := make([]Condition, 0) - if len(limit.RouteSelectors) > 0 { - // build conditions from the rules selected by the route selectors - for idx := range limit.RouteSelectors { - routeSelector := limit.RouteSelectors[idx] - hostnamesForConditions := routeSelector.HostnamesForConditions(route) - for _, rule := range routeSelector.SelectRules(route) { - routeConditions = append(routeConditions, conditionsFromRule(rule, hostnamesForConditions)...) - } - } - if len(routeConditions) == 0 { - return nil, errors.New("cannot match any route rules, check for invalid route selectors in the policy") - } - } else { - // build conditions from all rules if no route selectors are defined - hostnamesForConditions := (&kuadrantv1beta2.RouteSelector{}).HostnamesForConditions(route) - for _, rule := range route.Spec.Rules { - routeConditions = append(routeConditions, conditionsFromRule(rule, hostnamesForConditions)...) - } + // build conditions from all rules + for _, rule := range route.Spec.Rules { + routeConditions = append(routeConditions, conditionsFromRule(rule)...) } if len(limit.When) == 0 { @@ -163,41 +147,12 @@ func conditionsFromLimit(limit *kuadrantv1beta2.Limit, route *gatewayapiv1.HTTPR return whenConditions, nil } -// conditionsFromRule builds a list of conditions from a rule and a list of hostnames -// each combination of a rule match and hostname yields one condition +// conditionsFromRule builds a list of conditions from a rule // rules that specify no explicit match are assumed to match all request (i.e. implicit catch-all rule) -// empty list of hostnames yields a condition without a hostname pattern expression -func conditionsFromRule(rule gatewayapiv1.HTTPRouteRule, hostnames []gatewayapiv1.Hostname) (conditions []Condition) { - if len(rule.Matches) == 0 { - for _, hostname := range hostnames { - if hostname == "*" { - continue - } - condition := Condition{AllOf: []PatternExpression{patternExpresionFromHostname(hostname)}} - conditions = append(conditions, condition) - } - return - } - - for _, match := range rule.Matches { - condition := Condition{AllOf: patternExpresionsFromMatch(match)} - - if len(hostnames) > 0 { - for _, hostname := range hostnames { - if hostname == "*" { - conditions = append(conditions, condition) - continue - } - mergedCondition := condition - mergedCondition.AllOf = append(mergedCondition.AllOf, patternExpresionFromHostname(hostname)) - conditions = append(conditions, mergedCondition) - } - continue - } - - conditions = append(conditions, condition) - } - return +func conditionsFromRule(rule gatewayapiv1.HTTPRouteRule) []Condition { + return utils.Map(rule.Matches, func(match gatewayapiv1.HTTPRouteMatch) Condition { + return Condition{AllOf: patternExpresionsFromMatch(match)} + }) } func patternExpresionsFromMatch(match gatewayapiv1.HTTPRouteMatch) []PatternExpression { @@ -228,7 +183,7 @@ func patternExpresionsFromMatch(match gatewayapiv1.HTTPRouteMatch) []PatternExpr func patternExpresionFromPathMatch(pathMatch gatewayapiv1.HTTPPathMatch) PatternExpression { var ( - operator = PatternOperator(kuadrantv1beta2.StartsWithOperator) // default value + operator = PatternOperator(kuadrantv1beta3.StartsWithOperator) // default value value = "/" // default value ) @@ -252,7 +207,7 @@ func patternExpresionFromPathMatch(pathMatch gatewayapiv1.HTTPPathMatch) Pattern func patternExpresionFromMethod(method gatewayapiv1.HTTPMethod) PatternExpression { return PatternExpression{ Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), Value: string(method), } } @@ -262,27 +217,13 @@ func patternExpresionFromHeader(headerMatch gatewayapiv1.HTTPHeaderMatch) Patter // https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPHeaderMatch return PatternExpression{ - Selector: kuadrantv1beta2.ContextSelector(fmt.Sprintf("request.headers.%s", headerMatch.Name)), - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), + Selector: kuadrantv1beta3.ContextSelector(fmt.Sprintf("request.headers.%s", headerMatch.Name)), + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), Value: headerMatch.Value, } } -func patternExpresionFromHostname(hostname gatewayapiv1.Hostname) PatternExpression { - value := string(hostname) - operator := "eq" - if strings.HasPrefix(value, "*.") { - operator = "endswith" - value = value[1:] - } - return PatternExpression{ - Selector: "request.host", - Operator: PatternOperator(operator), - Value: value, - } -} - -func patternExpresionFromWhen(when kuadrantv1beta2.WhenCondition) PatternExpression { +func patternExpresionFromWhen(when kuadrantv1beta3.WhenCondition) PatternExpression { return PatternExpression{ Selector: when.Selector, Operator: PatternOperator(when.Operator), @@ -290,7 +231,7 @@ func patternExpresionFromWhen(when kuadrantv1beta2.WhenCondition) PatternExpress } } -func dataFromLimit(limitIdentifier string, limit *kuadrantv1beta2.Limit) (data []DataType) { +func dataFromLimit(limitIdentifier string, limit *kuadrantv1beta3.Limit) (data []DataType) { if limit == nil { return } @@ -317,7 +258,7 @@ func dataFromLimit(limitIdentifier string, limit *kuadrantv1beta2.Limit) (data [ return data } -func routeFromRLP(ctx context.Context, t *kuadrantgatewayapi.TopologyIndexes, rlp *kuadrantv1beta2.RateLimitPolicy, gw *gatewayapiv1.Gateway) (*gatewayapiv1.HTTPRoute, error) { +func routeFromRLP(ctx context.Context, t *kuadrantgatewayapi.TopologyIndexes, rlp *kuadrantv1beta3.RateLimitPolicy, gw *gatewayapiv1.Gateway) (*gatewayapiv1.HTTPRoute, error) { logger, err := logr.FromContext(ctx) if err != nil { return nil, err @@ -356,7 +297,7 @@ func routeFromRLP(ctx context.Context, t *kuadrantgatewayapi.TopologyIndexes, rl return route, nil } -func wasmRateLimitPolicy(ctx context.Context, t *kuadrantgatewayapi.TopologyIndexes, rlp *kuadrantv1beta2.RateLimitPolicy, gw *gatewayapiv1.Gateway) (*Policy, error) { +func wasmRateLimitPolicy(ctx context.Context, t *kuadrantgatewayapi.TopologyIndexes, rlp *kuadrantv1beta3.RateLimitPolicy, gw *gatewayapiv1.Gateway) (*Policy, error) { route, err := routeFromRLP(ctx, t, rlp, gw) if err != nil { return nil, err @@ -430,7 +371,7 @@ func ConfigForGateway( } for _, policy := range rateLimitPolicies { - rlp := policy.(*kuadrantv1beta2.RateLimitPolicy) + rlp := policy.(*kuadrantv1beta3.RateLimitPolicy) wasmRLP, err := wasmRateLimitPolicy(ctx, topologyIndex, rlp, gw) if err != nil { return nil, err diff --git a/pkg/rlptools/wasm/utils_test.go b/pkg/rlptools/wasm/utils_test.go index 03385266b..3ed026a9f 100644 --- a/pkg/rlptools/wasm/utils_test.go +++ b/pkg/rlptools/wasm/utils_test.go @@ -12,7 +12,7 @@ import ( "k8s.io/utils/ptr" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" ) // TODO(eastizle): missing WASMPluginMutator tests @@ -46,14 +46,14 @@ func TestRules(t *testing.T) { }, } - rlp := func(name string, limits map[string]kuadrantv1beta2.Limit) *kuadrantv1beta2.RateLimitPolicy { - return &kuadrantv1beta2.RateLimitPolicy{ + rlp := func(name string, limits map[string]kuadrantv1beta3.Limit) *kuadrantv1beta3.RateLimitPolicy { + return &kuadrantv1beta3.RateLimitPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: "my-app", }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ Limits: limits, }, }, @@ -61,23 +61,23 @@ func TestRules(t *testing.T) { } // a simple 50rps counter, for convinience, to be used in tests - counter50rps := kuadrantv1beta2.Rate{ + counter50rps := kuadrantv1beta3.Rate{ Limit: 50, Duration: 1, - Unit: kuadrantv1beta2.TimeUnit("second"), + Unit: kuadrantv1beta3.TimeUnit("second"), } testCases := []struct { name string - rlp *kuadrantv1beta2.RateLimitPolicy + rlp *kuadrantv1beta3.RateLimitPolicy route *gatewayapiv1.HTTPRoute expectedRules []Rule }{ { name: "minimal RLP", - rlp: rlp("minimal", map[string]kuadrantv1beta2.Limit{ + rlp: rlp("minimal", map[string]kuadrantv1beta3.Limit{ "50rps": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, + Rates: []kuadrantv1beta3.Rate{counter50rps}, }, }), route: httpRoute, @@ -88,12 +88,12 @@ func TestRules(t *testing.T) { AllOf: []PatternExpression{ { Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -119,44 +119,47 @@ func TestRules(t *testing.T) { }, }, { - name: "RLP with route selector based on hostname", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps-for-selected-hostnames": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { - Hostnames: []gatewayapiv1.Hostname{ - "*.example.com", - "myapp.apps.example.com", // ignored - }, - }, - }, + name: "HTTPRouteRules without rule matches", + rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ + "50rps": { + Rates: []kuadrantv1beta3.Rate{counter50rps}, }, }), - route: httpRoute, + route: catchAllHTTPRoute, expectedRules: []Rule{ { - Conditions: []Condition{ + Conditions: nil, + Actions: []Action{ { - AllOf: []PatternExpression{ - { - Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta2.StartsWithOperator), - Value: "/toy", - }, - { - Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), - Value: "GET", - }, + Scope: "my-app/my-rlp", + ExtensionName: RateLimitPolicyExtensionName, + Data: []DataType{ { - Selector: "request.host", - Operator: PatternOperator(kuadrantv1beta2.EndsWithOperator), - Value: ".example.com", + Value: &Static{ + Static: StaticSpec{ + Key: "limit.50rps__783b9343", + Value: "1", + }, + }, }, }, }, }, + }, + }, + }, + { + name: "RLP with counter qualifier", + rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ + "50rps-per-username": { + Rates: []kuadrantv1beta3.Rate{counter50rps}, + Counters: []kuadrantv1beta3.ContextSelector{"auth.identity.username"}, + }, + }), + route: catchAllHTTPRoute, + expectedRules: []Rule{ + { + Conditions: nil, Actions: []Action{ { Scope: "my-app/my-rlp", @@ -165,11 +168,18 @@ func TestRules(t *testing.T) { { Value: &Static{ Static: StaticSpec{ - Key: "limit.50rps_for_selected_hostnames__ac4044ab", + Key: "limit.50rps_per_username__d681f6c3", Value: "1", }, }, }, + { + Value: &Selector{ + Selector: SelectorSpec{ + Selector: "auth.identity.username", + }, + }, + }, }, }, }, @@ -177,26 +187,40 @@ func TestRules(t *testing.T) { }, }, { - name: "RLP with route selector based on http route matches (full match)", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps-for-selected-route": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ + name: "Route with header match", + rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ + "50rps": { + Rates: []kuadrantv1beta3.Rate{counter50rps}, + }, + }), + route: &gatewayapiv1.HTTPRoute{ + Spec: gatewayapiv1.HTTPRouteSpec{ + Hostnames: []gatewayapiv1.Hostname{"*.example.com"}, + Rules: []gatewayapiv1.HTTPRouteRule{ { Matches: []gatewayapiv1.HTTPRouteMatch{ { Path: &gatewayapiv1.HTTPPathMatch{ - Type: &[]gatewayapiv1.PathMatchType{gatewayapiv1.PathMatchPathPrefix}[0], - Value: &[]string{"/toy"}[0], + Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), + Value: ptr.To("/v1"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodGet), + Headers: []gatewayapiv1.HTTPHeaderMatch{ + { + Name: gatewayapiv1.HTTPHeaderName("X-kuadrant-a"), + Value: "1", + }, + { + Name: gatewayapiv1.HTTPHeaderName("X-kuadrant-b"), + Value: "1", + }, }, - Method: &[]gatewayapiv1.HTTPMethod{"GET"}[0], }, }, }, }, }, - }), - route: httpRoute, + }, expectedRules: []Rule{ { Conditions: []Condition{ @@ -204,14 +228,24 @@ func TestRules(t *testing.T) { AllOf: []PatternExpression{ { Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta2.StartsWithOperator), - Value: "/toy", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/v1", }, { Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, + { + Selector: "request.headers.X-kuadrant-a", + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "1", + }, + { + Selector: "request.headers.X-kuadrant-b", + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "1", + }, }, }, }, @@ -223,7 +257,7 @@ func TestRules(t *testing.T) { { Value: &Static{ Static: StaticSpec{ - Key: "limit.50rps_for_selected_route__db289136", + Key: "limit.50rps__783b9343", Value: "1", }, }, @@ -235,92 +269,100 @@ func TestRules(t *testing.T) { }, }, { - name: "RLP with route selector based on http route matches (partial match)", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps-for-selected-path": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ + name: "RLP with when and counter attributes", + rlp: rlp("my-rlp", map[string]kuadrantv1beta3.Limit{ + "users": { + Rates: []kuadrantv1beta3.Rate{counter50rps}, + Counters: []kuadrantv1beta3.ContextSelector{"auth.identity.username"}, + When: []kuadrantv1beta3.WhenCondition{ { + Selector: kuadrantv1beta3.ContextSelector("auth.identity.group"), + Operator: kuadrantv1beta3.NotEqualOperator, + Value: "admin", + }, + }, + }, + "all": { + Rates: []kuadrantv1beta3.Rate{counter50rps}, + }, + }), + route: &gatewayapiv1.HTTPRoute{ + Spec: gatewayapiv1.HTTPRouteSpec{ + Hostnames: []gatewayapiv1.Hostname{"api.toystore.com"}, + // 2 rules + Rules: []gatewayapiv1.HTTPRouteRule{ + { // Toys rule (think about routing to toystore backend) Matches: []gatewayapiv1.HTTPRouteMatch{ { Path: &gatewayapiv1.HTTPPathMatch{ - Type: &[]gatewayapiv1.PathMatchType{gatewayapiv1.PathMatchPathPrefix}[0], - Value: &[]string{"/toy"}[0], + Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), + Value: ptr.To("/toys"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodGet), + }, + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), + Value: ptr.To("/toys"), + }, + Method: ptr.To(gatewayapiv1.HTTPMethodPost), + }, + }, + }, + { // Assets rule (think about routing to assets backend) + Matches: []gatewayapiv1.HTTPRouteMatch{ + { + Path: &gatewayapiv1.HTTPPathMatch{ + Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), + Value: ptr.To("/assets"), }, }, }, }, }, }, - }), - route: httpRoute, + }, expectedRules: []Rule{ - { + { // rule associated to "all" limit Conditions: []Condition{ { AllOf: []PatternExpression{ { Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta2.StartsWithOperator), - Value: "/toy", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/toys", }, { Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, }, - }, - Actions: []Action{ { - Scope: "my-app/my-rlp", - ExtensionName: RateLimitPolicyExtensionName, - Data: []DataType{ + AllOf: []PatternExpression{ { - Value: &Static{ - Static: StaticSpec{ - Key: "limit.50rps_for_selected_path__38eb97a4", - Value: "1", - }, - }, + Selector: "request.url_path", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/toys", + }, + { + Selector: "request.method", + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "POST", }, }, }, - }, - }, - }, - }, - { - name: "RLP with mismatching route selectors", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps-for-non-existent-route": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ { - Matches: []gatewayapiv1.HTTPRouteMatch{ + AllOf: []PatternExpression{ { - Method: &[]gatewayapiv1.HTTPMethod{"POST"}[0], + Selector: "request.url_path", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/assets", }, }, }, }, - }, - }), - route: httpRoute, - expectedRules: []Rule{}, - }, - { - name: "HTTPRouteRules without rule matches", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - }, - }), - route: catchAllHTTPRoute, - expectedRules: []Rule{ - { - Conditions: nil, Actions: []Action{ { Scope: "my-app/my-rlp", @@ -329,7 +371,7 @@ func TestRules(t *testing.T) { { Value: &Static{ Static: StaticSpec{ - Key: "limit.50rps__783b9343", + Key: "limit.all__1edae8a9", Value: "1", }, }, @@ -338,105 +380,57 @@ func TestRules(t *testing.T) { }, }, }, - }, - }, - { - name: "RLP with counter qualifier", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps-per-username": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - Counters: []kuadrantv1beta2.ContextSelector{"auth.identity.username"}, - }, - }), - route: catchAllHTTPRoute, - expectedRules: []Rule{ - { - Conditions: nil, - Actions: []Action{ + { // rule associated to "users" limit + Conditions: []Condition{ { - Scope: "my-app/my-rlp", - ExtensionName: RateLimitPolicyExtensionName, - Data: []DataType{ + AllOf: []PatternExpression{ { - Value: &Static{ - Static: StaticSpec{ - Key: "limit.50rps_per_username__d681f6c3", - Value: "1", - }, - }, + Selector: "request.url_path", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/toys", }, { - Value: &Selector{ - Selector: SelectorSpec{ - Selector: "auth.identity.username", - }, - }, + Selector: "request.method", + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "GET", }, - }, - }, - }, - }, - }, - }, - { - name: "Route with header match", - rlp: rlp("my-rlp", map[string]kuadrantv1beta2.Limit{ - "50rps": { - Rates: []kuadrantv1beta2.Rate{counter50rps}, - }, - }), - route: &gatewayapiv1.HTTPRoute{ - Spec: gatewayapiv1.HTTPRouteSpec{ - Hostnames: []gatewayapiv1.Hostname{"*.example.com"}, - Rules: []gatewayapiv1.HTTPRouteRule{ - { - Matches: []gatewayapiv1.HTTPRouteMatch{ { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/v1"), - }, - Method: ptr.To(gatewayapiv1.HTTPMethodGet), - Headers: []gatewayapiv1.HTTPHeaderMatch{ - { - Name: gatewayapiv1.HTTPHeaderName("X-kuadrant-a"), - Value: "1", - }, - { - Name: gatewayapiv1.HTTPHeaderName("X-kuadrant-b"), - Value: "1", - }, - }, + Selector: "auth.identity.group", + Operator: PatternOperator(kuadrantv1beta3.NotEqualOperator), + Value: "admin", }, }, }, - }, - }, - }, - expectedRules: []Rule{ - { - Conditions: []Condition{ { AllOf: []PatternExpression{ { Selector: "request.url_path", - Operator: PatternOperator(kuadrantv1beta2.StartsWithOperator), - Value: "/v1", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/toys", }, { Selector: "request.method", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), - Value: "GET", + Operator: PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "POST", }, { - Selector: "request.headers.X-kuadrant-a", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), - Value: "1", + Selector: "auth.identity.group", + Operator: PatternOperator(kuadrantv1beta3.NotEqualOperator), + Value: "admin", }, + }, + }, + { + AllOf: []PatternExpression{ { - Selector: "request.headers.X-kuadrant-b", - Operator: PatternOperator(kuadrantv1beta2.EqualOperator), - Value: "1", + Selector: "request.url_path", + Operator: PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/assets", + }, + { + Selector: "auth.identity.group", + Operator: PatternOperator(kuadrantv1beta3.NotEqualOperator), + Value: "admin", }, }, }, @@ -449,11 +443,18 @@ func TestRules(t *testing.T) { { Value: &Static{ Static: StaticSpec{ - Key: "limit.50rps__783b9343", + Key: "limit.users__6231d900", Value: "1", }, }, }, + { + Value: &Selector{ + Selector: SelectorSpec{ + Selector: "auth.identity.username", + }, + }, + }, }, }, }, diff --git a/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go b/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go index fcbd70fdf..4ffb86ce9 100644 --- a/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go +++ b/tests/common/ratelimitpolicy/ratelimitpolicy_controller_test.go @@ -20,7 +20,7 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" "github.com/kuadrant/kuadrant-operator/pkg/rlptools" @@ -40,26 +40,26 @@ var _ = Describe("RateLimitPolicy controller (Serial)", Serial, func() { gateway *gatewayapiv1.Gateway ) - policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.RateLimitPolicy)) *kuadrantv1beta2.RateLimitPolicy { - policy := &kuadrantv1beta2.RateLimitPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta3.RateLimitPolicy)) *kuadrantv1beta3.RateLimitPolicy { + policy := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: rlpName, Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - Defaults: &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Defaults: &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: "minute", }, @@ -92,9 +92,9 @@ var _ = Describe("RateLimitPolicy controller (Serial)", Serial, func() { Context("RLP Enforced Reasons", func() { const limitadorDeploymentName = "limitador-limitador" - assertAcceptedCondTrueAndEnforcedCond := func(ctx context.Context, policy *kuadrantv1beta2.RateLimitPolicy, conditionStatus metav1.ConditionStatus, reason, message string) func(g Gomega) { + assertAcceptedCondTrueAndEnforcedCond := func(ctx context.Context, policy *kuadrantv1beta3.RateLimitPolicy, conditionStatus metav1.ConditionStatus, reason, message string) func(g Gomega) { return func(g Gomega) { - existingPolicy := &kuadrantv1beta2.RateLimitPolicy{} + existingPolicy := &kuadrantv1beta3.RateLimitPolicy{} g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(policy), existingPolicy)).To(Succeed()) acceptedCond := meta.FindStatusCondition(existingPolicy.Status.Conditions, string(gatewayapiv1alpha2.PolicyConditionAccepted)) g.Expect(acceptedCond).ToNot(BeNil()) @@ -159,26 +159,26 @@ var _ = Describe("RateLimitPolicy controller", func() { gateway *gatewayapiv1.Gateway ) - policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.RateLimitPolicy)) *kuadrantv1beta2.RateLimitPolicy { - policy := &kuadrantv1beta2.RateLimitPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta3.RateLimitPolicy)) *kuadrantv1beta3.RateLimitPolicy { + policy := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: rlpName, Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - Defaults: &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Defaults: &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: "minute", }, @@ -302,25 +302,25 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: rlpName, Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.Group("gateway.networking.k8s.io"), Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - Defaults: &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Defaults: &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: "minute", }, @@ -379,7 +379,7 @@ var _ = Describe("RateLimitPolicy controller", func() { It("Creates all the resources for a basic Gateway and RateLimitPolicy when missing a HTTPRoute attached to the Gateway", func(ctx SpecContext) { // create ratelimitpolicy - rlp := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlp := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(TestGatewayName) }) @@ -433,8 +433,8 @@ var _ = Describe("RateLimitPolicy controller", func() { Context("RLP Defaults", func() { Describe("Route policy defaults taking precedence over Gateway policy defaults", func() { var ( - gwRLP *kuadrantv1beta2.RateLimitPolicy - routeRLP *kuadrantv1beta2.RateLimitPolicy + gwRLP *kuadrantv1beta3.RateLimitPolicy + routeRLP *kuadrantv1beta3.RateLimitPolicy ) BeforeEach(func(ctx SpecContext) { @@ -447,7 +447,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create GW RLP - gwRLP = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwRLP = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(TestGatewayName) }) @@ -456,11 +456,11 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(assertPolicyIsAcceptedAndEnforced(ctx, gwRLPKey)).WithContext(ctx).Should(BeTrue()) // Create HTTPRoute RLP with new default limits - routeRLP = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + routeRLP = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "httproute-rlp" - policy.Spec.CommonSpec().Limits = map[string]kuadrantv1beta2.Limit{ + policy.Spec.CommonSpec().Limits = map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 10, Duration: 5, Unit: "second", }, @@ -519,7 +519,7 @@ var _ = Describe("RateLimitPolicy controller", func() { }) It("Explicit defaults - no underlying routes to enforce policy", func(ctx SpecContext) { - gwRLP := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwRLP := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(TestGatewayName) }) @@ -531,7 +531,7 @@ var _ = Describe("RateLimitPolicy controller", func() { }, testTimeOut) It("Implicit defaults - no underlying routes to enforce policy", func(ctx SpecContext) { - gwRLP := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwRLP := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(TestGatewayName) policy.Spec.RateLimitPolicyCommonSpec = *policy.Spec.Defaults.DeepCopy() @@ -546,8 +546,8 @@ var _ = Describe("RateLimitPolicy controller", func() { }) Context("RLP Overrides", func() { - var gwRLP *kuadrantv1beta2.RateLimitPolicy - var routeRLP *kuadrantv1beta2.RateLimitPolicy + var gwRLP *kuadrantv1beta3.RateLimitPolicy + var routeRLP *kuadrantv1beta3.RateLimitPolicy BeforeEach(func(ctx SpecContext) { // create httproute @@ -555,18 +555,18 @@ var _ = Describe("RateLimitPolicy controller", func() { Expect(k8sClient.Create(ctx, httpRoute)).To(Succeed()) Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) - gwRLP = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwRLP = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(TestGatewayName) policy.Spec.Overrides = policy.Spec.Defaults.DeepCopy() policy.Spec.Defaults = nil }) - routeRLP = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + routeRLP = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "httproute-rlp" - policy.Spec.CommonSpec().Limits = map[string]kuadrantv1beta2.Limit{ + policy.Spec.CommonSpec().Limits = map[string]kuadrantv1beta3.Limit{ "route": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 10, Duration: 5, Unit: "second", }, @@ -681,7 +681,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(assertPolicyIsAcceptedAndEnforced(ctx, routeRLPKey)).WithContext(ctx).Should(BeTrue()) // Create GW RLP with defaults - gwRLP = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwRLP = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(TestGatewayName) }) @@ -789,10 +789,10 @@ var _ = Describe("RateLimitPolicy controller", func() { }) Context("RLP accepted condition reasons", func() { - assertAcceptedConditionTrue := func(rlp *kuadrantv1beta2.RateLimitPolicy) func() bool { + assertAcceptedConditionTrue := func(rlp *kuadrantv1beta3.RateLimitPolicy) func() bool { return func() bool { rlpKey := client.ObjectKeyFromObject(rlp) - existingRLP := &kuadrantv1beta2.RateLimitPolicy{} + existingRLP := &kuadrantv1beta3.RateLimitPolicy{} err := k8sClient.Get(context.Background(), rlpKey, existingRLP) if err != nil { return false @@ -802,10 +802,10 @@ var _ = Describe("RateLimitPolicy controller", func() { } } - assertAcceptedConditionFalse := func(ctx context.Context, rlp *kuadrantv1beta2.RateLimitPolicy, reason, message string) func(g Gomega) { + assertAcceptedConditionFalse := func(ctx context.Context, rlp *kuadrantv1beta3.RateLimitPolicy, reason, message string) func(g Gomega) { return func(g Gomega) { rlpKey := client.ObjectKeyFromObject(rlp) - existingRLP := &kuadrantv1beta2.RateLimitPolicy{} + existingRLP := &kuadrantv1beta3.RateLimitPolicy{} g.Expect(k8sClient.Get(ctx, rlpKey, existingRLP)).To(Succeed()) cond := meta.FindStatusCondition(existingRLP.Status.Conditions, string(gatewayapiv1alpha2.PolicyConditionAccepted)) @@ -836,7 +836,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(assertAcceptedConditionTrue(rlp), time.Minute, 5*time.Second).Should(BeTrue()) - rlp2 := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlp2 := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "conflicting-rlp" }) Expect(k8sClient.Create(ctx, rlp2)).To(Succeed()) @@ -870,7 +870,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteA))).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlp := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeAName) }) @@ -900,7 +900,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteB))).WithContext(ctx).Should(BeTrue()) Eventually(func(g Gomega) { - rlpUpdated := &kuadrantv1beta2.RateLimitPolicy{} + rlpUpdated := &kuadrantv1beta3.RateLimitPolicy{} err = k8sClient.Get(ctx, client.ObjectKeyFromObject(rlp), rlpUpdated) g.Expect(err).ToNot(HaveOccurred()) rlpUpdated.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeBName) @@ -948,7 +948,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.GatewayIsReady(ctx, testClient(), gatewayA)).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlp := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(gwAName) }) @@ -979,7 +979,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.GatewayIsReady(ctx, testClient(), gatewayB)).WithContext(ctx).Should(BeTrue()) Eventually(func(g Gomega) { - rlpUpdated := &kuadrantv1beta2.RateLimitPolicy{} + rlpUpdated := &kuadrantv1beta3.RateLimitPolicy{} err = k8sClient.Get(ctx, client.ObjectKeyFromObject(rlp), rlpUpdated) g.Expect(err).ToNot(HaveOccurred()) rlpUpdated.Spec.TargetRef.Name = gatewayapiv1.ObjectName(gwBName) @@ -1039,7 +1039,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteB))).WithContext(ctx).Should(BeTrue()) // create rlpA - rlpA := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpA := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = rlpAName policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeAName) @@ -1051,7 +1051,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(assertPolicyIsAcceptedAndEnforced(ctx, rlpAKey)).WithContext(ctx).Should(BeTrue()) // create rlpB - rlpB := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpB := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = rlpBName policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeBName) @@ -1084,7 +1084,7 @@ var _ = Describe("RateLimitPolicy controller", func() { // To RLP A -> Route B (already taken) Eventually(func(g Gomega) { - rlpUpdated := &kuadrantv1beta2.RateLimitPolicy{} + rlpUpdated := &kuadrantv1beta3.RateLimitPolicy{} err = k8sClient.Get(ctx, client.ObjectKeyFromObject(rlpA), rlpUpdated) g.Expect(err).ToNot(HaveOccurred()) rlpUpdated.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeBName) @@ -1127,7 +1127,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create rlp - rlp := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlp := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeName) }) @@ -1187,7 +1187,7 @@ var _ = Describe("RateLimitPolicy controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteA))).WithContext(ctx).Should(BeTrue()) // create rlpA - rlpA := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpA := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = rlpAName policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeAName) @@ -1202,7 +1202,7 @@ var _ = Describe("RateLimitPolicy controller", func() { // new RLP B -> Route A (already taken) // create rlpB - rlpB := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpB := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = rlpBName policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeAName) @@ -1235,7 +1235,7 @@ var _ = Describe("RateLimitPolicy controller", func() { // RLP A -> Route B Eventually(func(g Gomega) { - rlpUpdated := &kuadrantv1beta2.RateLimitPolicy{} + rlpUpdated := &kuadrantv1beta3.RateLimitPolicy{} err = k8sClient.Get(ctx, client.ObjectKeyFromObject(rlpA), rlpUpdated) g.Expect(err).ToNot(HaveOccurred()) rlpUpdated.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeBName) @@ -1311,15 +1311,15 @@ var _ = Describe("RateLimitPolicy controller", func() { }) It("It defines route policy limits with gateway policy overrides", func(ctx SpecContext) { - rlpGatewayA := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpGatewayA := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = gatewayAName policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(gatewayAName) policy.Spec.Defaults = nil - policy.Spec.Overrides = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Overrides = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "gw-a-1000rps": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1000, Duration: 1, Unit: "second", }, @@ -1331,15 +1331,15 @@ var _ = Describe("RateLimitPolicy controller", func() { err := k8sClient.Create(ctx, rlpGatewayA) Expect(err).ToNot(HaveOccurred()) - rlpGatewayB := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpGatewayB := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = gatewayBName policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(gatewayBName) policy.Spec.Defaults = nil - policy.Spec.Overrides = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Overrides = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "gw-b-100rps": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 100, Duration: 1, Unit: "second", }, @@ -1351,13 +1351,13 @@ var _ = Describe("RateLimitPolicy controller", func() { err = k8sClient.Create(ctx, rlpGatewayB) Expect(err).ToNot(HaveOccurred()) - rlpTargetedRoute := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + rlpTargetedRoute := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.ObjectMeta.Name = targetedRouteName policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = gatewayapiv1.ObjectName(targetedRouteName) - policy.Spec.CommonSpec().Limits = map[string]kuadrantv1beta2.Limit{ + policy.Spec.CommonSpec().Limits = map[string]kuadrantv1beta3.Limit{ "route-10rps": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 10, Duration: 1, Unit: "second", }, @@ -1423,13 +1423,13 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { tests.DeleteNamespace(ctx, testClient(), testNamespace) }, afterEachTimeOut) - policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.RateLimitPolicy)) *kuadrantv1beta2.RateLimitPolicy { - policy := &kuadrantv1beta2.RateLimitPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta3.RateLimitPolicy)) *kuadrantv1beta3.RateLimitPolicy { + policy := &kuadrantv1beta3.RateLimitPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "my-policy", Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", @@ -1452,7 +1452,7 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Valid policy targeting Gateway", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" }) err := k8sClient.Create(ctx, policy) @@ -1460,7 +1460,7 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Invalid Target Ref Group", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Group = "not-gateway.networking.k8s.io" }) err := k8sClient.Create(ctx, policy) @@ -1469,7 +1469,7 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Invalid Target Ref Kind", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "TCPRoute" }) err := k8sClient.Create(ctx, policy) @@ -1480,10 +1480,10 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { Context("Defaults / Override validation", func() { It("Valid - only implicit defaults defined", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.Limits = map[string]kuadrantv1beta2.Limit{ + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { + policy.Spec.Limits = map[string]kuadrantv1beta3.Limit{ "implicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, }, } }) @@ -1491,11 +1491,11 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Valid - only explicit defaults defined", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.Defaults = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { + policy.Spec.Defaults = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "explicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, }, }, } @@ -1504,17 +1504,17 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Invalid - implicit and explicit defaults are mutually exclusive", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.Defaults = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { + policy.Spec.Defaults = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "explicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, }, }, } - policy.Spec.Limits = map[string]kuadrantv1beta2.Limit{ + policy.Spec.Limits = map[string]kuadrantv1beta3.Limit{ "implicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, }, } }) @@ -1524,18 +1524,18 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Invalid - explicit default and override defined", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.Defaults = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { + policy.Spec.Defaults = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "implicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, }, }, } - policy.Spec.Overrides = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Overrides = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "explicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, }, }, } @@ -1546,16 +1546,16 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Invalid - implicit default and override defined", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.Limits = map[string]kuadrantv1beta2.Limit{ + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { + policy.Spec.Limits = map[string]kuadrantv1beta3.Limit{ "implicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 2, Duration: 20, Unit: "second"}}, }, } - policy.Spec.Overrides = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Overrides = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "overrides": { - Rates: []kuadrantv1beta2.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, }, }, } @@ -1566,11 +1566,11 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Invalid - policy override targeting resource other than Gateway", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.Overrides = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { + policy.Spec.Overrides = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "implicit": { - Rates: []kuadrantv1beta2.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, }, }, } @@ -1581,12 +1581,12 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { }, testTimeOut) It("Valid - policy override targeting Gateway", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Spec.TargetRef.Kind = "Gateway" - policy.Spec.Overrides = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Overrides = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "override": { - Rates: []kuadrantv1beta2.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, + Rates: []kuadrantv1beta3.Rate{{Limit: 1, Duration: 10, Unit: "second"}}, }, }, } @@ -1594,44 +1594,4 @@ var _ = Describe("RateLimitPolicy CEL Validations", func() { Expect(k8sClient.Create(ctx, policy)).To(Succeed()) }, testTimeOut) }) - - Context("Route Selector Validation", func() { - const ( - gateWayRouteSelectorErrorMessage = "route selectors not supported when targeting a Gateway" - ) - - It("invalid usage of limit route selectors with a gateway targetRef", func(ctx SpecContext) { - policy := policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { - policy.Spec.TargetRef.Kind = "Gateway" - policy.Spec.TargetRef.Name = "my-gw" - policy.Spec.RateLimitPolicyCommonSpec = kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ - "l1": { - Rates: []kuadrantv1beta2.Rate{ - { - Limit: 1, Duration: 3, Unit: "minute", - }, - }, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { - Hostnames: []gatewayapiv1.Hostname{"*.foo.io"}, - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Value: ptr.To("/foo"), - }, - }, - }, - }, - }, - }, - }, - } - }) - - err := k8sClient.Create(ctx, policy) - Expect(err).To(Not(BeNil())) - Expect(strings.Contains(err.Error(), gateWayRouteSelectorErrorMessage)).To(BeTrue()) - }, testTimeOut) - }) }) diff --git a/tests/common/targetstatus/target_status_controller_test.go b/tests/common/targetstatus/target_status_controller_test.go index b8cb2f5d8..7ce33de85 100644 --- a/tests/common/targetstatus/target_status_controller_test.go +++ b/tests/common/targetstatus/target_status_controller_test.go @@ -11,7 +11,6 @@ import ( certmanv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certmanmetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" authorinoapi "github.com/kuadrant/authorino/api/v1beta2" - kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -23,8 +22,11 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - "github.com/kuadrant/kuadrant-operator/api/v1alpha1" - "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" + + kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" + kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/controllers" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" @@ -135,25 +137,25 @@ var _ = Describe("Target status reconciler", func() { policyAffectedCondition := controllers.PolicyAffectedConditionType("AuthPolicy") // policyFactory builds a standards AuthPolicy object that targets the test HTTPRoute by default, with the given mutate functions applied - policyFactory := func(mutateFns ...func(policy *v1beta2.AuthPolicy)) *v1beta2.AuthPolicy { - policy := &v1beta2.AuthPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.AuthPolicy)) *kuadrantv1beta2.AuthPolicy { + policy := &kuadrantv1beta2.AuthPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "AuthPolicy", - APIVersion: v1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta2.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "toystore", Namespace: testNamespace, }, - Spec: v1beta2.AuthPolicySpec{ + Spec: kuadrantv1beta2.AuthPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: TestHTTPRouteName, }, - Defaults: &v1beta2.AuthPolicyCommonSpec{ - AuthScheme: &v1beta2.AuthSchemeSpec{ - Authentication: map[string]v1beta2.AuthenticationSpec{ + Defaults: &kuadrantv1beta2.AuthPolicyCommonSpec{ + AuthScheme: &kuadrantv1beta2.AuthSchemeSpec{ + Authentication: map[string]kuadrantv1beta2.AuthenticationSpec{ "anonymous": { AuthenticationSpec: authorinoapi.AuthenticationSpec{ AuthenticationMethodSpec: authorinoapi.AuthenticationMethodSpec{ @@ -174,7 +176,7 @@ var _ = Describe("Target status reconciler", func() { // policyAcceptedAndTargetsAffected returns an assertion function that checks if an AuthPolicy is accepted // and the statuses of its target object and other optional route objects have been all updated as affected by the policy - policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *v1beta2.AuthPolicy, routeNames ...string) func() bool { + policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *kuadrantv1beta2.AuthPolicy, routeNames ...string) func() bool { return func() bool { if !tests.IsAuthPolicyAccepted(ctx, testClient(), policy)() { return false @@ -190,14 +192,14 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("Adds truthy PolicyAffected status condition if there is at least one policy accepted", func(ctx SpecContext) { - routePolicy1 := policyFactory(func(p *v1beta2.AuthPolicy) { + routePolicy1 := policyFactory(func(p *kuadrantv1beta2.AuthPolicy) { p.Name = "route-auth-1" }) Expect(k8sClient.Create(ctx, routePolicy1)).To(Succeed()) Eventually(policyAcceptedAndTargetsAffected(ctx, routePolicy1)).WithContext(ctx).Should(BeTrue()) - routePolicy2 := policyFactory(func(p *v1beta2.AuthPolicy) { // another policy that targets the same route. this policy will not be accepted + routePolicy2 := policyFactory(func(p *kuadrantv1beta2.AuthPolicy) { // another policy that targets the same route. this policy will not be accepted p.Name = "route-auth-2" }) Expect(k8sClient.Create(ctx, routePolicy2)).To(Succeed()) @@ -210,15 +212,15 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("Adds falsey PolicyAffected status condition if no policy is accepted", func(ctx SpecContext) { - routePolicy1 := policyFactory(func(p *v1beta2.AuthPolicy) { // create a policy with an invalid route selector so the policy is not accepted + routePolicy1 := policyFactory(func(p *kuadrantv1beta2.AuthPolicy) { // create a policy with an invalid route selector so the policy is not accepted p.Name = "route-auth-1" - p.Spec.Defaults.RouteSelectors = []v1beta2.RouteSelector{{Hostnames: []gatewayapiv1.Hostname{"invalid.example.com"}}} + p.Spec.Defaults.RouteSelectors = []kuadrantv1beta2.RouteSelector{{Hostnames: []gatewayapiv1.Hostname{"invalid.example.com"}}} }) Expect(k8sClient.Create(ctx, routePolicy1)).To(Succeed()) - routePolicy2 := policyFactory(func(p *v1beta2.AuthPolicy) { // create another policy with an invalid route selector so the policy is not accepted + routePolicy2 := policyFactory(func(p *kuadrantv1beta2.AuthPolicy) { // create another policy with an invalid route selector so the policy is not accepted p.Name = "route-auth-2" - p.Spec.Defaults.RouteSelectors = []v1beta2.RouteSelector{{Hostnames: []gatewayapiv1.Hostname{"invalid.example.com"}}} + p.Spec.Defaults.RouteSelectors = []kuadrantv1beta2.RouteSelector{{Hostnames: []gatewayapiv1.Hostname{"invalid.example.com"}}} }) Expect(k8sClient.Create(ctx, routePolicy2)).To(Succeed()) @@ -249,7 +251,7 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("adds PolicyAffected status condition to the targeted gateway and routes", func(ctx SpecContext) { - policy := policyFactory(func(policy *v1beta2.AuthPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta2.AuthPolicy) { policy.Name = "gateway-auth" policy.Spec.TargetRef = gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, @@ -262,7 +264,7 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("removes PolicyAffected status condition from the targeted gateway and routes when the policy is deleted", func(ctx SpecContext) { - policy := policyFactory(func(policy *v1beta2.AuthPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta2.AuthPolicy) { policy.Name = "gateway-auth" policy.Spec.TargetRef = gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, @@ -301,7 +303,7 @@ var _ = Describe("Target status reconciler", func() { otherRoute := tests.BuildBasicHttpRoute(otherRouteName, TestGatewayName, testNamespace, []string{randomHostFromGWHost()}) Expect(k8sClient.Create(ctx, otherRoute)).To(Succeed()) - gatewayPolicy := policyFactory(func(policy *v1beta2.AuthPolicy) { + gatewayPolicy := policyFactory(func(policy *kuadrantv1beta2.AuthPolicy) { policy.Name = "gateway-auth" policy.Spec.TargetRef = gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, @@ -327,28 +329,28 @@ var _ = Describe("Target status reconciler", func() { policyAffectedCondition := controllers.PolicyAffectedConditionType("RateLimitPolicy") // policyFactory builds a standards RateLimitPolicy object that targets the test HTTPRoute by default, with the given mutate functions applied - policyFactory := func(mutateFns ...func(policy *v1beta2.RateLimitPolicy)) *v1beta2.RateLimitPolicy { - policy := &v1beta2.RateLimitPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta3.RateLimitPolicy)) *kuadrantv1beta3.RateLimitPolicy { + policy := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: v1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "toystore", Namespace: testNamespace, }, - Spec: v1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(TestHTTPRouteName), }, - Defaults: &v1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]v1beta2.Limit{ + Defaults: &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []v1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: v1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -364,7 +366,7 @@ var _ = Describe("Target status reconciler", func() { // policyAcceptedAndTargetsAffected returns an assertion function that checks if an RateLimitPolicy is accepted // and the statuses of its target object and other optional route objects have been all updated as affected by the policy - policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *v1beta2.RateLimitPolicy, routeNames ...string) func() bool { + policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *kuadrantv1beta3.RateLimitPolicy, routeNames ...string) func() bool { return func() bool { policyKey := client.ObjectKeyFromObject(policy) if !tests.RLPIsAccepted(ctx, testClient(), policyKey)() { @@ -399,7 +401,7 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("adds PolicyAffected status condition to the targeted gateway and routes", func(ctx SpecContext) { - policy := policyFactory(func(policy *v1beta2.RateLimitPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "gateway-rlp" policy.Spec.TargetRef = gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, @@ -412,7 +414,7 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("removes PolicyAffected status condition from the targeted gateway and routes when the policy is deleted", func(ctx SpecContext) { - policy := policyFactory(func(policy *v1beta2.RateLimitPolicy) { + policy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "gateway-rlp" policy.Spec.TargetRef = gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, @@ -451,7 +453,7 @@ var _ = Describe("Target status reconciler", func() { otherRoute := tests.BuildBasicHttpRoute(otherRouteName, TestGatewayName, testNamespace, []string{randomHostFromGWHost()}) Expect(k8sClient.Create(ctx, otherRoute)).To(Succeed()) - gatewayPolicy := policyFactory(func(policy *v1beta2.RateLimitPolicy) { + gatewayPolicy := policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "gateway-rlp" policy.Spec.TargetRef = gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, @@ -477,8 +479,8 @@ var _ = Describe("Target status reconciler", func() { policyAffectedCondition := controllers.PolicyAffectedConditionType("DNSPolicy") // policyFactory builds a standards DNSPolicy object that targets the test gateway by default, with the given mutate functions applied - policyFactory := func(mutateFns ...func(policy *v1alpha1.DNSPolicy)) *v1alpha1.DNSPolicy { - policy := v1alpha1.NewDNSPolicy("test-dns-policy", testNamespace).WithTargetGateway(TestGatewayName) + policyFactory := func(mutateFns ...func(policy *kuadrantv1alpha1.DNSPolicy)) *kuadrantv1alpha1.DNSPolicy { + policy := kuadrantv1alpha1.NewDNSPolicy("test-dns-policy", testNamespace).WithTargetGateway(TestGatewayName) for _, mutateFn := range mutateFns { mutateFn(policy) } @@ -486,7 +488,7 @@ var _ = Describe("Target status reconciler", func() { } isDNSPolicyAccepted := func(ctx context.Context, policyKey client.ObjectKey) bool { - policy := &v1alpha1.DNSPolicy{} + policy := &kuadrantv1alpha1.DNSPolicy{} err := k8sClient.Get(ctx, policyKey, policy) if err != nil { return false @@ -495,7 +497,7 @@ var _ = Describe("Target status reconciler", func() { } isDNSPolicyEnforced := func(ctx context.Context, policyKey client.ObjectKey) bool { - policy := &v1alpha1.DNSPolicy{} + policy := &kuadrantv1alpha1.DNSPolicy{} err := k8sClient.Get(ctx, policyKey, policy) if err != nil { return false @@ -505,7 +507,7 @@ var _ = Describe("Target status reconciler", func() { // policyAcceptedAndTargetsAffected returns an assertion function that checks if a DNSPolicy is accepted // and the statuses of its target object has been all updated as affected by the policy - policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *v1alpha1.DNSPolicy) func() bool { + policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *kuadrantv1alpha1.DNSPolicy) func() bool { return func() bool { policyKey := client.ObjectKeyFromObject(policy) return isDNSPolicyAccepted(ctx, policyKey) && targetsAffected(ctx, policyKey, policyAffectedCondition, policy.Spec.TargetRef) @@ -530,7 +532,7 @@ var _ = Describe("Target status reconciler", func() { }, afterEachTimeOut) It("adds PolicyAffected status condition to the targeted gateway", func(ctx SpecContext) { - policy := policyFactory(func(policy *v1alpha1.DNSPolicy) { + policy := policyFactory(func(policy *kuadrantv1alpha1.DNSPolicy) { policy.Spec.ProviderRefs = append(policy.Spec.ProviderRefs, kuadrantdnsv1alpha1.ProviderRef{ Name: dnsProviderSecret.Name, }) @@ -543,7 +545,7 @@ var _ = Describe("Target status reconciler", func() { }, testTimeOut) It("removes PolicyAffected status condition from the targeted gateway when the policy is deleted", func(ctx SpecContext) { - policy := policyFactory(func(policy *v1alpha1.DNSPolicy) { + policy := policyFactory(func(policy *kuadrantv1alpha1.DNSPolicy) { policy.Spec.ProviderRefs = append(policy.Spec.ProviderRefs, kuadrantdnsv1alpha1.ProviderRef{ Name: dnsProviderSecret.Name, }) @@ -574,8 +576,8 @@ var _ = Describe("Target status reconciler", func() { var issuerRef *certmanmetav1.ObjectReference // policyFactory builds a standards TLSPolicy object that targets the test gateway by default, with the given mutate functions applied - policyFactory := func(mutateFns ...func(policy *v1alpha1.TLSPolicy)) *v1alpha1.TLSPolicy { - policy := v1alpha1.NewTLSPolicy("test-tls-policy", testNamespace).WithTargetGateway(TestGatewayName).WithIssuerRef(*issuerRef) + policyFactory := func(mutateFns ...func(policy *kuadrantv1alpha1.TLSPolicy)) *kuadrantv1alpha1.TLSPolicy { + policy := kuadrantv1alpha1.NewTLSPolicy("test-tls-policy", testNamespace).WithTargetGateway(TestGatewayName).WithIssuerRef(*issuerRef) for _, mutateFn := range mutateFns { mutateFn(policy) } @@ -583,7 +585,7 @@ var _ = Describe("Target status reconciler", func() { } isTLSPolicyAccepted := func(ctx context.Context, policyKey client.ObjectKey) bool { - policy := &v1alpha1.TLSPolicy{} + policy := &kuadrantv1alpha1.TLSPolicy{} err := k8sClient.Get(ctx, policyKey, policy) if err != nil { return false @@ -593,7 +595,7 @@ var _ = Describe("Target status reconciler", func() { // policyAcceptedAndTargetsAffected returns an assertion function that checks if a TLSPolicy is accepted // and the statuses of its target object has been all updated as affected by the policy - policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *v1alpha1.TLSPolicy) func() bool { + policyAcceptedAndTargetsAffected := func(ctx context.Context, policy *kuadrantv1alpha1.TLSPolicy) func() bool { return func() bool { policyKey := client.ObjectKeyFromObject(policy) if !isTLSPolicyAccepted(ctx, policyKey) { diff --git a/tests/commons.go b/tests/commons.go index 928f5b166..d60ca4247 100644 --- a/tests/commons.go +++ b/tests/commons.go @@ -33,6 +33,7 @@ import ( kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" kuadrantgatewayapi "github.com/kuadrant/kuadrant-operator/pkg/library/gatewayapi" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" "github.com/kuadrant/kuadrant-operator/pkg/library/utils" @@ -279,7 +280,7 @@ func RLPIsEnforced(ctx context.Context, cl client.Client, rlpKey client.ObjectKe func RLPIsConditionTrue(ctx context.Context, cl client.Client, rlpKey client.ObjectKey, condition string) func() bool { return func() bool { - existingRLP := &kuadrantv1beta2.RateLimitPolicy{} + existingRLP := &kuadrantv1beta3.RateLimitPolicy{} err := cl.Get(ctx, rlpKey, existingRLP) if err != nil { logf.Log.V(1).Error(err, "ratelimitpolicy not read", "rlp", rlpKey) @@ -291,7 +292,7 @@ func RLPIsConditionTrue(ctx context.Context, cl client.Client, rlpKey client.Obj } func RLPEnforcedCondition(ctx context.Context, cl client.Client, rlpKey client.ObjectKey, reason gatewayapiv1alpha2.PolicyConditionReason, message string) bool { - p := &kuadrantv1beta2.RateLimitPolicy{} + p := &kuadrantv1beta3.RateLimitPolicy{} if err := cl.Get(ctx, rlpKey, p); err != nil { return false } @@ -369,7 +370,7 @@ func IsAuthPolicyConditionTrue(ctx context.Context, cl client.Client, policy *ku func RLPIsNotAccepted(ctx context.Context, k8sClient client.Client, rlpKey client.ObjectKey) func() bool { return func() bool { - existingRLP := &kuadrantv1beta2.RateLimitPolicy{} + existingRLP := &kuadrantv1beta3.RateLimitPolicy{} err := k8sClient.Get(ctx, rlpKey, existingRLP) if err != nil { logf.Log.V(1).Info("ratelimitpolicy not read", "rlp", rlpKey, "error", err) @@ -672,7 +673,7 @@ func BuildBasicAuthScheme() *kuadrantv1beta2.AuthSchemeSpec { } func IsRLPAcceptedAndEnforced(g Gomega, ctx context.Context, cl client.Client, policyKey client.ObjectKey) { - existingPolicy := &kuadrantv1beta2.RateLimitPolicy{} + existingPolicy := &kuadrantv1beta3.RateLimitPolicy{} g.Expect(cl.Get(ctx, policyKey, existingPolicy)).To(Succeed()) acceptedCond := meta.FindStatusCondition(existingPolicy.Status.Conditions, string(gatewayapiv1alpha2.PolicyConditionAccepted)) diff --git a/tests/envoygateway/envoygateway_limitador_cluster_controller_test.go b/tests/envoygateway/envoygateway_limitador_cluster_controller_test.go index 5c7040343..aad9dab0a 100644 --- a/tests/envoygateway/envoygateway_limitador_cluster_controller_test.go +++ b/tests/envoygateway/envoygateway_limitador_cluster_controller_test.go @@ -20,7 +20,7 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/controllers" "github.com/kuadrant/kuadrant-operator/pkg/common" "github.com/kuadrant/kuadrant-operator/tests" @@ -52,17 +52,17 @@ var _ = Describe("limitador cluster controller", func() { tests.DeleteNamespace(ctx, testClient(), testNamespace) }, afterEachTimeOut) - policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.RateLimitPolicy)) *kuadrantv1beta2.RateLimitPolicy { - policy := &kuadrantv1beta2.RateLimitPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta3.RateLimitPolicy)) *kuadrantv1beta3.RateLimitPolicy { + policy := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "rlp", Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{}, + Spec: kuadrantv1beta3.RateLimitPolicySpec{}, } for _, mutateFn := range mutateFns { @@ -88,7 +88,7 @@ var _ = Describe("limitador cluster controller", func() { Context("RateLimitPolicy attached to the gateway", func() { var ( - gwPolicy *kuadrantv1beta2.RateLimitPolicy + gwPolicy *kuadrantv1beta3.RateLimitPolicy gwRoute *gatewayapiv1.HTTPRoute ) @@ -98,15 +98,15 @@ var _ = Describe("limitador cluster controller", func() { Expect(err).ToNot(HaveOccurred()) Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(gwRoute))).WithContext(ctx).Should(BeTrue()) - gwPolicy = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwPolicy = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "gw" policy.Spec.TargetRef.Group = gatewayapiv1.GroupName policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = TestGatewayName - policy.Spec.Defaults = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Defaults = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: "minute", }, diff --git a/tests/envoygateway/wasm_controller_test.go b/tests/envoygateway/wasm_controller_test.go index 636d8d67d..c786d71a3 100644 --- a/tests/envoygateway/wasm_controller_test.go +++ b/tests/envoygateway/wasm_controller_test.go @@ -17,7 +17,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/controllers" "github.com/kuadrant/kuadrant-operator/pkg/common" "github.com/kuadrant/kuadrant-operator/pkg/rlptools/wasm" @@ -50,17 +50,17 @@ var _ = Describe("wasm controller", func() { tests.DeleteNamespace(ctx, testClient(), testNamespace) }, afterEachTimeOut) - policyFactory := func(mutateFns ...func(policy *kuadrantv1beta2.RateLimitPolicy)) *kuadrantv1beta2.RateLimitPolicy { - policy := &kuadrantv1beta2.RateLimitPolicy{ + policyFactory := func(mutateFns ...func(policy *kuadrantv1beta3.RateLimitPolicy)) *kuadrantv1beta3.RateLimitPolicy { + policy := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: "rlp", Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{}, + Spec: kuadrantv1beta3.RateLimitPolicySpec{}, } for _, mutateFn := range mutateFns { @@ -77,7 +77,7 @@ var _ = Describe("wasm controller", func() { Context("RateLimitPolicy attached to the gateway", func() { var ( - gwPolicy *kuadrantv1beta2.RateLimitPolicy + gwPolicy *kuadrantv1beta3.RateLimitPolicy gwRoute *gatewayapiv1.HTTPRoute ) @@ -87,15 +87,15 @@ var _ = Describe("wasm controller", func() { Expect(err).ToNot(HaveOccurred()) Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(gwRoute))).WithContext(ctx).Should(BeTrue()) - gwPolicy = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + gwPolicy = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "gw" policy.Spec.TargetRef.Group = gatewayapiv1.GroupName policy.Spec.TargetRef.Kind = "Gateway" policy.Spec.TargetRef.Name = TestGatewayName - policy.Spec.Defaults = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Defaults = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: "minute", }, @@ -164,12 +164,12 @@ var _ = Describe("wasm controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -237,7 +237,7 @@ var _ = Describe("wasm controller", func() { Context("RateLimitPolicy attached to the route", func() { var ( - routePolicy *kuadrantv1beta2.RateLimitPolicy + routePolicy *kuadrantv1beta3.RateLimitPolicy gwRoute *gatewayapiv1.HTTPRoute ) @@ -247,15 +247,15 @@ var _ = Describe("wasm controller", func() { Expect(err).ToNot(HaveOccurred()) Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(gwRoute))).WithContext(ctx).Should(BeTrue()) - routePolicy = policyFactory(func(policy *kuadrantv1beta2.RateLimitPolicy) { + routePolicy = policyFactory(func(policy *kuadrantv1beta3.RateLimitPolicy) { policy.Name = "route" policy.Spec.TargetRef.Group = gatewayapiv1.GroupName policy.Spec.TargetRef.Kind = "HTTPRoute" policy.Spec.TargetRef.Name = TestHTTPRouteName - policy.Spec.Defaults = &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + policy.Spec.Defaults = &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { Limit: 1, Duration: 3, Unit: "minute", }, @@ -323,12 +323,12 @@ var _ = Describe("wasm controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, diff --git a/tests/istio/limitador_cluster_envoyfilter_controller_test.go b/tests/istio/limitador_cluster_envoyfilter_controller_test.go index 3de996083..6effe5fec 100644 --- a/tests/istio/limitador_cluster_envoyfilter_controller_test.go +++ b/tests/istio/limitador_cluster_envoyfilter_controller_test.go @@ -18,7 +18,7 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/pkg/common" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" "github.com/kuadrant/kuadrant-operator/tests" @@ -79,27 +79,27 @@ var _ = Describe("Limitador Cluster EnvoyFilter controller", func() { Context("RLP targeting Gateway", func() { It("EnvoyFilter created when RLP exists and deleted with RLP is deleted", func(ctx SpecContext) { // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: rlpName, Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, diff --git a/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go b/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go index 94319b340..4fbd6c8dd 100644 --- a/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go +++ b/tests/istio/rate_limiting_istio_wasmplugin_controller_test.go @@ -19,7 +19,7 @@ import ( gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayapiv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - kuadrantv1beta2 "github.com/kuadrant/kuadrant-operator/api/v1beta2" + kuadrantv1beta3 "github.com/kuadrant/kuadrant-operator/api/v1beta3" "github.com/kuadrant/kuadrant-operator/controllers" "github.com/kuadrant/kuadrant-operator/pkg/common" "github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant" @@ -81,23 +81,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -145,12 +145,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -217,65 +217,40 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ Kind: "RateLimitPolicy", - APIVersion: kuadrantv1beta2.GroupVersion.String(), + APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: rlpName, Namespace: testNamespace, }, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ - "toys": { - Rates: []kuadrantv1beta2.Rate{ - {Limit: 50, Duration: 1, Unit: kuadrantv1beta2.TimeUnit("minute")}, + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ + "users": { + Rates: []kuadrantv1beta3.Rate{ + {Limit: 50, Duration: 1, Unit: kuadrantv1beta3.TimeUnit("minute")}, }, - Counters: []kuadrantv1beta2.ContextSelector{"auth.identity.username"}, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { // selects the 1st HTTPRouteRule (i.e. get|post /toys*) for one of the hostnames - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/toys"), - }, - }, - }, - Hostnames: []gatewayapiv1.Hostname{"*.toystore.acme.com"}, - }, - }, - When: []kuadrantv1beta2.WhenCondition{ + Counters: []kuadrantv1beta3.ContextSelector{"auth.identity.username"}, + When: []kuadrantv1beta3.WhenCondition{ { Selector: "auth.identity.group", - Operator: kuadrantv1beta2.WhenConditionOperator("neq"), + Operator: kuadrantv1beta3.WhenConditionOperator("neq"), Value: "admin", }, }, }, - "assets": { - Rates: []kuadrantv1beta2.Rate{ - {Limit: 5, Duration: 1, Unit: kuadrantv1beta2.TimeUnit("minute")}, - {Limit: 100, Duration: 12, Unit: kuadrantv1beta2.TimeUnit("hour")}, - }, - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { // selects the 2nd HTTPRouteRule (i.e. /assets*) for all hostnames - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/assets"), - }, - }, - }, - }, + "all": { + Rates: []kuadrantv1beta3.Rate{ + {Limit: 5, Duration: 1, Unit: kuadrantv1beta3.TimeUnit("minute")}, + {Limit: 100, Duration: 12, Unit: kuadrantv1beta3.TimeUnit("hour")}, }, }, }, @@ -307,28 +282,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { policy := existingWASMConfig.Policies[0] Expect(policy.Name).To(Equal(rlpKey.String())) Expect(policy.Hostnames).To(Equal([]string{"*.toystore.acme.com", "api.toystore.io"})) - Expect(policy.Rules).To(ContainElement(wasm.Rule{ // rule to activate the 'toys' limit definition + Expect(policy.Rules).To(ContainElement(wasm.Rule{ // rule to activate the 'users' limit definition Conditions: []wasm.Condition{ { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toys", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, - { - Selector: "request.host", - Operator: wasm.PatternOperator(kuadrantv1beta2.EndsWithOperator), - Value: ".toystore.acme.com", - }, { Selector: "auth.identity.group", - Operator: wasm.PatternOperator(kuadrantv1beta2.NotEqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.NotEqualOperator), Value: "admin", }, }, @@ -337,22 +307,31 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toys", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "POST", }, { - Selector: "request.host", - Operator: wasm.PatternOperator(kuadrantv1beta2.EndsWithOperator), - Value: ".toystore.acme.com", + Selector: "auth.identity.group", + Operator: wasm.PatternOperator(kuadrantv1beta3.NotEqualOperator), + Value: "admin", + }, + }, + }, + { + AllOf: []wasm.PatternExpression{ + { + Selector: "request.url_path", + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/assets", }, { Selector: "auth.identity.group", - Operator: wasm.PatternOperator(kuadrantv1beta2.NotEqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.NotEqualOperator), Value: "admin", }, }, @@ -366,7 +345,7 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { { Value: &wasm.Static{ Static: wasm.StaticSpec{ - Key: wasm.LimitNameToLimitadorIdentifier(rlpKey, "toys"), + Key: wasm.LimitNameToLimitadorIdentifier(rlpKey, "users"), Value: "1", }, }, @@ -374,7 +353,7 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { { Value: &wasm.Selector{ Selector: wasm.SelectorSpec{ - Selector: kuadrantv1beta2.ContextSelector("auth.identity.username"), + Selector: kuadrantv1beta3.ContextSelector("auth.identity.username"), }, }, }, @@ -382,13 +361,41 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { }, }, })) - Expect(policy.Rules).To(ContainElement(wasm.Rule{ // rule to activate the 'assets' limit definition + Expect(policy.Rules).To(ContainElement(wasm.Rule{ // rule to activate the 'all' limit definition Conditions: []wasm.Condition{ { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/toys", + }, + { + Selector: "request.method", + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "GET", + }, + }, + }, + { + AllOf: []wasm.PatternExpression{ + { + Selector: "request.url_path", + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), + Value: "/toys", + }, + { + Selector: "request.method", + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), + Value: "POST", + }, + }, + }, + { + AllOf: []wasm.PatternExpression{ + { + Selector: "request.url_path", + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/assets", }, }, @@ -402,7 +409,7 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { { Value: &wasm.Static{ Static: wasm.StaticSpec{ - Key: wasm.LimitNameToLimitadorIdentifier(rlpKey, "assets"), + Key: wasm.LimitNameToLimitadorIdentifier(rlpKey, "all"), Value: "1", }, }, @@ -421,23 +428,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -480,12 +487,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -533,23 +540,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { It("Wasmplugin must not be created", func(ctx SpecContext) { // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -576,281 +583,6 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { }, testTimeOut) }) - Context("RLP targeting HTTPRoute when route selection match is empty", func() { - var ( - routeName = "toystore-route" - rlpName = "toystore-rlp" - TestGatewayName = "toystore-gw" - gateway *gatewayapiv1.Gateway - ) - - beforeEachCallback := func(ctx SpecContext) { - gateway = tests.BuildBasicGateway(TestGatewayName, testNamespace) - err := testClient().Create(ctx, gateway) - Expect(err).ToNot(HaveOccurred()) - Eventually(tests.GatewayIsReady(ctx, testClient(), gateway)).WithContext(ctx).Should(BeTrue()) - } - - BeforeEach(beforeEachCallback) - - It("When the gateway does not have more policies, the wasmplugin resource is not created", func(ctx SpecContext) { - // create httproute - httpRoute := tests.BuildBasicHttpRoute(routeName, TestGatewayName, testNamespace, []string{"*.example.com"}) - err := testClient().Create(ctx, httpRoute) - Expect(err).ToNot(HaveOccurred()) - Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) - - // create ratelimitpolicy with no matching routes - rlp := &kuadrantv1beta2.RateLimitPolicy{ - TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ - Group: gatewayapiv1.GroupName, - Kind: "HTTPRoute", - Name: gatewayapiv1.ObjectName(routeName), - }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ - "l1": { - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { // does no select any HTTPRouteRule (i.e. GET /toys*) - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/other"), - }, - }, - }, - }, - }, - Rates: []kuadrantv1beta2.Rate{ - { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), - }, - }, - }, - }, - }, - }, - } - err = testClient().Create(ctx, rlp) - Expect(err).ToNot(HaveOccurred()) - - // Check RLP status is available - rlpKey := client.ObjectKeyFromObject(rlp) - Eventually(assertPolicyIsAcceptedAndEnforced(ctx, rlpKey)).WithContext(ctx).Should(BeTrue()) - - // Check wasm plugin - wasmPluginKey := client.ObjectKey{Name: controllers.WASMPluginName(gateway), Namespace: testNamespace} - // Wait a bit to catch cases where wasmplugin is created and takes a bit to be created - Eventually(tests.WasmPluginIsAvailable(ctx, testClient(), wasmPluginKey), 20*time.Second, 5*time.Second).Should(BeFalse()) - existingWasmPlugin := &istioclientgoextensionv1alpha1.WasmPlugin{} - // must not exist - err = testClient().Get(ctx, wasmPluginKey, existingWasmPlugin) - Expect(apierrors.IsNotFound(err)).To(BeTrue()) - }, testTimeOut) - - It("When the gateway has more policies, the wasmplugin resource does not have any configuration regarding the current RLP", func(ctx SpecContext) { - // Gw A - // Route B -> Gw A - // RLP A -> Gw A - // Route C -> GW A - // RLP B -> Route C (however, no matching routes) - - var ( - routeBName = "toystore-b" - routeCName = "toystore-c" - rlpAName = "toystore-a" - rlpBName = "toystore-b" - ) - - // create httproute B - httpRouteB := tests.BuildBasicHttpRoute(routeBName, TestGatewayName, testNamespace, []string{"*.b.example.com"}) - err := testClient().Create(ctx, httpRouteB) - Expect(err).ToNot(HaveOccurred()) - Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteB))).WithContext(ctx).Should(BeTrue()) - - // create RLP A -> Gw A - rlpA := &kuadrantv1beta2.RateLimitPolicy{ - TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{Name: rlpAName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ - Group: gatewayapiv1.GroupName, - Kind: "Gateway", - Name: gatewayapiv1.ObjectName(TestGatewayName), - }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ - "l1": { - Rates: []kuadrantv1beta2.Rate{ - { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), - }, - }, - }, - }, - }, - }, - } - err = testClient().Create(ctx, rlpA) - Expect(err).ToNot(HaveOccurred()) - - // Check RLP status is available - rlpAKey := client.ObjectKey{Name: rlpAName, Namespace: testNamespace} - Eventually(assertPolicyIsAcceptedAndEnforced(ctx, rlpAKey)).WithContext(ctx).Should(BeTrue()) - - // create httproute C - httpRouteC := tests.BuildBasicHttpRoute(routeCName, TestGatewayName, testNamespace, []string{"*.c.example.com"}) - httpRouteC.Spec.Rules = []gatewayapiv1.HTTPRouteRule{ - { - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/otherPathRouteC"), - }, - Method: ptr.To(gatewayapiv1.HTTPMethod("GET")), - }, - }, - }, - } - - err = testClient().Create(ctx, httpRouteC) - Expect(err).ToNot(HaveOccurred()) - Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteC))).WithContext(ctx).Should(BeTrue()) - - // create RLP B -> Route C (however, no matching routes) - rlpB := &kuadrantv1beta2.RateLimitPolicy{ - TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{Name: rlpBName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ - TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ - Group: gatewayapiv1.GroupName, - Kind: "HTTPRoute", - Name: gatewayapiv1.ObjectName(routeCName), - }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ - "l1": { - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { // does no select any HTTPRouteRule (i.e. GET /otherPathRouteC*) - Matches: []gatewayapiv1.HTTPRouteMatch{ - { - Path: &gatewayapiv1.HTTPPathMatch{ - Type: ptr.To(gatewayapiv1.PathMatchPathPrefix), - Value: ptr.To("/notmatchingpath"), - }, - }, - }, - }, - }, - Rates: []kuadrantv1beta2.Rate{ - { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), - }, - }, - }, - }, - }, - }, - } - err = testClient().Create(ctx, rlpB) - Expect(err).ToNot(HaveOccurred()) - - // Check RLP status is available - rlpBKey := client.ObjectKey{Name: rlpBName, Namespace: testNamespace} - Eventually(assertPolicyIsAcceptedAndEnforced(ctx, rlpBKey)).WithContext(ctx).Should(BeTrue()) - - // Check wasm plugin only has configuration ONLY from the RLP targeting the gateway - // it may take some reconciliation loops to get to that, so checking it with eventually - Eventually(func() bool { - wasmPluginKey := client.ObjectKey{ - Name: controllers.WASMPluginName(gateway), Namespace: testNamespace, - } - existingWasmPlugin := &istioclientgoextensionv1alpha1.WasmPlugin{} - err := testClient().Get(ctx, wasmPluginKey, existingWasmPlugin) - if err != nil { - logf.Log.V(1).Info("wasmplugin not read", "key", wasmPluginKey, "error", err) - return false - } - existingWASMConfig, err := wasm.ConfigFromStruct(existingWasmPlugin.Spec.PluginConfig) - if err != nil { - logf.Log.V(1).Info("wasmplugin could not be deserialized", "key", wasmPluginKey, "error", err) - return false - } - - expectedPlugin := &wasm.Config{ - Extensions: map[string]wasm.Extension{ - wasm.RateLimitPolicyExtensionName: { - Endpoint: common.KuadrantRateLimitClusterName, - FailureMode: wasm.FailureModeAllow, - Type: wasm.RateLimitExtensionType, - }, - }, - Policies: []wasm.Policy{ - { - Name: rlpAKey.String(), - Hostnames: []string{"*"}, - Rules: []wasm.Rule{ - { - Conditions: []wasm.Condition{ - { - AllOf: []wasm.PatternExpression{ - { - Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), - Value: "/toy", - }, - { - Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), - Value: "GET", - }, - }, - }, - }, - Actions: []wasm.Action{ - { - Scope: wasm.LimitsNamespaceFromRLP(rlpA), - ExtensionName: wasm.RateLimitPolicyExtensionName, - Data: []wasm.DataType{ - { - Value: &wasm.Static{ - Static: wasm.StaticSpec{ - Key: wasm.LimitNameToLimitadorIdentifier(rlpAKey, "l1"), - Value: "1", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - if !reflect.DeepEqual(existingWASMConfig, expectedPlugin) { - diff := cmp.Diff(existingWASMConfig, expectedPlugin) - logf.Log.V(1).Info("wasmplugin does not match", "key", wasmPluginKey, "diff", diff) - return false - } - - return true - }).WithContext(ctx).Should(BeTrue()) - }, testTimeOut) - }) - Context("HTTPRoute switches parentship from one gateway to another", func() { var ( routeName = "route-a" @@ -885,23 +617,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { // Gw A will be the pre-existing $gateway with name $TestGatewayName // create RLP A -> Gw A - rlpA := &kuadrantv1beta2.RateLimitPolicy{ + rlpA := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -967,12 +699,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1106,23 +838,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create RLP A -> Route A - rlpA := &kuadrantv1beta2.RateLimitPolicy{ + rlpA := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -1174,12 +906,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1302,12 +1034,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1427,23 +1159,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { // // create RLP R -> Route A // - rlpR := &kuadrantv1beta2.RateLimitPolicy{ + rlpR := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeAName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -1495,12 +1227,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeA", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1541,7 +1273,7 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { // From RLP R -> Route A // To RLP R -> Route B Eventually(func(g Gomega) { - rlpUpdated := &kuadrantv1beta2.RateLimitPolicy{} + rlpUpdated := &kuadrantv1beta3.RateLimitPolicy{} err = testClient().Get(ctx, client.ObjectKeyFromObject(rlpR), rlpUpdated) g.Expect(err).ToNot(HaveOccurred()) rlpUpdated.Spec.TargetRef.Name = gatewayapiv1.ObjectName(routeBName) @@ -1586,12 +1318,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeB", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1686,23 +1418,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteA))).WithContext(ctx).Should(BeTrue()) // create RLP 1 -> Gw A - rlp1 := &kuadrantv1beta2.RateLimitPolicy{ + rlp1 := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlp1Name, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "gatewaylimit": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -1754,12 +1486,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeA", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1802,23 +1534,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { // // create RLP 2 -> Route A // - rlp2 := &kuadrantv1beta2.RateLimitPolicy{ + rlp2 := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlp2Name, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeAName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "routelimit": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 4, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 4, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -1870,12 +1602,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeA", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -1973,23 +1705,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRouteA))).WithContext(ctx).Should(BeTrue()) // create RLP 1 -> Gw A - rlp1 := &kuadrantv1beta2.RateLimitPolicy{ + rlp1 := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlp1Name, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "gatewaylimit": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -2004,23 +1736,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(assertPolicyIsAcceptedAndEnforced(ctx, rlp1Key)).WithContext(ctx).Should(BeTrue()) // create RLP 2 -> Route A - rlp2 := &kuadrantv1beta2.RateLimitPolicy{ + rlp2 := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlp2Name, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeAName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "routelimit": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 4, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 4, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -2072,12 +1804,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeA", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -2178,12 +1910,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeB", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -2218,12 +1950,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/routeA", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -2291,31 +2023,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create ratelimitpolicy - rlp := &kuadrantv1beta2.RateLimitPolicy{ + rlp := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: rlpName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "l1": { - RouteSelectors: []kuadrantv1beta2.RouteSelector{ - { - // Route does not specify any hostname - // gateway's listener specifies *.gw.example.com - Hostnames: []gatewayapiv1.Hostname{"*.gw.example.com"}, - }, - }, - - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -2358,12 +2082,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -2409,7 +2133,7 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.GatewayIsReady(ctx, testClient(), gateway)).WithContext(ctx).Should(BeTrue()) } - expectedWasmPluginConfig := func(rlpKey client.ObjectKey, rlp *kuadrantv1beta2.RateLimitPolicy, key, hostname string) *wasm.Config { + expectedWasmPluginConfig := func(rlpKey client.ObjectKey, rlp *kuadrantv1beta3.RateLimitPolicy, key, hostname string) *wasm.Config { return &wasm.Config{ Extensions: map[string]wasm.Extension{ wasm.RateLimitPolicyExtensionName: { @@ -2429,12 +2153,12 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { AllOf: []wasm.PatternExpression{ { Selector: "request.url_path", - Operator: wasm.PatternOperator(kuadrantv1beta2.StartsWithOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.StartsWithOperator), Value: "/toy", }, { Selector: "request.method", - Operator: wasm.PatternOperator(kuadrantv1beta2.EqualOperator), + Operator: wasm.PatternOperator(kuadrantv1beta3.EqualOperator), Value: "GET", }, }, @@ -2472,23 +2196,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Eventually(tests.RouteIsAccepted(ctx, testClient(), client.ObjectKeyFromObject(httpRoute))).WithContext(ctx).Should(BeTrue()) // create GW ratelimitpolicy with defaults - gwRLP := &kuadrantv1beta2.RateLimitPolicy{ + gwRLP := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: gwRLPName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "Gateway", Name: gatewayapiv1.ObjectName(TestGatewayName), }, - Defaults: &kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + Defaults: &kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "gateway": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 1, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 1, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, }, @@ -2513,23 +2237,23 @@ var _ = Describe("Rate Limiting WasmPlugin controller", func() { Expect(existingWASMConfig).To(Equal(expectedWasmPluginConfig(gwRLPKey, gwRLP, wasm.LimitNameToLimitadorIdentifier(gwRLPKey, "gateway"), "*"))) // Create Route RLP - routeRLP := &kuadrantv1beta2.RateLimitPolicy{ + routeRLP := &kuadrantv1beta3.RateLimitPolicy{ TypeMeta: metav1.TypeMeta{ - Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta2.GroupVersion.String(), + Kind: "RateLimitPolicy", APIVersion: kuadrantv1beta3.GroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{Name: routeRLPName, Namespace: testNamespace}, - Spec: kuadrantv1beta2.RateLimitPolicySpec{ + Spec: kuadrantv1beta3.RateLimitPolicySpec{ TargetRef: gatewayapiv1alpha2.LocalPolicyTargetReference{ Group: gatewayapiv1.GroupName, Kind: "HTTPRoute", Name: gatewayapiv1.ObjectName(routeName), }, - RateLimitPolicyCommonSpec: kuadrantv1beta2.RateLimitPolicyCommonSpec{ - Limits: map[string]kuadrantv1beta2.Limit{ + RateLimitPolicyCommonSpec: kuadrantv1beta3.RateLimitPolicyCommonSpec{ + Limits: map[string]kuadrantv1beta3.Limit{ "route": { - Rates: []kuadrantv1beta2.Rate{ + Rates: []kuadrantv1beta3.Rate{ { - Limit: 10, Duration: 3, Unit: kuadrantv1beta2.TimeUnit("minute"), + Limit: 10, Duration: 3, Unit: kuadrantv1beta3.TimeUnit("minute"), }, }, },