diff --git a/api/v1alpha1/quota_policy.go b/api/v1alpha1/quota_policy.go index ea4db7175c..3fd8a3bf89 100644 --- a/api/v1alpha1/quota_policy.go +++ b/api/v1alpha1/quota_policy.go @@ -165,9 +165,9 @@ type QuotaRule struct { type QuotaValue struct { // The limit alloted for a specified time window. Limit uint `json:"limit"` - // Time window. Must be exactly one of: "1s" (1 second), "1m" (1 minute), "1h" (1 hour), or "1d" (1 day). + // Time window. Must be exactly one of: "1s" (1 second), "1m" (1 minute), "1h" (1 hour), "1d" (1 day), "1w" (1 week), "1mo" (1 month), or "1y" (1 year). // - // +kubebuilder:validation:Enum="1s";"1m";"1h";"1d" + // +kubebuilder:validation:Enum="1s";"1m";"1h";"1d";"1w";"1mo";"1y" Duration string `json:"duration"` } diff --git a/internal/ratelimit/translator/translator.go b/internal/ratelimit/translator/translator.go index 5df319421b..88abbb50e2 100644 --- a/internal/ratelimit/translator/translator.go +++ b/internal/ratelimit/translator/translator.go @@ -400,7 +400,7 @@ func quotaValueToPolicy(qv *aigv1a1.QuotaValue) (*rlsconfv3.RateLimitPolicy, err }, nil } -// parseDuration accepts exactly "1s", "1m", "1h", or "1d". +// parseDuration accepts exactly "1s", "1m", "1h", "1d", "1w", "1mo", or "1y". func parseDuration(s string) (rlsconfv3.RateLimitUnit, error) { switch s { case "1s": @@ -411,8 +411,14 @@ func parseDuration(s string) (rlsconfv3.RateLimitUnit, error) { return rlsconfv3.RateLimitUnit_HOUR, nil case "1d": return rlsconfv3.RateLimitUnit_DAY, nil + case "1w": + return rlsconfv3.RateLimitUnit_WEEK, nil + case "1mo": + return rlsconfv3.RateLimitUnit_MONTH, nil + case "1y": + return rlsconfv3.RateLimitUnit_YEAR, nil default: - return 0, fmt.Errorf("unsupported duration %q: must be one of 1s, 1m, 1h", s) + return 0, fmt.Errorf("unsupported duration %q: must be one of 1s, 1m, 1h, 1d, 1w, 1mo, 1y", s) } } diff --git a/internal/ratelimit/translator/translator_test.go b/internal/ratelimit/translator/translator_test.go index ee6b8f8116..ea930f6a57 100644 --- a/internal/ratelimit/translator/translator_test.go +++ b/internal/ratelimit/translator/translator_test.go @@ -69,6 +69,10 @@ func TestParseDuration(t *testing.T) { {"1 second", "1s", rlsconfv3.RateLimitUnit_SECOND, false}, {"1 minute", "1m", rlsconfv3.RateLimitUnit_MINUTE, false}, {"1 hour", "1h", rlsconfv3.RateLimitUnit_HOUR, false}, + {"1 day", "1d", rlsconfv3.RateLimitUnit_DAY, false}, + {"1 week", "1w", rlsconfv3.RateLimitUnit_WEEK, false}, + {"1 month", "1mo", rlsconfv3.RateLimitUnit_MONTH, false}, + {"1 year", "1y", rlsconfv3.RateLimitUnit_YEAR, false}, {"30 seconds rejected", "30s", 0, true}, {"5 minutes rejected", "5m", 0, true}, {"2 hours rejected", "2h", 0, true}, diff --git a/manifests/charts/ai-gateway-crds-helm/templates/aigateway.envoyproxy.io_quotapolicies.yaml b/manifests/charts/ai-gateway-crds-helm/templates/aigateway.envoyproxy.io_quotapolicies.yaml index 6250bd161e..caf043ebb1 100644 --- a/manifests/charts/ai-gateway-crds-helm/templates/aigateway.envoyproxy.io_quotapolicies.yaml +++ b/manifests/charts/ai-gateway-crds-helm/templates/aigateway.envoyproxy.io_quotapolicies.yaml @@ -293,12 +293,16 @@ spec: duration: description: 'Time window. Must be exactly one of: "1s" (1 second), "1m" (1 minute), "1h" (1 - hour), or "1d" (1 day).' + hour), "1d" (1 day), "1w" (1 week), "1mo" (1 + month), or "1y" (1 year).' enum: - 1s - 1m - 1h - 1d + - 1w + - 1mo + - 1y type: string limit: description: The limit alloted for a specified @@ -334,13 +338,16 @@ spec: properties: duration: description: 'Time window. Must be exactly one of: "1s" - (1 second), "1m" (1 minute), "1h" (1 hour), or "1d" - (1 day).' + (1 second), "1m" (1 minute), "1h" (1 hour), "1d" (1 + day), "1w" (1 week), "1mo" (1 month), or "1y" (1 year).' enum: - 1s - 1m - 1h - 1d + - 1w + - 1mo + - 1y type: string limit: description: The limit alloted for a specified time @@ -390,12 +397,16 @@ spec: properties: duration: description: 'Time window. Must be exactly one of: "1s" (1 - second), "1m" (1 minute), "1h" (1 hour), or "1d" (1 day).' + second), "1m" (1 minute), "1h" (1 hour), "1d" (1 day), "1w" + (1 week), "1mo" (1 month), or "1y" (1 year).' enum: - 1s - 1m - 1h - 1d + - 1w + - 1mo + - 1y type: string limit: description: The limit alloted for a specified time window. diff --git a/site/docs/api/api.mdx b/site/docs/api/api.mdx index 03621506b7..2bd44fb887 100644 --- a/site/docs/api/api.mdx +++ b/site/docs/api/api.mdx @@ -2580,7 +2580,7 @@ QuotaValue defines the quota limits using sliding window. name="duration" type="string" required="true" - description="Time window. Must be exactly one of: `1s` (1 second), `1m` (1 minute), `1h` (1 hour), or `1d` (1 day)." + description="Time window. Must be exactly one of: `1s` (1 second), `1m` (1 minute), `1h` (1 hour), `1d` (1 day), `1w` (1 week), `1mo` (1 month), or `1y` (1 year)." /> diff --git a/site/docs/capabilities/traffic/quota-policy.md b/site/docs/capabilities/traffic/quota-policy.md index ee7f54c78f..a9f3a45607 100644 --- a/site/docs/capabilities/traffic/quota-policy.md +++ b/site/docs/capabilities/traffic/quota-policy.md @@ -287,12 +287,15 @@ Shadow mode is configured per bucket rule. It cannot be set on the `defaultBucke The `duration` field selects the sliding-window size. It must be exactly one of the following values: -| Value | Window | -| ------ | ---------- | -| `"1s"` | One second | -| `"1m"` | One minute | -| `"1h"` | One hour | -| `"1d"` | One day | +| Value | Window | +| ------- | ---------- | +| `"1s"` | One second | +| `"1m"` | One minute | +| `"1h"` | One hour | +| `"1d"` | One day | +| `"1w"` | One week | +| `"1mo"` | One month | +| `"1y"` | One year | The window is fixed-size — arbitrary multiples such as `"30s"` or `"15m"` are **not** valid and will be rejected by the CRD schema. Choose the `limit` to express your budget within one of these windows.