diff --git a/cmd/cluster-version-operator/start.go b/cmd/cluster-version-operator/start.go index cfc73bc32..1c523ab05 100644 --- a/cmd/cluster-version-operator/start.go +++ b/cmd/cluster-version-operator/start.go @@ -31,6 +31,7 @@ func init() { cmd.PersistentFlags().StringVar(&opts.ListenAddr, "listen", opts.ListenAddr, "Address to listen on for metrics") cmd.PersistentFlags().StringVar(&opts.Kubeconfig, "kubeconfig", opts.Kubeconfig, "Kubeconfig file to access a remote cluster (testing only)") + cmd.PersistentFlags().StringVar(&opts.ConfigFile, "config-file", opts.ConfigFile, "Configuration file for the CVO (represented by a clusterversionoperators.operator.openshift.io manifest file). DevPreview functionality.") cmd.PersistentFlags().StringVar(&opts.NodeName, "node-name", opts.NodeName, "kubernetes node name CVO is scheduled on.") cmd.PersistentFlags().BoolVar(&opts.EnableAutoUpdate, "enable-auto-update", opts.EnableAutoUpdate, "Enables the autoupdate controller.") cmd.PersistentFlags().StringVar(&opts.ReleaseImage, "release-image", opts.ReleaseImage, "The Openshift release image url.") diff --git a/pkg/cvo/cvo.go b/pkg/cvo/cvo.go index a043ce972..06a31262d 100644 --- a/pkg/cvo/cvo.go +++ b/pkg/cvo/cvo.go @@ -183,6 +183,9 @@ type Operator struct { // always be implicitly enabled. alwaysEnableCapabilities []configv1.ClusterVersionCapability + // configFile is a path to a ClusterVersionOperator configuration file + configFile string + // configuration, if enabled, reconciles the ClusterVersionOperator configuration. configuration *configuration.ClusterVersionOperatorConfiguration } @@ -209,6 +212,7 @@ func New( promqlTarget clusterconditions.PromQLTarget, injectClusterIdIntoPromQL bool, updateService string, + configFile string, alwaysEnableCapabilities []configv1.ClusterVersionCapability, ) (*Operator, error) { eventBroadcaster := record.NewBroadcaster() @@ -237,6 +241,7 @@ func New( availableUpdatesQueue: workqueue.NewTypedRateLimitingQueueWithConfig[any](workqueue.DefaultTypedControllerRateLimiter[any](), workqueue.TypedRateLimitingQueueConfig[any]{Name: "availableupdates"}), upgradeableQueue: workqueue.NewTypedRateLimitingQueueWithConfig[any](workqueue.DefaultTypedControllerRateLimiter[any](), workqueue.TypedRateLimitingQueueConfig[any]{Name: "upgradeable"}), + configFile: configFile, hypershift: hypershift, exclude: exclude, clusterProfile: clusterProfile, @@ -463,7 +468,7 @@ func (optr *Operator) Run(runContext context.Context, shutdownContext context.Co resultChannel <- asyncResult{name: "available updates"} }() - if optr.shouldReconcileCVOConfiguration() { + if optr.shouldReconcileCVOConfiguration() && optr.configFile == "" { resultChannelCount++ go func() { defer utilruntime.HandleCrash() @@ -477,7 +482,20 @@ func (optr *Operator) Run(runContext context.Context, shutdownContext context.Co resultChannel <- asyncResult{name: "cvo configuration"} }() } else { - klog.Infof("The ClusterVersionOperatorConfiguration feature gate is disabled or HyperShift is detected; the configuration sync routine will not run.") + klog.Infof("The ClusterVersionOperatorConfiguration feature gate is disabled, HyperShift is detected or --config-file flag is used; the configuration sync routine will not run.") + } + + if optr.enabledFeatureGates.CVOConfiguration() && optr.configFile != "" { + resultChannelCount++ + go func() { + defer utilruntime.HandleCrash() + wait.UntilWithContext(runContext, func(_ context.Context) { + klog.V(4).Infof("Syncing configuration file") + }, time.Second*15) + resultChannel <- asyncResult{name: "cvo configuration file"} + }() + } else { + klog.Infof("The ClusterVersionOperatorConfiguration feature gate is disabled or --config-file flag is not used; the configuration file sync routine will not run.") } resultChannelCount++ diff --git a/pkg/start/start.go b/pkg/start/start.go index 6fb92c684..471a0faf4 100644 --- a/pkg/start/start.go +++ b/pkg/start/start.go @@ -64,6 +64,7 @@ type Options struct { ServingKeyFile string Kubeconfig string + ConfigFile string NodeName string ListenAddr string @@ -517,6 +518,7 @@ func (o *Options) NewControllerContext(cb *ClientBuilder) (*Context, error) { o.PromQLTarget, o.InjectClusterIdIntoPromQL, o.UpdateService, + o.ConfigFile, stringsToCapabilities(o.AlwaysEnableCapabilities), ) if err != nil {