Skip to content

Commit 49153aa

Browse files
committed
removed the duplicate rate-limit structs from pkg/vmcp/config
Signed-off-by: Sanskarzz <sanskar.gur@gmail.com>
1 parent d4813e8 commit 49153aa

15 files changed

Lines changed: 376 additions & 509 deletions

File tree

cmd/thv-operator/Taskfile.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ tasks:
168168
platforms: [windows]
169169
ignore_error: true # Windows has no mkdir -p, so just ignore error if it exists
170170
- go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.17.3
171-
- $(go env GOPATH)/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./cmd/thv-operator/..." paths="./pkg/json/..." paths="./pkg/vmcp/config/..." paths="./pkg/vmcp/auth/types/..." paths="./pkg/telemetry/..." paths="./pkg/audit/..."
171+
- $(go env GOPATH)/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./cmd/thv-operator/..." paths="./pkg/json/..." paths="./pkg/ratelimit/types/..." paths="./pkg/vmcp/config/..." paths="./pkg/vmcp/auth/types/..." paths="./pkg/telemetry/..." paths="./pkg/audit/..."
172172

173173
operator-manifests:
174174
desc: Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects
@@ -286,6 +286,7 @@ tasks:
286286
sources:
287287
- '{{.ROOT_DIR}}/cmd/thv-operator/config/crd/bases/**/*.yaml'
288288
- '{{.ROOT_DIR}}/cmd/thv-operator/api/**/*.go'
289+
- '{{.ROOT_DIR}}/pkg/ratelimit/types/*.go'
289290
- '{{.ROOT_DIR}}/pkg/vmcp/config/*.go'
290291
- '{{.ROOT_DIR}}/pkg/vmcp/auth/types/*.go'
291292
- '{{.ROOT_DIR}}/pkg/telemetry/*.go'

cmd/thv-operator/api/v1beta1/mcpserver_types.go

Lines changed: 9 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
corev1 "k8s.io/api/core/v1"
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"k8s.io/apimachinery/pkg/runtime"
10+
11+
ratelimittypes "github.com/stacklok/toolhive/pkg/ratelimit/types"
1012
)
1113

1214
// Condition types for MCPServer
@@ -373,7 +375,7 @@ type MCPServerSpec struct {
373375
// RateLimiting defines rate limiting configuration for the MCP server.
374376
// Requires Redis session storage to be configured for distributed rate limiting.
375377
// +optional
376-
RateLimiting *RateLimitConfig `json:"rateLimiting,omitempty"`
378+
RateLimiting *ratelimittypes.RateLimitConfig `json:"rateLimiting,omitempty"`
377379
}
378380

379381
// ResourceOverrides defines overrides for annotations and labels on created resources
@@ -525,69 +527,17 @@ type SessionStorageConfig struct {
525527
}
526528

527529
// RateLimitConfig defines rate limiting configuration for an MCP server.
528-
// At least one of shared, perUser, or tools must be configured.
529-
//
530-
// +kubebuilder:validation:XValidation:rule="has(self.shared) || has(self.perUser) || (has(self.tools) && size(self.tools) > 0)",message="at least one of shared, perUser, or tools must be configured"
531-
//
532-
//nolint:lll // kubebuilder marker exceeds line length
533-
type RateLimitConfig struct {
534-
// Shared is a token bucket shared across all users for the entire server.
535-
// +optional
536-
Shared *RateLimitBucket `json:"shared,omitempty" yaml:"shared,omitempty"`
537-
538-
// PerUser is a token bucket applied independently to each authenticated user
539-
// at the server level. Requires authentication to be enabled.
540-
// Each unique userID creates Redis keys that expire after 2x refillPeriod.
541-
// Memory formula: unique_users_per_TTL_window * (1 + num_tools_with_per_user_limits) keys.
542-
// +optional
543-
PerUser *RateLimitBucket `json:"perUser,omitempty" yaml:"perUser,omitempty"`
544-
545-
// Tools defines per-tool rate limit overrides.
546-
// Each entry applies additional rate limits to calls targeting a specific tool name.
547-
// A request must pass both the server-level limit and the per-tool limit.
548-
// +listType=map
549-
// +listMapKey=name
550-
// +optional
551-
Tools []ToolRateLimitConfig `json:"tools,omitempty" yaml:"tools,omitempty"`
552-
}
530+
// +gendoc
531+
type RateLimitConfig = ratelimittypes.RateLimitConfig
553532

