Skip to content

Commit 29d38d2

Browse files
committed
remove mixed mode to simplify vmcp operation
1 parent 8dae561 commit 29d38d2

File tree

12 files changed

+14
-177
lines changed

12 files changed

+14
-177
lines changed

cmd/thv-operator/api/v1alpha1/virtualmcpserver_types.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ type OutgoingAuthConfig struct {
8585
// Source defines how backend authentication configurations are determined
8686
// - discovered: Automatically discover from backend's MCPServer.spec.externalAuthConfigRef
8787
// - inline: Explicit per-backend configuration in VirtualMCPServer
88-
// - mixed: Discover most, override specific backends
89-
// +kubebuilder:validation:Enum=discovered;inline;mixed
88+
// +kubebuilder:validation:Enum=discovered;inline
9089
// +kubebuilder:default=discovered
9190
// +optional
9291
Source string `json:"source,omitempty"`
@@ -96,7 +95,7 @@ type OutgoingAuthConfig struct {
9695
Default *BackendAuthConfig `json:"default,omitempty"`
9796

9897
// Backends defines per-backend authentication overrides
99-
// Works in all modes (discovered, inline, mixed)
98+
// Works in all modes (discovered, inline)
10099
// +optional
101100
Backends map[string]BackendAuthConfig `json:"backends,omitempty"`
102101
}

cmd/thv-operator/api/v1alpha1/virtualmcpserver_webhook.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,9 @@ func (r *VirtualMCPServer) validateOutgoingAuth() error {
102102
validSources := map[string]bool{
103103
"discovered": true,
104104
"inline": true,
105-
"mixed": true,
106105
}
107106
if auth.Source != "" && !validSources[auth.Source] {
108-
return fmt.Errorf("spec.outgoingAuth.source must be one of: discovered, inline, mixed")
107+
return fmt.Errorf("spec.outgoingAuth.source must be one of: discovered, inline")
109108
}
110109

111110
// Validate backend configurations

cmd/thv-operator/api/v1alpha1/virtualmcpserver_webhook_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func TestVirtualMCPServerValidate(t *testing.T) {
5858
},
5959
},
6060
wantErr: true,
61-
errMsg: "spec.outgoingAuth.source must be one of: discovered, inline, mixed",
61+
errMsg: "spec.outgoingAuth.source must be one of: discovered, inline",
6262
},
6363
{
6464
name: "valid backend external auth config ref",

cmd/thv-operator/controllers/virtualmcpserver_vmcpconfig_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,14 @@ func TestConvertOutgoingAuth(t *testing.T) {
111111
{
112112
name: "with per-backend auth",
113113
outgoingAuth: &mcpv1alpha1.OutgoingAuthConfig{
114-
Source: "mixed",
114+
Source: "discovered",
115115
Backends: map[string]mcpv1alpha1.BackendAuthConfig{
116116
"backend-1": {
117117
Type: mcpv1alpha1.BackendAuthTypeDiscovered,
118118
},
119119
},
120120
},
121-
expectedSource: "mixed",
121+
expectedSource: "discovered",
122122
hasDefault: false,
123123
backendCount: 1,
124124
},
@@ -514,7 +514,7 @@ func TestYAMLMarshalingDeterminism(t *testing.T) {
514514
},
515515
// OutgoingAuth with Backends map
516516
OutgoingAuth: &mcpv1alpha1.OutgoingAuthConfig{
517-
Source: "mixed",
517+
Source: "discovered",
518518
Backends: map[string]mcpv1alpha1.BackendAuthConfig{
519519
"backend-zebra": {
520520
Type: mcpv1alpha1.BackendAuthTypeDiscovered,

deploy/charts/operator-crds/crds/toolhive.stacklok.dev_virtualmcpservers.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ spec:
612612
type: object
613613
description: |-
614614
Backends defines per-backend authentication overrides
615-
Works in all modes (discovered, inline, mixed)
615+
Works in all modes (discovered, inline)
616616
type: object
617617
default:
618618
description: Default defines default behavior for backends without
@@ -645,11 +645,9 @@ spec:
645645
Source defines how backend authentication configurations are determined
646646
- discovered: Automatically discover from backend's MCPServer.spec.externalAuthConfigRef
647647
- inline: Explicit per-backend configuration in VirtualMCPServer
648-
- mixed: Discover most, override specific backends
649648
enum:
650649
- discovered
651650
- inline
652-
- mixed
653651
type: string
654652
type: object
655653
podTemplateSpec:

docs/operator/crd-api.md

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

docs/operator/virtualmcpserver-api.md

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ Configures authentication from Virtual MCP to backend MCPServers.
8080
- `source` (string, optional): How backend authentication configurations are determined
8181
- `discovered` (default): Automatically discover from backend's `MCPServer.spec.externalAuthConfigRef`
8282
- `inline`: Explicit per-backend configuration in VirtualMCPServer
83-
- `mixed`: Discover most, override specific backends
8483
- `default` (BackendAuthConfig, optional): Default behavior for backends without explicit auth config
8584
- `backends` (map[string]BackendAuthConfig, optional): Per-backend authentication overrides
8685

@@ -113,27 +112,6 @@ spec:
113112
headerFormat: "Bearer {token}"
114113
```
115114

116-
**Example (mixed mode)**:
117-
```yaml
118-
spec:
119-
outgoingAuth:
120-
source: mixed
121-
default:
122-
type: discovered
123-
backends:
124-
# Override specific backends while others use discovery
125-
slack:
126-
type: service_account
127-
serviceAccount:
128-
credentialsRef:
129-
name: slack-bot-override
130-
key: token
131-
headerName: Authorization
132-
headerFormat: "Bearer {token}"
133-
# Other backends (github, jira, etc.) will automatically
134-
# discover auth config from their MCPServer.spec.externalAuthConfigRef
135-
```
136-
137115
#### BackendAuthConfig
138116

139117
**Fields**:

docs/proposals/THV-2106-virtual-mcp-server.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ spec:
593593
# ===== OUTGOING AUTHENTICATION (Virtual MCP → Backends) =====
594594
outgoingAuth:
595595
# Configuration source
596-
source: discovered # inline | discovered | mixed
596+
source: discovered # inline | discovered
597597
598598
# When source=discovered:
599599
# Virtual MCP queries each backend's MCPServer.spec.externalAuthConfigRef

pkg/vmcp/aggregator/discoverer.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ func (d *backendDiscoverer) Discover(ctx context.Context, groupRef string) ([]vm
159159
//
160160
// Auth resolution logic:
161161
// - "discovered" mode: Use discovered auth if available, otherwise fall back to Default or backend-specific config
162-
// - "mixed" mode: Use discovered auth unless there's an explicit backend override in config
163162
// - "inline" mode (or ""): Always use config-based auth, ignore discovered auth
164163
// - unknown mode: Default to config-based auth for safety
165164
//
@@ -180,11 +179,6 @@ func (d *backendDiscoverer) applyAuthConfigToBackend(backend *vmcp.Backend, back
180179
// If no auth is discovered, fall back to config-based auth via ResolveForBackend
181180
// which will use backend-specific config, then Default, then no auth
182181
useDiscoveredAuth = backend.AuthStrategy != ""
183-
case "mixed":
184-
// In mixed mode, use discovered auth as default, but allow config overrides
185-
// If there's no explicit config for this backend, use discovered auth
186-
_, hasExplicitConfig := d.authConfig.Backends[backendName]
187-
useDiscoveredAuth = !hasExplicitConfig && backend.AuthStrategy != ""
188182
case "inline", "":
189183
// For inline mode or empty source, always use config-based auth
190184
// Ignore any discovered auth from backends
@@ -199,7 +193,7 @@ func (d *backendDiscoverer) applyAuthConfigToBackend(backend *vmcp.Backend, back
199193
// Keep the auth discovered from MCPServer (already populated in backend)
200194
logger.Debugf("Backend %s using discovered auth strategy: %s", backendName, backend.AuthStrategy)
201195
} else {
202-
// Use auth from config (inline mode or explicit override in mixed mode)
196+
// Use auth from config (inline mode)
203197
authStrategy, authMetadata := d.authConfig.ResolveForBackend(backendName)
204198
if authStrategy != "" {
205199
backend.AuthStrategy = authStrategy

pkg/vmcp/aggregator/discoverer_test.go

Lines changed: 0 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -493,90 +493,6 @@ func TestBackendDiscoverer_applyAuthConfigToBackend(t *testing.T) {
493493
assert.Equal(t, "config-token", backend.AuthMetadata["token"])
494494
})
495495

496-
t.Run("mixed mode with explicit config override", func(t *testing.T) {
497-
t.Parallel()
498-
ctrl := gomock.NewController(t)
499-
t.Cleanup(ctrl.Finish)
500-
501-
mockWorkloadDiscoverer := discoverermocks.NewMockDiscoverer(ctrl)
502-
mockGroups := mocks.NewMockManager(ctrl)
503-
504-
authConfig := &config.OutgoingAuthConfig{
505-
Source: "mixed",
506-
Backends: map[string]*config.BackendAuthStrategy{
507-
"backend1": {
508-
Type: "bearer",
509-
Metadata: map[string]any{
510-
"token": "override-token",
511-
},
512-
},
513-
},
514-
}
515-
516-
discoverer := &backendDiscoverer{
517-
workloadsManager: mockWorkloadDiscoverer,
518-
groupsManager: mockGroups,
519-
authConfig: authConfig,
520-
}
521-
522-
backend := &vmcp.Backend{
523-
ID: "backend1",
524-
Name: "backend1",
525-
AuthStrategy: "token_exchange",
526-
AuthMetadata: map[string]any{
527-
"token_endpoint": "https://auth.example.com/token",
528-
},
529-
}
530-
531-
discoverer.applyAuthConfigToBackend(backend, "backend1")
532-
533-
// In mixed mode with explicit config, config should override discovered auth
534-
assert.Equal(t, "bearer", backend.AuthStrategy)
535-
assert.Equal(t, "override-token", backend.AuthMetadata["token"])
536-
})
537-
538-
t.Run("mixed mode without explicit config uses discovered auth", func(t *testing.T) {
539-
t.Parallel()
540-
ctrl := gomock.NewController(t)
541-
t.Cleanup(ctrl.Finish)
542-
543-
mockWorkloadDiscoverer := discoverermocks.NewMockDiscoverer(ctrl)
544-
mockGroups := mocks.NewMockManager(ctrl)
545-
546-
authConfig := &config.OutgoingAuthConfig{
547-
Source: "mixed",
548-
Backends: map[string]*config.BackendAuthStrategy{
549-
"other-backend": {
550-
Type: "bearer",
551-
Metadata: map[string]any{
552-
"token": "other-token",
553-
},
554-
},
555-
},
556-
}
557-
558-
discoverer := &backendDiscoverer{
559-
workloadsManager: mockWorkloadDiscoverer,
560-
groupsManager: mockGroups,
561-
authConfig: authConfig,
562-
}
563-
564-
backend := &vmcp.Backend{
565-
ID: "backend1",
566-
Name: "backend1",
567-
AuthStrategy: "token_exchange",
568-
AuthMetadata: map[string]any{
569-
"token_endpoint": "https://auth.example.com/token",
570-
},
571-
}
572-
573-
discoverer.applyAuthConfigToBackend(backend, "backend1")
574-
575-
// In mixed mode without explicit config, discovered auth should be preserved
576-
assert.Equal(t, "token_exchange", backend.AuthStrategy)
577-
assert.Equal(t, "https://auth.example.com/token", backend.AuthMetadata["token_endpoint"])
578-
})
579-
580496
t.Run("inline mode ignores discovered auth", func(t *testing.T) {
581497
t.Parallel()
582498
ctrl := gomock.NewController(t)
@@ -813,52 +729,6 @@ func TestBackendDiscoverer_applyAuthConfigToBackend(t *testing.T) {
813729
assert.Equal(t, "secret-key-123", backend.AuthMetadata["api_key"])
814730
})
815731

816-
t.Run("mixed mode falls back to config when no discovered auth", func(t *testing.T) {
817-
t.Parallel()
818-
ctrl := gomock.NewController(t)
819-
t.Cleanup(ctrl.Finish)
820-
821-
mockWorkloadDiscoverer := discoverermocks.NewMockDiscoverer(ctrl)
822-
mockGroups := mocks.NewMockManager(ctrl)
823-
824-
authConfig := &config.OutgoingAuthConfig{
825-
Source: "mixed",
826-
Backends: map[string]*config.BackendAuthStrategy{
827-
"other-backend": {
828-
Type: "bearer",
829-
Metadata: map[string]any{
830-
"token": "other-token",
831-
},
832-
},
833-
},
834-
Default: &config.BackendAuthStrategy{
835-
Type: "bearer",
836-
Metadata: map[string]any{
837-
"token": "default-token",
838-
},
839-
},
840-
}
841-
842-
discoverer := &backendDiscoverer{
843-
workloadsManager: mockWorkloadDiscoverer,
844-
groupsManager: mockGroups,
845-
authConfig: authConfig,
846-
}
847-
848-
backend := &vmcp.Backend{
849-
ID: "backend1",
850-
Name: "backend1",
851-
// No discovered auth
852-
}
853-
854-
discoverer.applyAuthConfigToBackend(backend, "backend1")
855-
856-
// In mixed mode with no explicit config and no discovered auth,
857-
// should use default config
858-
assert.Equal(t, "bearer", backend.AuthStrategy)
859-
assert.Equal(t, "default-token", backend.AuthMetadata["token"])
860-
})
861-
862732
t.Run("discovered mode falls back to default config when no auth discovered", func(t *testing.T) {
863733
t.Parallel()
864734
ctrl := gomock.NewController(t)

0 commit comments

Comments
 (0)