@@ -7,13 +7,14 @@ import (
77 "flag"
88 "fmt"
99 "os"
10+ "strconv"
1011 "strings"
1112
13+ // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
14+ // to ensure that exec-entrypoint and run can make use of them.
1215 "k8s.io/apimachinery/pkg/runtime"
1316 utilruntime "k8s.io/apimachinery/pkg/util/runtime"
1417 clientgoscheme "k8s.io/client-go/kubernetes/scheme"
15- // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
16- // to ensure that exec-entrypoint and run can make use of them.
1718 _ "k8s.io/client-go/plugin/pkg/client/auth"
1819 ctrl "sigs.k8s.io/controller-runtime"
1920 "sigs.k8s.io/controller-runtime/pkg/cache"
3637 setupLog = log .Log .WithName ("setup" )
3738)
3839
40+ // Feature flags for controller groups
41+ const (
42+ featureServer = "ENABLE_SERVER"
43+ featureRegistry = "ENABLE_REGISTRY"
44+ featureVMCP = "ENABLE_VMCP"
45+ )
46+
47+ // controllerDependencies maps each controller group to its required dependencies
48+ var controllerDependencies = map [string ][]string {
49+ featureVMCP : {featureServer }, // Virtual MCP requires server controllers
50+ }
51+
3952func init () {
4053 utilruntime .Must (clientgoscheme .AddToScheme (scheme ))
4154 utilruntime .Must (mcpv1alpha1 .AddToScheme (scheme ))
@@ -111,6 +124,69 @@ func main() {
111124
112125// setupControllersAndWebhooks sets up all controllers and webhooks with the manager
113126func setupControllersAndWebhooks (mgr ctrl.Manager ) error {
127+ // Check feature flags
128+ enableServer := isFeatureEnabled (featureServer , true )
129+ enableRegistry := isFeatureEnabled (featureRegistry , true )
130+ enableVMCP := isFeatureEnabled (featureVMCP , true )
131+
132+ // Track enabled features for dependency checking
133+ enabledFeatures := map [string ]bool {
134+ featureServer : enableServer ,
135+ featureRegistry : enableRegistry ,
136+ featureVMCP : enableVMCP ,
137+ }
138+
139+ // Check dependencies and log warnings for missing dependencies
140+ for feature , deps := range controllerDependencies {
141+ if ! enabledFeatures [feature ] {
142+ continue // Skip if feature itself is disabled
143+ }
144+ for _ , dep := range deps {
145+ if ! enabledFeatures [dep ] {
146+ setupLog .Info (
147+ fmt .Sprintf ("%s requires %s to be enabled, skipping %s controllers" , feature , dep , feature ),
148+ "feature" , feature ,
149+ "required_dependency" , dep ,
150+ )
151+ enabledFeatures [feature ] = false // Mark as effectively disabled
152+ break
153+ }
154+ }
155+ }
156+
157+ // Set up server-related controllers
158+ if enabledFeatures [featureServer ] {
159+ if err := setupServerControllers (mgr , enableRegistry ); err != nil {
160+ return err
161+ }
162+ } else {
163+ setupLog .Info ("ENABLE_SERVER is disabled, skipping server-related controllers" )
164+ }
165+
166+ // Set up registry controller
167+ if enabledFeatures [featureRegistry ] {
168+ if err := setupRegistryController (mgr ); err != nil {
169+ return err
170+ }
171+ } else {
172+ setupLog .Info ("ENABLE_REGISTRY is disabled, skipping MCPRegistry controller" )
173+ }
174+
175+ // Set up Virtual MCP controllers and webhooks
176+ if enabledFeatures [featureVMCP ] {
177+ if err := setupAggregationControllers (mgr ); err != nil {
178+ return err
179+ }
180+ } else {
181+ setupLog .Info ("ENABLE_VMCP is disabled, skipping Virtual MCP controllers and webhooks" )
182+ }
183+
184+ //+kubebuilder:scaffold:builder
185+ return nil
186+ }
187+
188+ // setupServerControllers sets up server-related controllers (MCPServer, MCPExternalAuthConfig, MCPRemoteProxy, ToolConfig)
189+ func setupServerControllers (mgr ctrl.Manager , enableRegistry bool ) error {
114190 // Set up field indexing for MCPServer.Spec.GroupRef
115191 if err := mgr .GetFieldIndexer ().IndexField (
116192 context .Background (),
@@ -127,37 +203,43 @@ func setupControllersAndWebhooks(mgr ctrl.Manager) error {
127203 return fmt .Errorf ("unable to create field index for spec.groupRef: %w" , err )
128204 }
129205
130- // Create a shared platform detector for all controllers
131- sharedPlatformDetector := ctrlutil .NewSharedPlatformDetector ()
206+ // Set image validation mode based on whether registry is enabled
207+ // If ENABLE_REGISTRY is enabled, enforce registry-based image validation
208+ // Otherwise, allow all images
209+ imageValidation := validation .ImageValidationAlwaysAllow
210+ if enableRegistry {
211+ imageValidation = validation .ImageValidationRegistryEnforcing
212+ }
213+
214+ // Set up MCPServer controller
132215 rec := & controllers.MCPServerReconciler {
133216 Client : mgr .GetClient (),
134217 Scheme : mgr .GetScheme (),
135218 Recorder : mgr .GetEventRecorderFor ("mcpserver-controller" ),
136- PlatformDetector : sharedPlatformDetector ,
137- ImageValidation : validation . ImageValidationAlwaysAllow ,
219+ PlatformDetector : ctrlutil . NewSharedPlatformDetector () ,
220+ ImageValidation : imageValidation ,
138221 }
139-
140222 if err := rec .SetupWithManager (mgr ); err != nil {
141223 return fmt .Errorf ("unable to create controller MCPServer: %w" , err )
142224 }
143225
144- // Register MCPToolConfig controller
226+ // Set up MCPToolConfig controller
145227 if err := (& controllers.ToolConfigReconciler {
146228 Client : mgr .GetClient (),
147229 Scheme : mgr .GetScheme (),
148230 }).SetupWithManager (mgr ); err != nil {
149231 return fmt .Errorf ("unable to create controller MCPToolConfig: %w" , err )
150232 }
151233
152- // Register MCPExternalAuthConfig controller
234+ // Set up MCPExternalAuthConfig controller
153235 if err := (& controllers.MCPExternalAuthConfigReconciler {
154236 Client : mgr .GetClient (),
155237 Scheme : mgr .GetScheme (),
156238 }).SetupWithManager (mgr ); err != nil {
157239 return fmt .Errorf ("unable to create controller MCPExternalAuthConfig: %w" , err )
158240 }
159241
160- // Register MCPRemoteProxy controller
242+ // Set up MCPRemoteProxy controller
161243 if err := (& controllers.MCPRemoteProxyReconciler {
162244 Client : mgr .GetClient (),
163245 Scheme : mgr .GetScheme (),
@@ -166,13 +248,22 @@ func setupControllersAndWebhooks(mgr ctrl.Manager) error {
166248 return fmt .Errorf ("unable to create controller MCPRemoteProxy: %w" , err )
167249 }
168250
169- // Only register MCPRegistry controller if feature flag is enabled
170- rec . ImageValidation = validation . ImageValidationRegistryEnforcing
251+ return nil
252+ }
171253
254+ // setupRegistryController sets up the MCPRegistry controller
255+ func setupRegistryController (mgr ctrl.Manager ) error {
172256 if err := (controllers .NewMCPRegistryReconciler (mgr .GetClient (), mgr .GetScheme ())).SetupWithManager (mgr ); err != nil {
173257 return fmt .Errorf ("unable to create controller MCPRegistry: %w" , err )
174258 }
259+ return nil
260+ }
175261
262+ // setupAggregationControllers sets up Virtual MCP-related controllers and webhooks
263+ // (MCPGroup, VirtualMCPServer, and their webhooks)
264+ // Note: This function assumes server controllers are enabled (enforced by dependency check)
265+ // The field index for MCPServer.Spec.GroupRef is created in setupServerControllers
266+ func setupAggregationControllers (mgr ctrl.Manager ) error {
176267 // Set up MCPGroup controller
177268 if err := (& controllers.MCPGroupReconciler {
178269 Client : mgr .GetClient (),
@@ -199,11 +290,25 @@ func setupControllersAndWebhooks(mgr ctrl.Manager) error {
199290 if err := (& mcpv1alpha1.VirtualMCPCompositeToolDefinition {}).SetupWebhookWithManager (mgr ); err != nil {
200291 return fmt .Errorf ("unable to create webhook VirtualMCPCompositeToolDefinition: %w" , err )
201292 }
202- //+kubebuilder:scaffold:builder
203293
204294 return nil
205295}
206296
297+ // isFeatureEnabled checks if a feature flag environment variable is enabled.
298+ // If the environment variable is not set, it returns the default value.
299+ // The environment variable is considered enabled if it's set to "true" (case-insensitive).
300+ func isFeatureEnabled (envVar string , defaultValue bool ) bool {
301+ value , found := os .LookupEnv (envVar )
302+ if ! found {
303+ return defaultValue
304+ }
305+ enabled , err := strconv .ParseBool (value )
306+ if err != nil {
307+ return defaultValue
308+ }
309+ return enabled
310+ }
311+
207312// getDefaultNamespaces returns a map of namespaces to cache.Config for the operator to watch.
208313// if WATCH_NAMESPACE is not set, returns nil which is defaulted to a cluster scope.
209314func getDefaultNamespaces () map [string ]cache.Config {
0 commit comments