554533
// RateLimitBucket defines a token bucket configuration with a maximum capacity
555534
// and a refill period. Used by both shared and per-user rate limits.
556-
type RateLimitBucket struct {
557-
// MaxTokens is the maximum number of tokens (bucket capacity).
558-
// This is also the burst size: the maximum number of requests that can be served
559-
// instantaneously before the bucket is depleted.
560-
// +kubebuilder:validation:Required
561-
// +kubebuilder:validation:Minimum=1
562-
MaxTokens int32 `json:"maxTokens" yaml:"maxTokens"`
563-
564-
// RefillPeriod is the duration to fully refill the bucket from zero to maxTokens.
565-
// The effective refill rate is maxTokens / refillPeriod tokens per second.
566-
// Format: Go duration string (e.g., "1m0s", "30s", "1h0m0s").
567-
// +kubebuilder:validation:Required
568-
RefillPeriod metav1.Duration `json:"refillPeriod" yaml:"refillPeriod"`
569-
}
535+
// +gendoc
536+
type RateLimitBucket = ratelimittypes.RateLimitBucket
570537

571538
// ToolRateLimitConfig defines rate limits for a specific tool.
572-
// At least one of shared or perUser must be configured.
573-
//
574-
// +kubebuilder:validation:XValidation:rule="has(self.shared) || has(self.perUser)",message="at least one of shared or perUser must be configured"
575-
//
576-
//nolint:lll // kubebuilder marker exceeds line length
577-
type ToolRateLimitConfig struct {
578-
// Name is the MCP tool name this limit applies to.
579-
// +kubebuilder:validation:Required
580-
// +kubebuilder:validation:MinLength=1
581-
Name string `json:"name" yaml:"name"`
582-
583-
// Shared token bucket for this specific tool.
584-
// +optional
585-
Shared *RateLimitBucket `json:"shared,omitempty" yaml:"shared,omitempty"`
586-
587-
// PerUser token bucket configuration for this tool.
588-
// +optional
589-
PerUser *RateLimitBucket `json:"perUser,omitempty" yaml:"perUser,omitempty"`
590-
}
539+
// +gendoc
540+
type ToolRateLimitConfig = ratelimittypes.ToolRateLimitConfig
591541

