package lumperctl import ( "fmt" "os" "github.com/go-logr/logr" ggcrlog "github.com/google/go-containerregistry/pkg/logs" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" whv1 "edge-infra.dev/pkg/f8n/warehouse/k8s/apis/v1alpha2" "edge-infra.dev/pkg/f8n/warehouse/k8s/controllers/lumperctl/internal" "edge-infra.dev/pkg/k8s/runtime/controller" "edge-infra.dev/pkg/k8s/runtime/controller/metrics" "edge-infra.dev/pkg/lib/fog" "edge-infra.dev/pkg/lib/runtime/version" ) // Run creates the manager, sets up the controller, and then starts // everything. Errors are returned for handling in package main. func Run(opts ...controller.Option) error { // use the controller's logger to write logs produced by imported pkgs SetPackageLoggers(fog.New()) log := ctrl.Log.WithName("startup") log.Info("version", "version", version.New().String()) // create config first, so that controller-runtime flags are parsed when // we create the manager cfg, err := newConfig(os.Args[1:]) if err != nil { log.Error(err, "failed to instantiate config") return err } healthzChecker := internal.New(ctrl.Log.WithName("lumper-liveness")) mgrCreator := CreateMgr(healthzChecker) mgr, err := mgrCreator(opts...) if err != nil { log.Error(err, "failed to create manager") return err } ctx := ctrl.SetupSignalHandler() if err := cfg.afterParse(ctx, mgr.GetClient()); err != nil { log.Error(err, "failed to compute config values after parsing") return err } // TODO: this always prints '{}'. either export fields or remove log.Info("parsed options", "config", cfg) if err := RegisterControllers(mgr, cfg, healthzChecker); err != nil { log.Error(err, "failed to register controllers") return err } log.Info("starting manager") if err := mgr.Start(ctx); err != nil { log.Error(err, "manager encountered a fatal error") return err } return nil } func CreateMgr(healthzChecker *internal.LivenessChecker) func(o ...controller.Option) (ctrl.Manager, error) { return func(o ...controller.Option) (ctrl.Manager, error) { cfg, opts := controller.ProcessOptions(o...) opts.LeaderElectionID = "lumperctl20ds.edge.ncr.com" opts.Scheme = createScheme() opts.HealthProbeBindAddress = ":8082" mgr, err := ctrl.NewManager(cfg, opts) if err != nil { return nil, err } if err := mgr.AddHealthzCheck("lumper-status", healthzChecker.Check); err != nil { return nil, fmt.Errorf("failed to set up Liveness Check: %w", err) } return mgr, nil } } // registerControllers instantiates each reconciler for this controller and // registers it with the input controller manager func RegisterControllers(mgr ctrl.Manager, cfg *Config, healthzChecker *internal.LivenessChecker) error { metrics := metrics.New(mgr, "lpctl", metrics.WithSuspend(), metrics.WithReason(), metrics.WithCollectors( internal.CacheReadOpsMetric, internal.CacheLenMetric, internal.EdgeVersionMetric, ), ) if err := (&UnpackedPalletReconciler{ Reconciler: &internal.Reconciler{ OwnerGroupLabel: whv1.UnpackedPalletLabel, Conditions: unpackedPalletConditions, Metrics: metrics, Cache: cfg.Cache, Provider: cfg.Provider, LivenessChecker: healthzChecker, }, }).SetupWithManager(mgr, cfg.UpCfg); err != nil { return fmt.Errorf("failed to set up UnpackedPalletReconciler: %w", err) } if err := (&ShipmentReconciler{ Reconciler: &internal.Reconciler{ OwnerGroupLabel: whv1.ShipmentLabel, Conditions: shipmentConditions, Metrics: metrics, Cache: cfg.Cache, Provider: cfg.Provider, LivenessChecker: healthzChecker, }, }).SetupWithManager(mgr, cfg.ShipCfg); err != nil { return fmt.Errorf("failed to set up ShipmentReconciler: %w", err) } return nil } func createScheme() *runtime.Scheme { scheme := runtime.NewScheme() utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(whv1.AddToScheme(scheme)) return scheme } func SetPackageLoggers(log logr.Logger) { ctrl.SetLogger(log) // inject log adapters for ggcr so errors and diagnostic logs it produces are // written the same as other controller logs. by default, this package discards // all log messages gcr := "go-containerregistry" ggcrlog.Debug.SetOutput(fog.InfoWriter(log, gcr)) ggcrlog.Progress.SetOutput(fog.InfoWriter(log, gcr)) ggcrlog.Warn.SetOutput(fog.ErrorWriter(log, gcr)) }