sigs.k8s.io/cluster-api@v1.7.1/main.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // main is the main package for the Cluster API Core Provider. 18 package main 19 20 import ( 21 "context" 22 "errors" 23 "flag" 24 "fmt" 25 "os" 26 goruntime "runtime" 27 "time" 28 29 "github.com/spf13/pflag" 30 corev1 "k8s.io/api/core/v1" 31 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 32 "k8s.io/apimachinery/pkg/labels" 33 "k8s.io/apimachinery/pkg/runtime" 34 "k8s.io/apimachinery/pkg/selection" 35 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 36 "k8s.io/client-go/tools/leaderelection/resourcelock" 37 cliflag "k8s.io/component-base/cli/flag" 38 "k8s.io/component-base/logs" 39 logsv1 "k8s.io/component-base/logs/api/v1" 40 _ "k8s.io/component-base/logs/json/register" 41 "k8s.io/klog/v2" 42 ctrl "sigs.k8s.io/controller-runtime" 43 "sigs.k8s.io/controller-runtime/pkg/cache" 44 "sigs.k8s.io/controller-runtime/pkg/client" 45 "sigs.k8s.io/controller-runtime/pkg/controller" 46 "sigs.k8s.io/controller-runtime/pkg/webhook" 47 48 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 49 "sigs.k8s.io/cluster-api/api/v1beta1/index" 50 "sigs.k8s.io/cluster-api/controllers" 51 "sigs.k8s.io/cluster-api/controllers/remote" 52 addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1" 53 addonscontrollers "sigs.k8s.io/cluster-api/exp/addons/controllers" 54 addonswebhooks "sigs.k8s.io/cluster-api/exp/addons/webhooks" 55 expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" 56 expcontrollers "sigs.k8s.io/cluster-api/exp/controllers" 57 ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1beta1" 58 expipamwebhooks "sigs.k8s.io/cluster-api/exp/ipam/webhooks" 59 runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1" 60 runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog" 61 runtimecontrollers "sigs.k8s.io/cluster-api/exp/runtime/controllers" 62 runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" 63 expwebhooks "sigs.k8s.io/cluster-api/exp/webhooks" 64 "sigs.k8s.io/cluster-api/feature" 65 addonsv1alpha3 "sigs.k8s.io/cluster-api/internal/apis/core/exp/addons/v1alpha3" 66 addonsv1alpha4 "sigs.k8s.io/cluster-api/internal/apis/core/exp/addons/v1alpha4" 67 expv1alpha3 "sigs.k8s.io/cluster-api/internal/apis/core/exp/v1alpha3" 68 expv1alpha4 "sigs.k8s.io/cluster-api/internal/apis/core/exp/v1alpha4" 69 clusterv1alpha3 "sigs.k8s.io/cluster-api/internal/apis/core/v1alpha3" 70 clusterv1alpha4 "sigs.k8s.io/cluster-api/internal/apis/core/v1alpha4" 71 runtimeclient "sigs.k8s.io/cluster-api/internal/runtime/client" 72 runtimeregistry "sigs.k8s.io/cluster-api/internal/runtime/registry" 73 runtimewebhooks "sigs.k8s.io/cluster-api/internal/webhooks/runtime" 74 "sigs.k8s.io/cluster-api/util/flags" 75 "sigs.k8s.io/cluster-api/version" 76 "sigs.k8s.io/cluster-api/webhooks" 77 ) 78 79 var ( 80 catalog = runtimecatalog.New() 81 scheme = runtime.NewScheme() 82 setupLog = ctrl.Log.WithName("setup") 83 controllerName = "cluster-api-controller-manager" 84 85 // flags. 86 enableLeaderElection bool 87 leaderElectionLeaseDuration time.Duration 88 leaderElectionRenewDeadline time.Duration 89 leaderElectionRetryPeriod time.Duration 90 watchFilterValue string 91 watchNamespace string 92 profilerAddress string 93 enableContentionProfiling bool 94 syncPeriod time.Duration 95 restConfigQPS float32 96 restConfigBurst int 97 webhookPort int 98 webhookCertDir string 99 healthAddr string 100 tlsOptions = flags.TLSOptions{} 101 diagnosticsOptions = flags.DiagnosticsOptions{} 102 logOptions = logs.NewOptions() 103 // core Cluster API specific flags. 104 clusterTopologyConcurrency int 105 clusterCacheTrackerConcurrency int 106 clusterClassConcurrency int 107 clusterConcurrency int 108 extensionConfigConcurrency int 109 machineConcurrency int 110 machineSetConcurrency int 111 machineDeploymentConcurrency int 112 machinePoolConcurrency int 113 clusterResourceSetConcurrency int 114 machineHealthCheckConcurrency int 115 nodeDrainClientTimeout time.Duration 116 ) 117 118 func init() { 119 _ = clientgoscheme.AddToScheme(scheme) 120 _ = apiextensionsv1.AddToScheme(scheme) 121 122 _ = clusterv1alpha3.AddToScheme(scheme) 123 _ = clusterv1alpha4.AddToScheme(scheme) 124 _ = clusterv1.AddToScheme(scheme) 125 126 _ = expv1alpha3.AddToScheme(scheme) 127 _ = expv1alpha4.AddToScheme(scheme) 128 _ = expv1.AddToScheme(scheme) 129 130 _ = addonsv1alpha3.AddToScheme(scheme) 131 _ = addonsv1alpha4.AddToScheme(scheme) 132 _ = addonsv1.AddToScheme(scheme) 133 134 _ = runtimev1.AddToScheme(scheme) 135 136 _ = ipamv1.AddToScheme(scheme) 137 138 // Register the RuntimeHook types into the catalog. 139 _ = runtimehooksv1.AddToCatalog(catalog) 140 } 141 142 // InitFlags initializes the flags. 143 func InitFlags(fs *pflag.FlagSet) { 144 logsv1.AddFlags(logOptions, fs) 145 146 fs.BoolVar(&enableLeaderElection, "leader-elect", false, 147 "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") 148 149 fs.DurationVar(&leaderElectionLeaseDuration, "leader-elect-lease-duration", 15*time.Second, 150 "Interval at which non-leader candidates will wait to force acquire leadership (duration string)") 151 152 fs.DurationVar(&leaderElectionRenewDeadline, "leader-elect-renew-deadline", 10*time.Second, 153 "Duration that the leading controller manager will retry refreshing leadership before giving up (duration string)") 154 155 fs.DurationVar(&leaderElectionRetryPeriod, "leader-elect-retry-period", 2*time.Second, 156 "Duration the LeaderElector clients should wait between tries of actions (duration string)") 157 158 fs.StringVar(&watchNamespace, "namespace", "", 159 "Namespace that the controller watches to reconcile cluster-api objects. If unspecified, the controller watches for cluster-api objects across all namespaces.") 160 161 fs.StringVar(&watchFilterValue, "watch-filter", "", 162 fmt.Sprintf("Label value that the controller watches to reconcile cluster-api objects. Label key is always %s. If unspecified, the controller watches for all cluster-api objects.", clusterv1.WatchLabel)) 163 164 fs.StringVar(&profilerAddress, "profiler-address", "", 165 "Bind address to expose the pprof profiler (e.g. localhost:6060)") 166 167 fs.BoolVar(&enableContentionProfiling, "contention-profiling", false, 168 "Enable block profiling") 169 170 fs.IntVar(&clusterTopologyConcurrency, "clustertopology-concurrency", 10, 171 "Number of clusters to process simultaneously") 172 173 fs.IntVar(&clusterClassConcurrency, "clusterclass-concurrency", 10, 174 "Number of ClusterClasses to process simultaneously") 175 176 fs.IntVar(&clusterConcurrency, "cluster-concurrency", 10, 177 "Number of clusters to process simultaneously") 178 179 fs.IntVar(&clusterCacheTrackerConcurrency, "clustercachetracker-concurrency", 10, 180 "Number of clusters to process simultaneously") 181 182 fs.IntVar(&extensionConfigConcurrency, "extensionconfig-concurrency", 10, 183 "Number of extension configs to process simultaneously") 184 185 fs.IntVar(&machineConcurrency, "machine-concurrency", 10, 186 "Number of machines to process simultaneously") 187 188 fs.IntVar(&machineSetConcurrency, "machineset-concurrency", 10, 189 "Number of machine sets to process simultaneously") 190 191 fs.IntVar(&machineDeploymentConcurrency, "machinedeployment-concurrency", 10, 192 "Number of machine deployments to process simultaneously") 193 194 fs.IntVar(&machinePoolConcurrency, "machinepool-concurrency", 10, 195 "Number of machine pools to process simultaneously") 196 197 fs.IntVar(&clusterResourceSetConcurrency, "clusterresourceset-concurrency", 10, 198 "Number of cluster resource sets to process simultaneously") 199 200 fs.IntVar(&machineHealthCheckConcurrency, "machinehealthcheck-concurrency", 10, 201 "Number of machine health checks to process simultaneously") 202 203 fs.DurationVar(&syncPeriod, "sync-period", 10*time.Minute, 204 "The minimum interval at which watched resources are reconciled (e.g. 15m)") 205 206 fs.Float32Var(&restConfigQPS, "kube-api-qps", 20, 207 "Maximum queries per second from the controller client to the Kubernetes API server. Defaults to 20") 208 209 fs.IntVar(&restConfigBurst, "kube-api-burst", 30, 210 "Maximum number of queries that should be allowed in one burst from the controller client to the Kubernetes API server. Default 30") 211 212 fs.DurationVar(&nodeDrainClientTimeout, "node-drain-client-timeout-duration", time.Second*10, 213 "The timeout of the client used for draining nodes. Defaults to 10s") 214 215 fs.IntVar(&webhookPort, "webhook-port", 9443, 216 "Webhook Server port") 217 218 fs.StringVar(&webhookCertDir, "webhook-cert-dir", "/tmp/k8s-webhook-server/serving-certs/", 219 "Webhook cert dir, only used when webhook-port is specified.") 220 221 fs.StringVar(&healthAddr, "health-addr", ":9440", 222 "The address the health endpoint binds to.") 223 224 flags.AddDiagnosticsOptions(fs, &diagnosticsOptions) 225 flags.AddTLSOptions(fs, &tlsOptions) 226 227 feature.MutableGates.AddFlag(fs) 228 } 229 230 // Add RBAC for the authorized diagnostics endpoint. 231 // +kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create 232 // +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create 233 234 func main() { 235 InitFlags(pflag.CommandLine) 236 pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc) 237 pflag.CommandLine.AddGoFlagSet(flag.CommandLine) 238 // Set log level 2 as default. 239 if err := pflag.CommandLine.Set("v", "2"); err != nil { 240 setupLog.Error(err, "failed to set default log level") 241 os.Exit(1) 242 } 243 pflag.Parse() 244 245 if err := logsv1.ValidateAndApply(logOptions, nil); err != nil { 246 setupLog.Error(err, "unable to start manager") 247 os.Exit(1) 248 } 249 250 // klog.Background will automatically use the right logger. 251 ctrl.SetLogger(klog.Background()) 252 253 restConfig := ctrl.GetConfigOrDie() 254 restConfig.QPS = restConfigQPS 255 restConfig.Burst = restConfigBurst 256 restConfig.UserAgent = remote.DefaultClusterAPIUserAgent(controllerName) 257 258 if nodeDrainClientTimeout <= 0 { 259 setupLog.Error(errors.New("node drain client timeout must be greater than zero"), "unable to start manager") 260 os.Exit(1) 261 } 262 263 minVer := version.MinimumKubernetesVersion 264 if feature.Gates.Enabled(feature.ClusterTopology) { 265 minVer = version.MinimumKubernetesVersionClusterTopology 266 } 267 268 if err := version.CheckKubernetesVersion(restConfig, minVer); err != nil { 269 setupLog.Error(err, "unable to start manager") 270 os.Exit(1) 271 } 272 273 tlsOptionOverrides, err := flags.GetTLSOptionOverrideFuncs(tlsOptions) 274 if err != nil { 275 setupLog.Error(err, "unable to add TLS settings to the webhook server") 276 os.Exit(1) 277 } 278 279 diagnosticsOpts := flags.GetDiagnosticsOptions(diagnosticsOptions) 280 281 var watchNamespaces map[string]cache.Config 282 if watchNamespace != "" { 283 watchNamespaces = map[string]cache.Config{ 284 watchNamespace: {}, 285 } 286 } 287 288 if enableContentionProfiling { 289 goruntime.SetBlockProfileRate(1) 290 } 291 292 req, _ := labels.NewRequirement(clusterv1.ClusterNameLabel, selection.Exists, nil) 293 clusterSecretCacheSelector := labels.NewSelector().Add(*req) 294 295 ctrlOptions := ctrl.Options{ 296 Scheme: scheme, 297 LeaderElection: enableLeaderElection, 298 LeaderElectionID: "controller-leader-election-capi", 299 LeaseDuration: &leaderElectionLeaseDuration, 300 RenewDeadline: &leaderElectionRenewDeadline, 301 RetryPeriod: &leaderElectionRetryPeriod, 302 LeaderElectionResourceLock: resourcelock.LeasesResourceLock, 303 HealthProbeBindAddress: healthAddr, 304 PprofBindAddress: profilerAddress, 305 Metrics: diagnosticsOpts, 306 Cache: cache.Options{ 307 DefaultNamespaces: watchNamespaces, 308 SyncPeriod: &syncPeriod, 309 ByObject: map[client.Object]cache.ByObject{ 310 // Note: Only Secrets with the cluster name label are cached. 311 // The default client of the manager won't use the cache for secrets at all (see Client.Cache.DisableFor). 312 // The cached secrets will only be used by the secretCachingClient we create below. 313 &corev1.Secret{}: { 314 Label: clusterSecretCacheSelector, 315 }, 316 }, 317 }, 318 Client: client.Options{ 319 Cache: &client.CacheOptions{ 320 DisableFor: []client.Object{ 321 &corev1.ConfigMap{}, 322 &corev1.Secret{}, 323 }, 324 }, 325 }, 326 WebhookServer: webhook.NewServer( 327 webhook.Options{ 328 Port: webhookPort, 329 CertDir: webhookCertDir, 330 TLSOpts: tlsOptionOverrides, 331 }, 332 ), 333 } 334 335 mgr, err := ctrl.NewManager(restConfig, ctrlOptions) 336 if err != nil { 337 setupLog.Error(err, "unable to start manager") 338 os.Exit(1) 339 } 340 341 // Setup the context that's going to be used in controllers and for the manager. 342 ctx := ctrl.SetupSignalHandler() 343 344 setupChecks(mgr) 345 setupIndexes(ctx, mgr) 346 tracker := setupReconcilers(ctx, mgr) 347 setupWebhooks(mgr, tracker) 348 349 setupLog.Info("starting manager", "version", version.Get().String()) 350 if err := mgr.Start(ctx); err != nil { 351 setupLog.Error(err, "problem running manager") 352 os.Exit(1) 353 } 354 } 355 356 func setupChecks(mgr ctrl.Manager) { 357 if err := mgr.AddReadyzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { 358 setupLog.Error(err, "unable to create ready check") 359 os.Exit(1) 360 } 361 362 if err := mgr.AddHealthzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { 363 setupLog.Error(err, "unable to create health check") 364 os.Exit(1) 365 } 366 } 367 368 func setupIndexes(ctx context.Context, mgr ctrl.Manager) { 369 if err := index.AddDefaultIndexes(ctx, mgr); err != nil { 370 setupLog.Error(err, "unable to setup indexes") 371 os.Exit(1) 372 } 373 } 374 375 func setupReconcilers(ctx context.Context, mgr ctrl.Manager) webhooks.ClusterCacheTrackerReader { 376 secretCachingClient, err := client.New(mgr.GetConfig(), client.Options{ 377 HTTPClient: mgr.GetHTTPClient(), 378 Cache: &client.CacheOptions{ 379 Reader: mgr.GetCache(), 380 }, 381 }) 382 if err != nil { 383 setupLog.Error(err, "unable to create secret caching client") 384 os.Exit(1) 385 } 386 387 // Set up a ClusterCacheTracker and ClusterCacheReconciler to provide to controllers 388 // requiring a connection to a remote cluster 389 tracker, err := remote.NewClusterCacheTracker( 390 mgr, 391 remote.ClusterCacheTrackerOptions{ 392 SecretCachingClient: secretCachingClient, 393 ControllerName: controllerName, 394 Log: &ctrl.Log, 395 Indexes: []remote.Index{remote.NodeProviderIDIndex}, 396 }, 397 ) 398 if err != nil { 399 setupLog.Error(err, "unable to create cluster cache tracker") 400 os.Exit(1) 401 } 402 403 if err := (&remote.ClusterCacheReconciler{ 404 Client: mgr.GetClient(), 405 Tracker: tracker, 406 WatchFilterValue: watchFilterValue, 407 }).SetupWithManager(ctx, mgr, concurrency(clusterCacheTrackerConcurrency)); err != nil { 408 setupLog.Error(err, "unable to create controller", "controller", "ClusterCacheReconciler") 409 os.Exit(1) 410 } 411 412 var runtimeClient runtimeclient.Client 413 if feature.Gates.Enabled(feature.RuntimeSDK) { 414 // This is the creation of the runtimeClient for the controllers, embedding a shared catalog and registry instance. 415 runtimeClient = runtimeclient.New(runtimeclient.Options{ 416 Catalog: catalog, 417 Registry: runtimeregistry.New(), 418 Client: mgr.GetClient(), 419 }) 420 } 421 422 unstructuredCachingClient, err := client.New(mgr.GetConfig(), client.Options{ 423 HTTPClient: mgr.GetHTTPClient(), 424 Cache: &client.CacheOptions{ 425 Reader: mgr.GetCache(), 426 Unstructured: true, 427 }, 428 }) 429 if err != nil { 430 setupLog.Error(err, "unable to create unstructured caching client") 431 os.Exit(1) 432 } 433 434 if feature.Gates.Enabled(feature.ClusterTopology) { 435 if err := (&controllers.ClusterClassReconciler{ 436 Client: mgr.GetClient(), 437 RuntimeClient: runtimeClient, 438 UnstructuredCachingClient: unstructuredCachingClient, 439 WatchFilterValue: watchFilterValue, 440 }).SetupWithManager(ctx, mgr, concurrency(clusterClassConcurrency)); err != nil { 441 setupLog.Error(err, "unable to create controller", "controller", "ClusterClass") 442 os.Exit(1) 443 } 444 445 if err := (&controllers.ClusterTopologyReconciler{ 446 Client: mgr.GetClient(), 447 APIReader: mgr.GetAPIReader(), 448 RuntimeClient: runtimeClient, 449 Tracker: tracker, 450 UnstructuredCachingClient: unstructuredCachingClient, 451 WatchFilterValue: watchFilterValue, 452 }).SetupWithManager(ctx, mgr, concurrency(clusterTopologyConcurrency)); err != nil { 453 setupLog.Error(err, "unable to create controller", "controller", "ClusterTopology") 454 os.Exit(1) 455 } 456 457 if err := (&controllers.MachineDeploymentTopologyReconciler{ 458 Client: mgr.GetClient(), 459 APIReader: mgr.GetAPIReader(), 460 WatchFilterValue: watchFilterValue, 461 }).SetupWithManager(ctx, mgr, controller.Options{}); err != nil { 462 setupLog.Error(err, "unable to create controller", "controller", "MachineDeploymentTopology") 463 os.Exit(1) 464 } 465 466 if err := (&controllers.MachineSetTopologyReconciler{ 467 Client: mgr.GetClient(), 468 APIReader: mgr.GetAPIReader(), 469 WatchFilterValue: watchFilterValue, 470 }).SetupWithManager(ctx, mgr, controller.Options{}); err != nil { 471 setupLog.Error(err, "unable to create controller", "controller", "MachineSetTopology") 472 os.Exit(1) 473 } 474 } 475 476 if feature.Gates.Enabled(feature.RuntimeSDK) { 477 if err = (&runtimecontrollers.ExtensionConfigReconciler{ 478 Client: mgr.GetClient(), 479 APIReader: mgr.GetAPIReader(), 480 RuntimeClient: runtimeClient, 481 WatchFilterValue: watchFilterValue, 482 }).SetupWithManager(ctx, mgr, concurrency(extensionConfigConcurrency)); err != nil { 483 setupLog.Error(err, "unable to create controller", "controller", "ExtensionConfig") 484 os.Exit(1) 485 } 486 } 487 488 if err := (&controllers.ClusterReconciler{ 489 Client: mgr.GetClient(), 490 UnstructuredCachingClient: unstructuredCachingClient, 491 APIReader: mgr.GetAPIReader(), 492 WatchFilterValue: watchFilterValue, 493 }).SetupWithManager(ctx, mgr, concurrency(clusterConcurrency)); err != nil { 494 setupLog.Error(err, "unable to create controller", "controller", "Cluster") 495 os.Exit(1) 496 } 497 if err := (&controllers.MachineReconciler{ 498 Client: mgr.GetClient(), 499 UnstructuredCachingClient: unstructuredCachingClient, 500 APIReader: mgr.GetAPIReader(), 501 Tracker: tracker, 502 WatchFilterValue: watchFilterValue, 503 NodeDrainClientTimeout: nodeDrainClientTimeout, 504 }).SetupWithManager(ctx, mgr, concurrency(machineConcurrency)); err != nil { 505 setupLog.Error(err, "unable to create controller", "controller", "Machine") 506 os.Exit(1) 507 } 508 if err := (&controllers.MachineSetReconciler{ 509 Client: mgr.GetClient(), 510 UnstructuredCachingClient: unstructuredCachingClient, 511 APIReader: mgr.GetAPIReader(), 512 Tracker: tracker, 513 WatchFilterValue: watchFilterValue, 514 }).SetupWithManager(ctx, mgr, concurrency(machineSetConcurrency)); err != nil { 515 setupLog.Error(err, "unable to create controller", "controller", "MachineSet") 516 os.Exit(1) 517 } 518 if err := (&controllers.MachineDeploymentReconciler{ 519 Client: mgr.GetClient(), 520 UnstructuredCachingClient: unstructuredCachingClient, 521 APIReader: mgr.GetAPIReader(), 522 WatchFilterValue: watchFilterValue, 523 }).SetupWithManager(ctx, mgr, concurrency(machineDeploymentConcurrency)); err != nil { 524 setupLog.Error(err, "unable to create controller", "controller", "MachineDeployment") 525 os.Exit(1) 526 } 527 528 if feature.Gates.Enabled(feature.MachinePool) { 529 if err := (&expcontrollers.MachinePoolReconciler{ 530 Client: mgr.GetClient(), 531 APIReader: mgr.GetAPIReader(), 532 Tracker: tracker, 533 WatchFilterValue: watchFilterValue, 534 }).SetupWithManager(ctx, mgr, concurrency(machinePoolConcurrency)); err != nil { 535 setupLog.Error(err, "unable to create controller", "controller", "MachinePool") 536 os.Exit(1) 537 } 538 } 539 540 if feature.Gates.Enabled(feature.ClusterResourceSet) { 541 if err := (&addonscontrollers.ClusterResourceSetReconciler{ 542 Client: mgr.GetClient(), 543 Tracker: tracker, 544 WatchFilterValue: watchFilterValue, 545 }).SetupWithManager(ctx, mgr, concurrency(clusterResourceSetConcurrency)); err != nil { 546 setupLog.Error(err, "unable to create controller", "controller", "ClusterResourceSet") 547 os.Exit(1) 548 } 549 if err := (&addonscontrollers.ClusterResourceSetBindingReconciler{ 550 Client: mgr.GetClient(), 551 WatchFilterValue: watchFilterValue, 552 }).SetupWithManager(ctx, mgr, concurrency(clusterResourceSetConcurrency)); err != nil { 553 setupLog.Error(err, "unable to create controller", "controller", "ClusterResourceSetBinding") 554 os.Exit(1) 555 } 556 } 557 558 if err := (&controllers.MachineHealthCheckReconciler{ 559 Client: mgr.GetClient(), 560 Tracker: tracker, 561 WatchFilterValue: watchFilterValue, 562 }).SetupWithManager(ctx, mgr, concurrency(machineHealthCheckConcurrency)); err != nil { 563 setupLog.Error(err, "unable to create controller", "controller", "MachineHealthCheck") 564 os.Exit(1) 565 } 566 567 return tracker 568 } 569 570 func setupWebhooks(mgr ctrl.Manager, tracker webhooks.ClusterCacheTrackerReader) { 571 // NOTE: ClusterClass and managed topologies are behind ClusterTopology feature gate flag; the webhook 572 // is going to prevent creating or updating new objects in case the feature flag is disabled. 573 if err := (&webhooks.ClusterClass{Client: mgr.GetClient()}).SetupWebhookWithManager(mgr); err != nil { 574 setupLog.Error(err, "unable to create webhook", "webhook", "ClusterClass") 575 os.Exit(1) 576 } 577 578 // NOTE: ClusterClass and managed topologies are behind ClusterTopology feature gate flag; the webhook 579 // is going to prevent usage of Cluster.Topology in case the feature flag is disabled. 580 if err := (&webhooks.Cluster{Client: mgr.GetClient(), ClusterCacheTrackerReader: tracker}).SetupWebhookWithManager(mgr); err != nil { 581 setupLog.Error(err, "unable to create webhook", "webhook", "Cluster") 582 os.Exit(1) 583 } 584 585 if err := (&webhooks.Machine{}).SetupWebhookWithManager(mgr); err != nil { 586 setupLog.Error(err, "unable to create webhook", "webhook", "Machine") 587 os.Exit(1) 588 } 589 590 if err := (&webhooks.MachineSet{}).SetupWebhookWithManager(mgr); err != nil { 591 setupLog.Error(err, "unable to create webhook", "webhook", "MachineSet") 592 os.Exit(1) 593 } 594 595 if err := (&webhooks.MachineDeployment{}).SetupWebhookWithManager(mgr); err != nil { 596 setupLog.Error(err, "unable to create webhook", "webhook", "MachineDeployment") 597 os.Exit(1) 598 } 599 600 // NOTE: MachinePool is behind MachinePool feature gate flag; the webhook 601 // is going to prevent creating or updating new objects in case the feature flag is disabled 602 if err := (&expwebhooks.MachinePool{}).SetupWebhookWithManager(mgr); err != nil { 603 setupLog.Error(err, "unable to create webhook", "webhook", "MachinePool") 604 os.Exit(1) 605 } 606 607 // NOTE: ClusterResourceSet is behind ClusterResourceSet feature gate flag; the webhook 608 // is going to prevent creating or updating new objects in case the feature flag is disabled 609 if err := (&addonswebhooks.ClusterResourceSet{}).SetupWebhookWithManager(mgr); err != nil { 610 setupLog.Error(err, "unable to create webhook", "webhook", "ClusterResourceSet") 611 os.Exit(1) 612 } 613 // NOTE: ClusterResourceSetBinding is behind ClusterResourceSet feature gate flag; the webhook 614 // is going to prevent creating or updating new objects in case the feature flag is disabled 615 if err := (&addonswebhooks.ClusterResourceSetBinding{}).SetupWebhookWithManager(mgr); err != nil { 616 setupLog.Error(err, "unable to create webhook", "webhook", "ClusterResourceSetBinding") 617 os.Exit(1) 618 } 619 620 if err := (&webhooks.MachineHealthCheck{}).SetupWebhookWithManager(mgr); err != nil { 621 setupLog.Error(err, "unable to create webhook", "webhook", "MachineHealthCheck") 622 os.Exit(1) 623 } 624 625 // NOTE: ExtensionConfig is behind the RuntimeSDK feature gate flag. The webhook will prevent creating or updating 626 // new objects if the feature flag is disabled. 627 if err := (&runtimewebhooks.ExtensionConfig{}).SetupWebhookWithManager(mgr); err != nil { 628 setupLog.Error(err, "unable to create webhook", "webhook", "ExtensionConfig") 629 os.Exit(1) 630 } 631 632 if err := (&expipamwebhooks.IPAddress{ 633 // We are using GetAPIReader here to avoid caching all IPAddressClaims 634 Client: mgr.GetAPIReader(), 635 }).SetupWebhookWithManager(mgr); err != nil { 636 setupLog.Error(err, "unable to create webhook", "webhook", "IPAddress") 637 os.Exit(1) 638 } 639 if err := (&expipamwebhooks.IPAddressClaim{}).SetupWebhookWithManager(mgr); err != nil { 640 setupLog.Error(err, "unable to create webhook", "webhook", "IPAddressClaim") 641 os.Exit(1) 642 } 643 } 644 645 func concurrency(c int) controller.Options { 646 return controller.Options{MaxConcurrentReconciles: c} 647 }