592542
// Permission profile types
593543
const (

cmd/thv-operator/api/v1beta1/mcpserver_types_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,16 @@ func TestVirtualMCPServerSpecRateLimitingJSONRoundtrip(t *testing.T) {
129129
Address: "redis.default.svc.cluster.local:6379",
130130
},
131131
Config: vmcpconfig.Config{
132-
RateLimiting: &vmcpconfig.RateLimitConfig{
133-
Shared: &vmcpconfig.RateLimitBucket{MaxTokens: 10, RefillPeriod: metav1.Duration{Duration: time.Minute}},
134-
PerUser: &vmcpconfig.RateLimitBucket{
132+
RateLimiting: &RateLimitConfig{
133+
Shared: &RateLimitBucket{MaxTokens: 10, RefillPeriod: metav1.Duration{Duration: time.Minute}},
134+
PerUser: &RateLimitBucket{
135135
MaxTokens: 2,
136136
RefillPeriod: metav1.Duration{Duration: time.Minute},
137137
},
138-
Tools: []vmcpconfig.ToolRateLimitConfig{
138+
Tools: []ToolRateLimitConfig{
139139
{
140140
Name: "backend_a_echo",
141-
Shared: &vmcpconfig.RateLimitBucket{
141+
Shared: &RateLimitBucket{
142142
MaxTokens: 5,
143143
RefillPeriod: metav1.Duration{Duration: 30 * time.Second},
144144
},

cmd/thv-operator/api/v1beta1/zz_generated.deepcopy.go

Lines changed: 2 additions & 74 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/thv-operator/pkg/vmcpconfig/converter_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,15 +1612,15 @@ func TestConverter_RateLimitingPassThrough(t *testing.T) {
16121612
Spec: mcpv1beta1.VirtualMCPServerSpec{
16131613
GroupRef: &mcpv1beta1.MCPGroupRef{Name: "test-group"},
16141614
Config: vmcpconfig.Config{
1615-
RateLimiting: &vmcpconfig.RateLimitConfig{
1616-
PerUser: &vmcpconfig.RateLimitBucket{
1615+
RateLimiting: &mcpv1beta1.RateLimitConfig{
1616+
PerUser: &mcpv1beta1.RateLimitBucket{
16171617
MaxTokens: 2,
16181618
RefillPeriod: metav1.Duration{Duration: time.Minute},
16191619
},
1620-
Tools: []vmcpconfig.ToolRateLimitConfig{
1620+
Tools: []mcpv1beta1.ToolRateLimitConfig{
16211621
{
16221622
Name: "backend_a_echo",
1623-
Shared: &vmcpconfig.RateLimitBucket{
1623+
Shared: &mcpv1beta1.RateLimitBucket{
16241624
MaxTokens: 5,
16251625
RefillPeriod: metav1.Duration{Duration: 30 * time.Second},
16261626
},

cmd/thv-operator/test-integration/virtualmcp/virtualmcpserver_sessionstorage_cel_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ var _ = Describe("CEL Validation for SessionStorageConfig on VirtualMCPServer",
112112
Context("rateLimiting", func() {
113113
It("should reject rate limiting without redis session storage", func() {
114114
vmcp := newVirtualMCPServerWithSessionStorage("vmcp-rl-no-redis", nil)
115-
vmcp.Spec.Config.RateLimiting = &vmcpconfig.RateLimitConfig{
116-
Shared: &vmcpconfig.RateLimitBucket{
115+
vmcp.Spec.Config.RateLimiting = &mcpv1beta1.RateLimitConfig{
116+
Shared: &mcpv1beta1.RateLimitBucket{
117117
MaxTokens: 1,
118118
RefillPeriod: metav1.Duration{Duration: time.Minute},
119119
},
@@ -129,8 +129,8 @@ var _ = Describe("CEL Validation for SessionStorageConfig on VirtualMCPServer",
129129
Provider: "redis",
130130
Address: "redis:6379",
131131
})
132-
vmcp.Spec.Config.RateLimiting = &vmcpconfig.RateLimitConfig{
133-
PerUser: &vmcpconfig.RateLimitBucket{
132+
vmcp.Spec.Config.RateLimiting = &mcpv1beta1.RateLimitConfig{
133+
PerUser: &mcpv1beta1.RateLimitBucket{
134134
MaxTokens: 1,
135135
RefillPeriod: metav1.Duration{Duration: time.Minute},
136136
},
@@ -153,8 +153,8 @@ var _ = Describe("CEL Validation for SessionStorageConfig on VirtualMCPServer",
153153
Audience: "test-audience",
154154
},
155155
}
156-
vmcp.Spec.Config.RateLimiting = &vmcpconfig.RateLimitConfig{
157-
PerUser: &vmcpconfig.RateLimitBucket{
156+
vmcp.Spec.Config.RateLimiting = &mcpv1beta1.RateLimitConfig{
157+
PerUser: &mcpv1beta1.RateLimitBucket{
158158
MaxTokens: 1,
159159
RefillPeriod: metav1.Duration{Duration: time.Minute},
160160
},

0 commit comments

Comments
 (0)