@@ -35,7 +35,6 @@ import (
3535 configv1 "github.com/openshift/api/config/v1"
3636 clientset "github.com/openshift/client-go/config/clientset/versioned"
3737 configinformers "github.com/openshift/client-go/config/informers/externalversions"
38- configlistersv1 "github.com/openshift/client-go/config/listers/config/v1"
3938 operatorclientset "github.com/openshift/client-go/operator/clientset/versioned"
4039 operatorinformers "github.com/openshift/client-go/operator/informers/externalversions"
4140 "github.com/openshift/library-go/pkg/config/clusterstatus"
@@ -190,13 +189,13 @@ func (o *Options) Run(ctx context.Context) error {
190189 }
191190
192191 clusterVersionConfigInformerFactory , configInformerFactory := o .prepareConfigInformerFactories (cb )
193- _ , _ , err = o .processInitialFeatureGate (ctx , configInformerFactory )
192+ startingFeatureSet , startingCvoGates , err : = o .processInitialFeatureGate (ctx , configInformerFactory )
194193 if err != nil {
195194 return fmt .Errorf ("error processing feature gates: %w" , err )
196195 }
197196
198197 // initialize the controllers and attempt to load the payload information
199- controllerCtx , err := o .NewControllerContext (cb , clusterVersionConfigInformerFactory , configInformerFactory )
198+ controllerCtx , err := o .NewControllerContext (cb , startingFeatureSet , startingCvoGates , clusterVersionConfigInformerFactory , configInformerFactory )
200199 if err != nil {
201200 return err
202201 }
@@ -244,7 +243,7 @@ func (o *Options) getOpenShiftVersion() string {
244243 return releaseMetadata .Version
245244}
246245
247- func (o * Options ) processInitialFeatureGate (ctx context.Context , configInformerFactory configinformers.SharedInformerFactory ) (configv1.FeatureSet , * featuregates.CvoGates , error ) {
246+ func (o * Options ) processInitialFeatureGate (ctx context.Context , configInformerFactory configinformers.SharedInformerFactory ) (configv1.FeatureSet , featuregates.CvoGates , error ) {
248247 featureGates := configInformerFactory .Config ().V1 ().FeatureGates ().Lister ()
249248 configInformerFactory .Start (ctx .Done ())
250249 configInformerFactory .WaitForCacheSync (ctx .Done ())
@@ -256,8 +255,8 @@ func (o *Options) processInitialFeatureGate(ctx context.Context, configInformerF
256255 var clusterFeatureGate * configv1.FeatureGate
257256
258257 // client-go automatically retries some network blip errors on GETs for 30s by default, and we want to
259- // retry the remaining ones ourselves. If we fail longer than that, the operator won't be able to do work
260- // anyway. Return the error and crashloop.
258+ // retry the remaining ones ourselves. If we fail longer than that, CVO won't be able to do work anyway.
259+ // Return the error and crashloop.
261260 //
262261 // We implement the timeout with a context because the timeout in PollImmediateWithContext does not behave
263262 // well when ConditionFunc takes longer time to execute, like here where the GET can be retried by client-go
@@ -284,17 +283,17 @@ func (o *Options) processInitialFeatureGate(ctx context.Context, configInformerF
284283 }
285284 }); err != nil {
286285 if lastError != nil {
287- return "" , nil , lastError
286+ return "" , cvoGates , lastError
288287 }
289- return "" , nil , err
288+ return "" , cvoGates , err
290289 }
291290
292291 if cvoGates .UnknownVersion () {
293292 klog .Warningf ("CVO features for version %s could not be detected from FeatureGate; will use defaults plus special UnknownVersion feature gate" , cvoOpenShiftVersion )
294293 }
295294 klog .Infof ("CVO features for version %s enabled at startup: %+v" , cvoOpenShiftVersion , cvoGates )
296295
297- return startingFeatureSet , & cvoGates , nil
296+ return startingFeatureSet , cvoGates , nil
298297}
299298
300299// run launches a number of goroutines to handle manifest application,
@@ -362,7 +361,7 @@ func (o *Options) run(ctx context.Context, controllerCtx *Context, lock resource
362361 resultChannel <- asyncResult {name : "metrics server" , error : err }
363362 }()
364363 }
365- if err := controllerCtx .InitializeFromPayload (runContext , restConfig , burstRestConfig ); err != nil {
364+ if err := controllerCtx .CVO . InitializeFromPayload (runContext , restConfig , burstRestConfig ); err != nil {
366365 if firstError == nil {
367366 firstError = err
368367 }
@@ -577,13 +576,17 @@ type Context struct {
577576 // OperatorInformerFactory should be used to get informers / listers for code that works with resources from the
578577 // operator.openshift.io group
579578 OperatorInformerFactory operatorinformers.SharedInformerFactory
580-
581- fgLister configlistersv1.FeatureGateLister
582579}
583580
584581// NewControllerContext initializes the default Context for the current Options. It does
585582// not start any background processes.
586- func (o * Options ) NewControllerContext (cb * ClientBuilder , clusterVersionConfigInformerFactory , configInformerFactory configinformers.SharedInformerFactory ) (* Context , error ) {
583+ func (o * Options ) NewControllerContext (
584+ cb * ClientBuilder ,
585+ startingFeatureSet configv1.FeatureSet ,
586+ startingCvoGates featuregates.CvoGates ,
587+ clusterVersionConfigInformerFactory ,
588+ configInformerFactory configinformers.SharedInformerFactory ,
589+ ) (* Context , error ) {
587590 kubeClient := cb .KubeClientOrDie (internal .ConfigNamespace , useProtobuf )
588591 openshiftConfigInformerFactory := coreinformers .NewSharedInformerFactoryWithOptions (kubeClient , resyncPeriod (o .ResyncInterval ), coreinformers .WithNamespace (internal .ConfigNamespace ))
589592 openshiftConfigManagedInformerFactory := coreinformers .NewSharedInformerFactoryWithOptions (kubeClient , resyncPeriod (o .ResyncInterval ), coreinformers .WithNamespace (internal .ConfigManagedNamespace ))
@@ -621,12 +624,14 @@ func (o *Options) NewControllerContext(cb *ClientBuilder, clusterVersionConfigIn
621624 o .InjectClusterIdIntoPromQL ,
622625 o .UpdateService ,
623626 stringsToCapabilities (o .AlwaysEnableCapabilities ),
627+ startingFeatureSet ,
628+ startingCvoGates ,
624629 )
625630 if err != nil {
626631 return nil , err
627632 }
628633
629- featureChangeStopper , err := featuregates .NewChangeStopper (configInformerFactory .Config ().V1 ().FeatureGates ())
634+ featureChangeStopper , err := featuregates .NewChangeStopper (configInformerFactory .Config ().V1 ().FeatureGates (), startingFeatureSet , startingCvoGates )
630635 if err != nil {
631636 return nil , err
632637 }
@@ -639,8 +644,6 @@ func (o *Options) NewControllerContext(cb *ClientBuilder, clusterVersionConfigIn
639644 OperatorInformerFactory : operatorInformerFactory ,
640645 CVO : cvo ,
641646 StopOnFeatureGateChange : featureChangeStopper ,
642-
643- fgLister : configInformerFactory .Config ().V1 ().FeatureGates ().Lister (),
644647 }
645648
646649 if o .EnableAutoUpdate {
@@ -663,70 +666,6 @@ func (o *Options) NewControllerContext(cb *ClientBuilder, clusterVersionConfigIn
663666 return ctx , nil
664667}
665668
666- // InitializeFromPayload initializes the CVO and FeatureGate ChangeStoppers controllers from the payload. It extracts the
667- // current CVO version from the initial payload and uses it to determine the initial the required featureset and enabled
668- // feature gates. Both the payload and determined feature information are used to initialize CVO and feature gate
669- // ChangeStopper controllers.
670- func (c * Context ) InitializeFromPayload (ctx context.Context , restConfig * rest.Config , burstRestConfig * rest.Config ) error {
671- var startingFeatureSet configv1.FeatureSet
672- var clusterFeatureGate * configv1.FeatureGate
673-
674- // client-go automatically retries some network blip errors on GETs for 30s by default, and we want to
675- // retry the remaining ones ourselves. If we fail longer than that, the operator won't be able to do work
676- // anyway. Return the error and crashloop.
677- //
678- // We implement the timeout with a context because the timeout in PollImmediateWithContext does not behave
679- // well when ConditionFunc takes longer time to execute, like here where the GET can be retried by client-go
680- var lastError error
681- if err := wait .PollUntilContextTimeout (context .Background (), 2 * time .Second , 25 * time .Second , true , func (ctx context.Context ) (bool , error ) {
682- gate , fgErr := c .fgLister .Get ("cluster" )
683- switch {
684- case apierrors .IsNotFound (fgErr ):
685- // if we have no featuregates, then the cluster is using the default featureset, which is "".
686- // This excludes everything that could possibly depend on a different feature set.
687- startingFeatureSet = ""
688- klog .Infof ("FeatureGate not found in cluster, using default feature set %q at startup" , startingFeatureSet )
689- return true , nil
690- case fgErr != nil :
691- lastError = fgErr
692- klog .Warningf ("Failed to get FeatureGate from cluster: %v" , fgErr )
693- return false , nil
694- default :
695- clusterFeatureGate = gate
696- startingFeatureSet = gate .Spec .FeatureSet
697- klog .Infof ("FeatureGate found in cluster, using its feature set %q at startup" , startingFeatureSet )
698- return true , nil
699- }
700- }); err != nil {
701- if lastError != nil {
702- return lastError
703- }
704- return err
705- }
706-
707- payload , err := c .CVO .LoadInitialPayload (ctx , startingFeatureSet , restConfig )
708- if err != nil {
709- return err
710- }
711-
712- var cvoGates featuregates.CvoGates
713- if clusterFeatureGate != nil {
714- cvoGates = featuregates .CvoGatesFromFeatureGate (clusterFeatureGate , payload .Release .Version )
715- } else {
716- cvoGates = featuregates .DefaultCvoGates (payload .Release .Version )
717- }
718-
719- if cvoGates .UnknownVersion () {
720- klog .Infof ("CVO features for version %s could not be detected from FeatureGate; will use defaults plus special UnknownVersion feature gate" , payload .Release .Version )
721- }
722- klog .Infof ("CVO features for version %s enabled at startup: %+v" , payload .Release .Version , cvoGates )
723-
724- c .StopOnFeatureGateChange .SetStartingFeatures (startingFeatureSet , cvoGates )
725- c .CVO .InitializeFromPayload (payload , startingFeatureSet , cvoGates , restConfig , burstRestConfig )
726-
727- return nil
728- }
729-
730669func stringsToCapabilities (names []string ) []configv1.ClusterVersionCapability {
731670 caps := make ([]configv1.ClusterVersionCapability , len (names ))
732671 for i , c := range names {
0 commit comments