@@ -26,6 +26,7 @@ import (
2626
2727 // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2828 // to ensure that exec-entrypoint and run can make use of them.
29+ "k8s.io/client-go/kubernetes"
2930 _ "k8s.io/client-go/plugin/pkg/client/auth"
3031
3132 "k8s.io/apimachinery/pkg/runtime"
@@ -40,6 +41,11 @@ import (
4041 metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
4142
4243 configv1 "github.com/openshift/api/config/v1"
44+ "github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
45+ "github.com/openshift/library-go/pkg/operator/events"
46+
47+ configv1client "github.com/openshift/client-go/config/clientset/versioned"
48+ configinformers "github.com/openshift/client-go/config/informers/externalversions"
4349
4450 "github.com/openshift/cluster-cloud-controller-manager-operator/pkg/controllers"
4551 "github.com/openshift/cluster-cloud-controller-manager-operator/pkg/restmapper"
@@ -79,6 +85,12 @@ func main() {
7985 "The namespace for managed objects, target cloud-conf in particular." ,
8086 )
8187
88+ recorderName := "cloud-controller-manager-operator-cloud-config-sync-controller"
89+ missingVersion := "0.0.1-snapshot"
90+ desiredVersion := controllers .GetReleaseVersion ()
91+ sharedClock := clock.RealClock {}
92+ ctx := ctrl .SetupSignalHandler ()
93+
8294 // Once all the flags are regitered, switch to pflag
8395 // to allow leader lection flags to be bound
8496 pflag .CommandLine .AddGoFlagSet (flag .CommandLine )
@@ -131,7 +143,36 @@ func main() {
131143 os .Exit (1 )
132144 }
133145
134- sharedClock := clock.RealClock {}
146+ // Feature gate accessor
147+ configClient , err := configv1client .NewForConfig (mgr .GetConfig ())
148+ if err != nil {
149+ setupLog .Error (err , "unable to create config client" )
150+ os .Exit (1 )
151+ }
152+ kubeClient , err := kubernetes .NewForConfig (mgr .GetConfig ())
153+ if err != nil {
154+ setupLog .Error (err , "unable to create kube client" )
155+ os .Exit (1 )
156+ }
157+
158+ configInformers := configinformers .NewSharedInformerFactory (configClient , 10 * time .Minute )
159+ controllerRef , err := events .GetControllerReferenceForCurrentPod (ctx , kubeClient , * managedNamespace , nil )
160+ if err != nil {
161+ klog .Warningf ("unable to get owner reference (falling back to namespace): %v" , err )
162+ }
163+
164+ featureGateAccessor := featuregates .NewFeatureGateAccess (
165+ desiredVersion , missingVersion ,
166+ configInformers .Config ().V1 ().ClusterVersions (), configInformers .Config ().V1 ().FeatureGates (),
167+ events .NewKubeRecorder (kubeClient .CoreV1 ().Events (* managedNamespace ), recorderName , controllerRef , sharedClock ),
168+ )
169+ featureGateAccessor .SetChangeHandler (func (featureChange featuregates.FeatureChange ) {
170+ // Do nothing here. The controller watches feature gate changes and will react to them.
171+ klog .InfoS ("FeatureGates changed" , "enabled" , featureChange .New .Enabled , "disabled" , featureChange .New .Disabled )
172+ })
173+ go featureGateAccessor .Run (ctx )
174+ go configInformers .Start (ctx .Done ())
175+
135176 if err = (& controllers.CloudConfigReconciler {
136177 ClusterOperatorStatusClient : controllers.ClusterOperatorStatusClient {
137178 Client : mgr .GetClient (),
@@ -140,7 +181,8 @@ func main() {
140181 ReleaseVersion : controllers .GetReleaseVersion (),
141182 ManagedNamespace : * managedNamespace ,
142183 },
143- Scheme : mgr .GetScheme (),
184+ Scheme : mgr .GetScheme (),
185+ FeatureGateAccess : featureGateAccessor ,
144186 }).SetupWithManager (mgr ); err != nil {
145187 setupLog .Error (err , "unable to create cloud-config sync controller" , "controller" , "ClusterOperator" )
146188 os .Exit (1 )
@@ -171,7 +213,7 @@ func main() {
171213 }
172214
173215 setupLog .Info ("starting manager" )
174- if err := mgr .Start (ctrl . SetupSignalHandler () ); err != nil {
216+ if err := mgr .Start (ctx ); err != nil {
175217 setupLog .Error (err , "problem running manager" )
176218 os .Exit (1 )
177219 }
0 commit comments