Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/v1alpha1/ratelimit_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type LocalRateLimit struct {
//
// +optional
// +kubebuilder:validation:MaxItems=16
// +kubebuilder:validation:XValidation:rule="self.all(r, r.limit.requests > 0)", message="requests must be greater than 0 for local rate limits"
// +kubebuilder:validation:XValidation:rule="self.all(r, !has(r.cost) || !has(r.cost.response))", message="response cost is not supported for Local Rate Limits"
// +kubebuilder:validation:XValidation:rule="self.all(r, !has(r.limit.fromMetadata))", message="limit fromMetadata is not supported for Local Rate Limits"
Rules []RateLimitRule `json:"rules"`
Expand Down Expand Up @@ -436,7 +437,7 @@ type RateLimitValue struct {
// Requests is the number of requests (or cost units, when used with
// cost-based rate limiting) allowed per Unit.
//
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=4294967295
// +kubebuilder:validation:Format=uint32
Requests uint32 `json:"requests"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1829,7 +1829,7 @@ spec:
cost-based rate limiting) allowed per Unit.
format: uint32
maximum: 4294967295
minimum: 1
minimum: 0
type: integer
unit:
description: |-
Expand Down Expand Up @@ -2240,7 +2240,7 @@ spec:
cost-based rate limiting) allowed per Unit.
format: uint32
maximum: 4294967295
minimum: 1
minimum: 0
type: integer
unit:
description: |-
Expand Down Expand Up @@ -2288,6 +2288,9 @@ spec:
maxItems: 16
type: array
x-kubernetes-validations:
- message: requests must be greater than 0 for local rate
limits
rule: self.all(r, r.limit.requests > 0)
- message: response cost is not supported for Local Rate Limits
rule: self.all(r, !has(r.cost) || !has(r.cost.response))
- message: limit fromMetadata is not supported for Local Rate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1828,7 +1828,7 @@ spec:
cost-based rate limiting) allowed per Unit.
format: uint32
maximum: 4294967295
minimum: 1
minimum: 0
type: integer
unit:
description: |-
Expand Down Expand Up @@ -2239,7 +2239,7 @@ spec:
cost-based rate limiting) allowed per Unit.
format: uint32
maximum: 4294967295
minimum: 1
minimum: 0
type: integer
unit:
description: |-
Expand Down Expand Up @@ -2287,6 +2287,9 @@ spec:
maxItems: 16
type: array
x-kubernetes-validations:
- message: requests must be greater than 0 for local rate
limits
rule: self.all(r, r.limit.requests > 0)
- message: response cost is not supported for Local Rate Limits
rule: self.all(r, !has(r.cost) || !has(r.cost.response))
- message: limit fromMetadata is not supported for Local Rate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed BackendTrafficPolicy global rate limits rejecting `requests: 0`, allowing zero-request global rules to block matching traffic while local zero limits remain rejected.
68 changes: 61 additions & 7 deletions test/cel-validation/backendtrafficpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1936,7 +1936,7 @@ func TestBackendTrafficPolicyTarget(t *testing.T) {
wantErrors: []string{},
},
{
desc: "rate limit requests of zero is rejected",
desc: "rate limit requests of one is accepted",
mutate: func(btp *egv1a1.BackendTrafficPolicy) {
btp.Spec = egv1a1.BackendTrafficPolicySpec{
PolicyTargetReferences: egv1a1.PolicyTargetReferences{
Expand All @@ -1953,7 +1953,7 @@ func TestBackendTrafficPolicyTarget(t *testing.T) {
Rules: []egv1a1.RateLimitRule{
{
Limit: egv1a1.RateLimitValue{
Requests: 0,
Requests: 1,
Unit: "Minute",
},
},
Expand All @@ -1962,10 +1962,36 @@ func TestBackendTrafficPolicyTarget(t *testing.T) {
},
}
},
wantErrors: []string{
"spec.ratelimit.global.rules[0].limit.requests",
"should be greater than or equal to 1",
wantErrors: []string{},
},
{
desc: "global rate limit requests of zero is accepted",
mutate: func(btp *egv1a1.BackendTrafficPolicy) {
btp.Spec = egv1a1.BackendTrafficPolicySpec{
PolicyTargetReferences: egv1a1.PolicyTargetReferences{
TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{
LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{
Group: gwapiv1.Group("gateway.networking.k8s.io"),
Kind: gwapiv1.Kind("Gateway"),
Name: gwapiv1.ObjectName("eg"),
},
},
},
RateLimit: &egv1a1.RateLimitSpec{
Global: &egv1a1.GlobalRateLimit{
Rules: []egv1a1.RateLimitRule{
{
Limit: egv1a1.RateLimitValue{
Requests: 0,
Unit: "Minute",
},
},
},
},
},
}
},
wantErrors: []string{},
},
{
desc: "local rate limit requests at uint32 max boundary is accepted",
Expand Down Expand Up @@ -1996,6 +2022,35 @@ func TestBackendTrafficPolicyTarget(t *testing.T) {
},
wantErrors: []string{},
},
{
desc: "local rate limit requests of one is accepted",
mutate: func(btp *egv1a1.BackendTrafficPolicy) {
btp.Spec = egv1a1.BackendTrafficPolicySpec{
PolicyTargetReferences: egv1a1.PolicyTargetReferences{
TargetRef: &gwapiv1.LocalPolicyTargetReferenceWithSectionName{
LocalPolicyTargetReference: gwapiv1.LocalPolicyTargetReference{
Group: gwapiv1.Group("gateway.networking.k8s.io"),
Kind: gwapiv1.Kind("Gateway"),
Name: gwapiv1.ObjectName("eg"),
},
},
},
RateLimit: &egv1a1.RateLimitSpec{
Local: &egv1a1.LocalRateLimit{
Rules: []egv1a1.RateLimitRule{
{
Limit: egv1a1.RateLimitValue{
Requests: 1,
Unit: "Minute",
},
},
},
},
},
}
},
wantErrors: []string{},
},
{
desc: "local rate limit requests of zero is rejected",
mutate: func(btp *egv1a1.BackendTrafficPolicy) {
Expand Down Expand Up @@ -2024,8 +2079,7 @@ func TestBackendTrafficPolicyTarget(t *testing.T) {
}
},
wantErrors: []string{
"spec.ratelimit.local.rules[0].limit.requests",
"should be greater than or equal to 1",
"requests must be greater than 0 for local rate limits",
},
},
{
Expand Down
Loading