Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 54 additions & 49 deletions cmd/capi-controllers/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
package main

import (
"context"
"errors"
"flag"
"fmt"
"os"
"time"

"github.com/go-logr/logr"
metal3v1 "github.com/metal3-io/cluster-api-provider-metal3/api/v1beta1"

admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
Expand All @@ -27,7 +30,6 @@ import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
klog "k8s.io/klog/v2"

awsv1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
azurev1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
Expand Down Expand Up @@ -87,128 +89,131 @@ func initScheme(scheme *runtime.Scheme) {
}

func main() {
cfg := ctrl.GetConfigOrDie()
ctx := ctrl.SetupSignalHandler()
scheme := runtime.NewScheme()
initScheme(scheme)

opts := commoncmdoptions.InitCommonOptions(managerName, controllers.DefaultCAPINamespace)

webhookPort := flag.Int(
extraflags := flag.NewFlagSet("", flag.ContinueOnError)
webhookPort := extraflags.Int(
"webhook-port",
9443,
"The port for the webhook server to listen on.",
)
webhookCertDir := flag.String(
webhookCertDir := extraflags.String(
"webhook-cert-dir",
"/tmp/k8s-webhook-server/serving-certs/",
"Webhook cert dir, only used when webhook-port is specified.",
)

opts.Parse()

cacheOpts := getDefaultCacheOptions(*opts.CAPINamespace, 10*time.Minute)

cfg := ctrl.GetConfigOrDie()
ctx := ctrl.SetupSignalHandler()
log, operatorConfig, mgrOpts, initManager, err := commoncmdoptions.InitOperatorConfig(ctx, cfg, scheme, managerName, controllers.DefaultCAPINamespace, extraflags)
if err != nil {
log.Error(err, "unable to initialize operator config")
os.Exit(1)
}

mgrOpts, tlsOptions := opts.GetCommonManagerOptions()
mgrOpts.Cache = cacheOpts
mgrOpts.Scheme = scheme
mgrOpts.Cache = getDefaultCacheOptions(*operatorConfig.CAPINamespace, 10*time.Minute)
mgrOpts.WebhookServer = crwebhook.NewServer(crwebhook.Options{
Port: *webhookPort,
CertDir: *webhookCertDir,
TLSOpts: tlsOptions,
TLSOpts: operatorConfig.TLSOptions,
})

mgr, err := ctrl.NewManager(cfg, mgrOpts)
if err != nil {
klog.Error(err, "unable to start manager")
os.Exit(1)
}
ctx, cancel := context.WithCancel(ctx)

if err := commoncmdoptions.AddCommonChecks(mgr); err != nil {
klog.Error(err, "unable to add common checks")
mgr, err := initManager(ctx, cancel, mgrOpts)
if err != nil {
log.Error(err, "unable to initialize manager")
os.Exit(1)
}

platform, infra, err := util.GetPlatform(ctx, mgr.GetAPIReader())
if err != nil {
klog.Error(err, "unable to get platform")
log.Error(err, "unable to get platform")
os.Exit(1)
}

setupPlatformReconcilers(mgr, opts, infra, platform)
if err := setupPlatformReconcilers(log, mgr, operatorConfig, infra, platform); err != nil {
log.Error(err, "unable to setup platform reconcilers")
os.Exit(1)
}

klog.Info("Starting manager")
log.Info("Starting manager")

if err := mgr.Start(ctx); err != nil {
klog.Error(err, "problem running manager")
log.Error(err, "problem running manager")
os.Exit(1)
}
}

func setupPlatformReconcilers(mgr manager.Manager, opts *commoncmdoptions.CommonOptions, infra *configv1.Infrastructure, platform configv1.PlatformType) {
func setupPlatformReconcilers(log logr.Logger, mgr manager.Manager, operatorConfig commoncmdoptions.OperatorConfig, infra *configv1.Infrastructure, platform configv1.PlatformType) error {
// Only setup reconcile controllers and webhooks when the platform is supported.
// This avoids unnecessary CAPI providers discovery, installs and reconciles when the platform is not supported.
infraTypes, _, err := util.GetCAPITypesForInfrastructure(infra)
if err != nil {
if errors.Is(err, util.ErrUnsupportedPlatform) {
klog.Infof("Detected platform %q is not supported, skipping capi controllers setup", platform)
return
log.Info("Detected platform is not supported, skipping capi controllers setup", "platform", platform)
return nil
}

klog.Error(err, "unable to get infrastructure objects")
os.Exit(1)
return fmt.Errorf("unable to get infrastructure objects: %w", err)
}

if err := setupReconcilers(mgr, operatorConfig, infra, platform, infraTypes.Cluster()); err != nil {
return fmt.Errorf("unable to setup reconcilers: %w", err)
}

if err := setupWebhooks(mgr); err != nil {
return fmt.Errorf("unable to setup webhooks: %w", err)
}

setupReconcilers(mgr, opts, infra, platform, infraTypes.Cluster())
setupWebhooks(mgr)
return nil
}

func setupReconcilers(mgr manager.Manager, opts *commoncmdoptions.CommonOptions, infra *configv1.Infrastructure, platform configv1.PlatformType, infraClusterObject client.Object) {
func setupReconcilers(mgr manager.Manager, operatorConfig commoncmdoptions.OperatorConfig, infra *configv1.Infrastructure, platform configv1.PlatformType, infraClusterObject client.Object) error {
if err := (&corecluster.CoreClusterController{
ClusterOperatorStatusClient: opts.GetClusterOperatorStatusClient(mgr, platform, "cluster-resource"),
ClusterOperatorStatusClient: operatorConfig.GetClusterOperatorStatusClient(mgr, platform, "cluster-resource"),
Cluster: &clusterv1.Cluster{},
Platform: platform,
Infra: infra,
}).SetupWithManager(mgr); err != nil {
klog.Error(err, "unable to create controller", "controller", "CoreCluster")
os.Exit(1)
return fmt.Errorf("unable to create corecluster controller: %w", err)
}

if err := (&secretsync.UserDataSecretController{
ClusterOperatorStatusClient: opts.GetClusterOperatorStatusClient(mgr, platform, "user-data-secret"),
ClusterOperatorStatusClient: operatorConfig.GetClusterOperatorStatusClient(mgr, platform, "user-data-secret"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
klog.Error(err, "unable to create user-data-secret controller", "controller", "UserDataSecret")
os.Exit(1)
return fmt.Errorf("unable to create user-data-secret controller: %w", err)
}

if err := (&kubeconfig.KubeconfigReconciler{
ClusterOperatorStatusClient: opts.GetClusterOperatorStatusClient(mgr, platform, "kubeconfig"),
ClusterOperatorStatusClient: operatorConfig.GetClusterOperatorStatusClient(mgr, platform, "kubeconfig"),
Scheme: mgr.GetScheme(),
RestCfg: mgr.GetConfig(),
}).SetupWithManager(mgr); err != nil {
klog.Error(err, "unable to create controller", "controller", "Kubeconfig")
os.Exit(1)
return fmt.Errorf("unable to create kubeconfig controller: %w", err)
}

if err := (&infracluster.InfraClusterController{
ClusterOperatorStatusClient: opts.GetClusterOperatorStatusClient(mgr, platform, "infracluster"),
ClusterOperatorStatusClient: operatorConfig.GetClusterOperatorStatusClient(mgr, platform, "infracluster"),
Scheme: mgr.GetScheme(),
RestCfg: mgr.GetConfig(),
Platform: platform,
Infra: infra,
}).SetupWithManager(mgr, infraClusterObject); err != nil {
klog.Error(err, "unable to create infracluster controller", "controller", "InfraCluster")
os.Exit(1)
return fmt.Errorf("unable to create infracluster controller: %w", err)
}

return nil
}

func setupWebhooks(mgr ctrl.Manager) {
func setupWebhooks(mgr ctrl.Manager) error {
if err := (&webhook.ClusterWebhook{}).SetupWebhookWithManager(mgr); err != nil {
klog.Error(err, "unable to create webhook", "webhook", "Cluster")
os.Exit(1)
return fmt.Errorf("unable to create webhook: %w", err)
}

return nil
}

func getDefaultCacheOptions(capiNamespace string, sync time.Duration) cache.Options {
Expand Down
75 changes: 29 additions & 46 deletions cmd/capi-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,49 +63,40 @@ func initScheme(scheme *runtime.Scheme) {
}

func main() {
ctx, cancel := context.WithCancel(ctrl.SetupSignalHandler())
cfg := ctrl.GetConfigOrDie()

scheme := runtime.NewScheme()
initScheme(scheme)

opts := commoncmdoptions.InitCommonOptions(managerName, controllers.DefaultOperatorNamespace)

imagesFile := flag.String(
extraflags := flag.NewFlagSet("", flag.ContinueOnError)
imagesFile := extraflags.String(
"images-json",
defaultImagesLocation,
"The location of images file to use by operator for managed CAPI binaries.",
)

opts.Parse()

log := ctrl.Log.WithName("capi-operator")
log, operatorConfig, mgrOpts, initManager, err := commoncmdoptions.InitOperatorConfig(ctx, cfg, scheme, managerName, controllers.DefaultOperatorNamespace, extraflags)
if err != nil {
log.Error(err, "unable to initialize operator config")
os.Exit(1)
}

cacheOpts := cache.Options{
mgrOpts.Cache = cache.Options{
DefaultNamespaces: map[string]cache.Config{
*opts.CAPINamespace: {},
*opts.OperatorNamespace: {},
*operatorConfig.CAPINamespace: {},
*operatorConfig.OperatorNamespace: {},
},
SyncPeriod: ptr.To(10 * time.Minute),
}

mgrOpts, _ := opts.GetCommonManagerOptions()
mgrOpts.Cache = cacheOpts
mgrOpts.Scheme = scheme
mgrOpts.Logger = log

cfg := ctrl.GetConfigOrDie()
ctx, cancel := context.WithCancel(ctrl.SetupSignalHandler())

mgr, err := ctrl.NewManager(cfg, mgrOpts)
mgr, err := initManager(ctx, cancel, mgrOpts)
if err != nil {
log.Error(err, "unable to create manager")
log.Error(err, "unable to initialize manager")
os.Exit(1)
}

if err := commoncmdoptions.AddCommonChecks(mgr); err != nil {
log.Error(err, "unable to add common checks")
os.Exit(1)
}

if err := setupControllers(ctx, log, mgr, opts, *imagesFile, cancel); err != nil {
if err := setupControllers(ctx, log, mgr, operatorConfig, *imagesFile, cancel); err != nil {
log.Error(err, "unable to setup controllers")
os.Exit(1)
}
Expand All @@ -118,7 +109,7 @@ func main() {
}
}

func setupControllers(ctx context.Context, log logr.Logger, mgr ctrl.Manager, opts *commoncmdoptions.CommonOptions, imagesFile string, cancel context.CancelFunc) error {
func setupControllers(ctx context.Context, log logr.Logger, mgr ctrl.Manager, operatorConfig commoncmdoptions.OperatorConfig, imagesFile string, cancel context.CancelFunc) error {
infra, err := util.GetInfra(ctx, mgr.GetAPIReader())
if err != nil {
return fmt.Errorf("unable to get infrastructure: %w", err)
Expand All @@ -137,7 +128,7 @@ func setupControllers(ctx context.Context, log logr.Logger, mgr ctrl.Manager, op
supportedPlatform := util.IsCAPIEnabledForPlatform(featureGates, infra.Status.PlatformStatus.Type)

if err := (&clusteroperator.ClusterOperatorController{
ClusterOperatorStatusClient: opts.GetClusterOperatorStatusClient(mgr, platform, "clusteroperator"),
ClusterOperatorStatusClient: operatorConfig.GetClusterOperatorStatusClient(mgr, platform, "clusteroperator"),
Scheme: mgr.GetScheme(),
IsUnsupportedPlatform: !supportedPlatform,
}).SetupWithManager(mgr); err != nil {
Expand All @@ -157,8 +148,17 @@ func setupControllers(ctx context.Context, log logr.Logger, mgr ctrl.Manager, op
return err
}

if err := setupCapiInstallerController(mgr, log, providerProfiles); err != nil {
return err
if err := (&revision.RevisionController{
Client: mgr.GetClient(),
ProviderProfiles: providerProfiles,
ReleaseVersion: util.GetReleaseVersion(),
}).SetupWithManager(mgr, operatorConfig.TLSOptions); err != nil {
log.Error(err, "unable to create revision controller", "controller", "RevisionController")
return fmt.Errorf("unable to create revision controller: %w", err)
}

if err := installer.SetupWithManager(mgr, providerProfiles); err != nil {
return fmt.Errorf("unable to create installer controller: %w", err)
}

return nil
Expand All @@ -184,20 +184,3 @@ func loadProviderImages(ctx context.Context, mgr ctrl.Manager, imagesFile string

return providerProfiles, nil
}

func setupCapiInstallerController(mgr ctrl.Manager, log logr.Logger, providerProfiles []providerimages.ProviderImageManifests) error {
if err := (&revision.RevisionController{
Client: mgr.GetClient(),
ProviderProfiles: providerProfiles,
ReleaseVersion: util.GetReleaseVersion(),
}).SetupWithManager(mgr); err != nil {
log.Error(err, "unable to create revision controller", "controller", "RevisionController")
return fmt.Errorf("unable to create revision controller: %w", err)
}

if err := installer.SetupWithManager(mgr, providerProfiles); err != nil {
return fmt.Errorf("unable to create installer controller: %w", err)
}

return nil
}
Loading