Skip to content

Commit 0fcaf58

Browse files
committed
MCO-1661: Introduce FeatureGatesHandler across MCO
This commit replaces plain accesses to FeatureGateAccess with proper usages of the new FeatureGatesHandler and simplifies most of the error checks needed in the previous approach.
1 parent 1f99680 commit 0fcaf58

36 files changed

+342
-603
lines changed

cmd/machine-config-controller/start.go

Lines changed: 41 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"flag"
66
"fmt"
77
"os"
8-
"time"
98

109
features "github.com/openshift/api/features"
1110
"github.com/openshift/machine-config-operator/cmd/common"
@@ -82,7 +81,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
8281
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
8382
ctrlctx.ClientBuilder.KubeClientOrDie("node-update-controller"),
8483
ctrlctx.ClientBuilder.MachineConfigClientOrDie("node-update-controller"),
85-
ctrlctx.FeatureGateAccess,
84+
ctrlctx.FeatureGatesHandler,
8685
)
8786

8887
certrotationcontroller, err := certrotationcontroller.New(
@@ -108,56 +107,46 @@ func runStartCmd(_ *cobra.Command, _ []string) {
108107

109108
close(ctrlctx.InformersStarted)
110109

111-
select {
112-
case <-ctrlctx.FeatureGateAccess.InitialFeatureGatesObserved():
113-
fg, err := ctrlctx.FeatureGateAccess.CurrentFeatureGates()
114-
if err != nil {
115-
klog.Fatalf("unable to get initial features: %v", err)
116-
}
117-
118-
enabled, disabled := ctrlcommon.GetEnabledDisabledFeatures(fg)
119-
klog.Infof("FeatureGates initialized: enabled=%v disabled=%v", enabled, disabled)
120-
if fg.Enabled(features.FeatureGatePinnedImages) && fg.Enabled(features.FeatureGateMachineConfigNodes) {
121-
pinnedImageSet := pinnedimageset.New(
122-
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
123-
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
124-
ctrlctx.ClientBuilder.KubeClientOrDie("pinned-image-set-controller"),
125-
ctrlctx.ClientBuilder.MachineConfigClientOrDie("pinned-image-set-controller"),
126-
)
127-
128-
go pinnedImageSet.Run(2, ctrlctx.Stop)
129-
// start the informers again to enable feature gated types.
130-
// see comments in SharedInformerFactory interface.
131-
ctrlctx.InformerFactory.Start(ctrlctx.Stop)
132-
}
110+
if fgErr := ctrlctx.FeatureGatesHandler.Connect(ctx); fgErr != nil {
111+
klog.Fatal(fmt.Errorf("failed to connect to feature gates %w", fgErr))
112+
}
133113

134-
if ctrlcommon.IsBootImageControllerRequired(ctrlctx) {
135-
machineSetBootImage := machinesetbootimage.New(
136-
ctrlctx.ClientBuilder.KubeClientOrDie("machine-set-boot-image-controller"),
137-
ctrlctx.ClientBuilder.MachineClientOrDie("machine-set-boot-image-controller"),
138-
ctrlctx.KubeNamespacedInformerFactory.Core().V1().ConfigMaps(),
139-
ctrlctx.MachineInformerFactory.Machine().V1beta1().MachineSets(),
140-
ctrlctx.ConfigInformerFactory.Config().V1().Infrastructures(),
141-
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
142-
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),
143-
ctrlctx.FeatureGateAccess,
144-
)
145-
go machineSetBootImage.Run(ctrlctx.Stop)
146-
// start the informers again to enable feature gated types.
147-
// see comments in SharedInformerFactory interface.
148-
ctrlctx.KubeNamespacedInformerFactory.Start(ctrlctx.Stop)
149-
ctrlctx.MachineInformerFactory.Start(ctrlctx.Stop)
150-
ctrlctx.ConfigInformerFactory.Start(ctrlctx.Stop)
151-
ctrlctx.OperatorInformerFactory.Start(ctrlctx.Stop)
152-
}
114+
if ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGatePinnedImages) && ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGateMachineConfigNodes) {
115+
pinnedImageSet := pinnedimageset.New(
116+
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
117+
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
118+
ctrlctx.ClientBuilder.KubeClientOrDie("pinned-image-set-controller"),
119+
ctrlctx.ClientBuilder.MachineConfigClientOrDie("pinned-image-set-controller"),
120+
)
121+
122+
go pinnedImageSet.Run(2, ctrlctx.Stop)
123+
// start the informers again to enable feature gated types.
124+
// see comments in SharedInformerFactory interface.
125+
ctrlctx.InformerFactory.Start(ctrlctx.Stop)
126+
}
153127

154-
if fg.Enabled(features.FeatureGateOnClusterBuild) {
155-
ctrlctx.OCLInformerFactory.Start(ctrlctx.Stop)
156-
}
128+
if ctrlcommon.IsBootImageControllerRequired(ctrlctx) {
129+
machineSetBootImage := machinesetbootimage.New(
130+
ctrlctx.ClientBuilder.KubeClientOrDie("machine-set-boot-image-controller"),
131+
ctrlctx.ClientBuilder.MachineClientOrDie("machine-set-boot-image-controller"),
132+
ctrlctx.KubeNamespacedInformerFactory.Core().V1().ConfigMaps(),
133+
ctrlctx.MachineInformerFactory.Machine().V1beta1().MachineSets(),
134+
ctrlctx.ConfigInformerFactory.Config().V1().Infrastructures(),
135+
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
136+
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),
137+
ctrlctx.FeatureGatesHandler,
138+
)
139+
go machineSetBootImage.Run(ctrlctx.Stop)
140+
// start the informers again to enable feature gated types.
141+
// see comments in SharedInformerFactory interface.
142+
ctrlctx.KubeNamespacedInformerFactory.Start(ctrlctx.Stop)
143+
ctrlctx.MachineInformerFactory.Start(ctrlctx.Stop)
144+
ctrlctx.ConfigInformerFactory.Start(ctrlctx.Stop)
145+
ctrlctx.OperatorInformerFactory.Start(ctrlctx.Stop)
146+
}
157147

158-
case <-time.After(1 * time.Minute):
159-
klog.Errorf("timed out waiting for FeatureGate detection")
160-
os.Exit(1)
148+
if ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGateOnClusterBuild) {
149+
ctrlctx.OCLInformerFactory.Start(ctrlctx.Stop)
161150
}
162151

163152
for _, c := range controllers {
@@ -215,7 +204,7 @@ func createControllers(ctx *ctrlcommon.ControllerContext) []ctrlcommon.Controlle
215204
ctx.ClientBuilder.KubeClientOrDie("kubelet-config-controller"),
216205
ctx.ClientBuilder.MachineConfigClientOrDie("kubelet-config-controller"),
217206
ctx.ClientBuilder.ConfigClientOrDie("kubelet-config-controller"),
218-
ctx.FeatureGateAccess,
207+
ctx.FeatureGatesHandler,
219208
),
220209
containerruntimeconfig.New(
221210
rootOpts.templates,
@@ -231,7 +220,7 @@ func createControllers(ctx *ctrlcommon.ControllerContext) []ctrlcommon.Controlle
231220
ctx.ClientBuilder.KubeClientOrDie("container-runtime-config-controller"),
232221
ctx.ClientBuilder.MachineConfigClientOrDie("container-runtime-config-controller"),
233222
ctx.ClientBuilder.ConfigClientOrDie("container-runtime-config-controller"),
234-
ctx.FeatureGateAccess,
223+
ctx.FeatureGatesHandler,
235224
),
236225
// The renderer creates "rendered" MCs from the MC fragments generated by
237226
// the above sub-controllers, which are then consumed by the node controller
@@ -255,7 +244,7 @@ func createControllers(ctx *ctrlcommon.ControllerContext) []ctrlcommon.Controlle
255244
ctx.ConfigInformerFactory.Config().V1().Schedulers(),
256245
ctx.ClientBuilder.KubeClientOrDie("node-update-controller"),
257246
ctx.ClientBuilder.MachineConfigClientOrDie("node-update-controller"),
258-
ctx.FeatureGateAccess,
247+
ctx.FeatureGatesHandler,
259248
),
260249
)
261250

cmd/machine-config-daemon/start.go

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import (
44
"context"
55
"errors"
66
"flag"
7+
"fmt"
78
"net/url"
89
"os"
910
"time"
1011

12+
"github.com/openshift/api/features"
13+
1114
"k8s.io/apimachinery/pkg/api/resource"
1215
"k8s.io/client-go/tools/clientcmd"
1316

14-
features "github.com/openshift/api/features"
1517
"github.com/openshift/machine-config-operator/internal/clients"
1618
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
1719
"github.com/openshift/machine-config-operator/pkg/daemon"
@@ -190,7 +192,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
190192
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
191193
startOpts.kubeletHealthzEnabled,
192194
startOpts.kubeletHealthzEndpoint,
193-
ctrlctx.FeatureGateAccess,
195+
ctrlctx.FeatureGatesHandler,
194196
)
195197
if err != nil {
196198
klog.Fatalf("Failed to initialize: %v", err)
@@ -204,46 +206,38 @@ func runStartCmd(_ *cobra.Command, _ []string) {
204206
ctrlctx.OperatorInformerFactory.Start(stopCh)
205207
close(ctrlctx.InformersStarted)
206208

207-
select {
208-
case <-ctrlctx.FeatureGateAccess.InitialFeatureGatesObserved():
209-
// ok to start the rest of the informers now that we have observed the initial feature gates
209+
if fgErr := ctrlctx.FeatureGatesHandler.Connect(ctx); fgErr != nil {
210+
klog.Fatal(fmt.Errorf("failed to connect to feature gates %w", fgErr))
211+
}
210212

211-
featureGates, err := ctrlctx.FeatureGateAccess.CurrentFeatureGates()
213+
// ok to start the rest of the informers now that we have observed the initial feature gates
214+
if ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGatePinnedImages) && ctrlctx.FeatureGatesHandler.Enabled(features.FeatureGateMachineConfigNodes) {
215+
klog.Infof("Feature enabled: %s", features.FeatureGatePinnedImages)
216+
criClient, err := cri.NewClient(ctx, constants.DefaultCRIOSocketPath)
212217
if err != nil {
213-
klog.Fatalf("Could not get FG: %v", err)
214-
} else {
215-
klog.Infof("FeatureGates initialized: knownFeatureGates=%v", featureGates.KnownFeatures())
216-
if featureGates.Enabled(features.FeatureGatePinnedImages) && featureGates.Enabled(features.FeatureGateMachineConfigNodes) {
217-
klog.Infof("Feature enabled: %s", features.FeatureGatePinnedImages)
218-
criClient, err := cri.NewClient(ctx, constants.DefaultCRIOSocketPath)
219-
if err != nil {
220-
klog.Fatalf("Failed to initialize CRI client: %v", err)
221-
}
222-
223-
prefetchTimeout := 2 * time.Minute
224-
pinnedImageSetManager := daemon.NewPinnedImageSetManager(
225-
startOpts.nodeName,
226-
criClient,
227-
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
228-
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
229-
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
230-
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
231-
resource.MustParse(constants.MinFreeStorageAfterPrefetch),
232-
constants.DefaultCRIOSocketPath,
233-
constants.KubeletAuthFile,
234-
constants.ContainerRegistryConfPath,
235-
prefetchTimeout,
236-
ctrlctx.FeatureGateAccess,
237-
)
238-
239-
go pinnedImageSetManager.Run(2, stopCh)
240-
// start the informers for the pinned image set again after the feature gate is enabled this is allowed.
241-
// see comments in SharedInformerFactory interface.
242-
ctrlctx.InformerFactory.Start(stopCh)
243-
}
218+
klog.Fatalf("Failed to initialize CRI client: %v", err)
244219
}
245-
case <-time.After(1 * time.Minute):
246-
klog.Fatalf("Could not get FG, timed out: %v", err)
220+
221+
prefetchTimeout := 2 * time.Minute
222+
pinnedImageSetManager := daemon.NewPinnedImageSetManager(
223+
startOpts.nodeName,
224+
criClient,
225+
ctrlctx.ClientBuilder.MachineConfigClientOrDie(componentName),
226+
ctrlctx.InformerFactory.Machineconfiguration().V1().PinnedImageSets(),
227+
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
228+
ctrlctx.InformerFactory.Machineconfiguration().V1().MachineConfigPools(),
229+
resource.MustParse(constants.MinFreeStorageAfterPrefetch),
230+
constants.DefaultCRIOSocketPath,
231+
constants.KubeletAuthFile,
232+
constants.ContainerRegistryConfPath,
233+
prefetchTimeout,
234+
ctrlctx.FeatureGatesHandler,
235+
)
236+
237+
go pinnedImageSetManager.Run(2, stopCh)
238+
// start the informers for the pinned image set again after the feature gate is enabled this is allowed.
239+
// see comments in SharedInformerFactory interface.
240+
ctrlctx.InformerFactory.Start(stopCh)
247241
}
248242

249243
if err := dn.Run(stopCh, exitCh, errCh); err != nil {

cmd/machine-config-operator/start.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package main
33
import (
44
"context"
55
"flag"
6+
"fmt"
67
"os"
7-
"time"
88

99
"github.com/openshift/machine-config-operator/cmd/common"
1010
"github.com/openshift/machine-config-operator/internal/clients"
@@ -100,7 +100,7 @@ func runStartCmd(_ *cobra.Command, _ []string) {
100100
ctrlctx.ConfigInformerFactory.Config().V1().ClusterOperators(),
101101
ctrlctx.ClientBuilder.OperatorClientOrDie(componentName),
102102
ctrlctx.OperatorInformerFactory.Operator().V1().MachineConfigurations(),
103-
ctrlctx.FeatureGateAccess,
103+
ctrlctx.FeatureGatesHandler,
104104
ctrlctx.InformerFactory.Machineconfiguration().V1().KubeletConfigs(),
105105
ctrlctx.InformerFactory.Machineconfiguration().V1().ContainerRuntimeConfigs(),
106106
ctrlctx.ConfigInformerFactory.Config().V1().Nodes(),
@@ -122,16 +122,8 @@ func runStartCmd(_ *cobra.Command, _ []string) {
122122

123123
close(ctrlctx.InformersStarted)
124124

125-
select {
126-
case <-ctrlctx.FeatureGateAccess.InitialFeatureGatesObserved():
127-
featureGates, err := ctrlctx.FeatureGateAccess.CurrentFeatureGates()
128-
if err != nil {
129-
klog.Fatalf("Could not get FG: %v", err)
130-
} else {
131-
klog.Infof("FeatureGates initialized: knownFeatureGates=%v", featureGates.KnownFeatures())
132-
}
133-
case <-time.After(1 * time.Minute):
134-
klog.Fatalf("Could not get FG, timed out: %v", err)
125+
if fgErr := ctrlctx.FeatureGatesHandler.Connect(ctx); fgErr != nil {
126+
klog.Fatal(fmt.Errorf("failed to connect to feature gates %w", fgErr))
135127
}
136128

137129
go controller.Run(2, ctrlctx.Stop)

pkg/controller/bootstrap/bootstrap.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
apicfgv1alpha1 "github.com/openshift/api/config/v1alpha1"
2323
mcfgv1 "github.com/openshift/api/machineconfiguration/v1"
2424
apioperatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1"
25-
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
2625
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
2726
containerruntimeconfig "github.com/openshift/machine-config-operator/pkg/controller/container-runtime-config"
2827
kubeletconfig "github.com/openshift/machine-config-operator/pkg/controller/kubelet-config"
@@ -170,9 +169,9 @@ func (b *Bootstrap) Run(destDir string) error {
170169
return fmt.Errorf("error: no featuregate found in dir: %q", b.manifestDir)
171170
}
172171

173-
fgAccess, err := featuregates.NewHardcodedFeatureGateAccessFromFeatureGate(featureGate, version.ReleaseVersion)
172+
fgHandler, err := ctrlcommon.NewFeatureGatesCRHandlerImpl(featureGate, version.ReleaseVersion)
174173
if err != nil {
175-
return fmt.Errorf("error creating feature gate access: %w", err)
174+
return fmt.Errorf("error creating feature gates handler: %w", err)
176175
}
177176

178177
iconfigs, err := template.RunBootstrap(b.templatesDir, cconfig, psraw, apiServer)
@@ -183,7 +182,7 @@ func (b *Bootstrap) Run(destDir string) error {
183182

184183
configs = append(configs, iconfigs...)
185184

186-
rconfigs, err := containerruntimeconfig.RunImageBootstrap(b.templatesDir, cconfig, pools, icspRules, idmsRules, itmsRules, imgCfg, clusterImagePolicies, imagePolicies, fgAccess)
185+
rconfigs, err := containerruntimeconfig.RunImageBootstrap(b.templatesDir, cconfig, pools, icspRules, idmsRules, itmsRules, imgCfg, clusterImagePolicies, imagePolicies, fgHandler)
187186
if err != nil {
188187
return err
189188
}
@@ -201,7 +200,7 @@ func (b *Bootstrap) Run(destDir string) error {
201200
klog.Infof("Successfully generated MachineConfigs from containerruntime.")
202201

203202
if featureGate != nil {
204-
featureConfigs, err := kubeletconfig.RunFeatureGateBootstrap(b.templatesDir, fgAccess, nodeConfig, cconfig, pools, apiServer)
203+
featureConfigs, err := kubeletconfig.RunFeatureGateBootstrap(b.templatesDir, fgHandler, nodeConfig, cconfig, pools, apiServer)
205204
if err != nil {
206205
return err
207206
}
@@ -218,7 +217,7 @@ func (b *Bootstrap) Run(destDir string) error {
218217
}
219218
}
220219
if nodeConfig != nil {
221-
nodeConfigs, err := kubeletconfig.RunNodeConfigBootstrap(b.templatesDir, fgAccess, cconfig, nodeConfig, pools, apiServer)
220+
nodeConfigs, err := kubeletconfig.RunNodeConfigBootstrap(b.templatesDir, fgHandler, cconfig, nodeConfig, pools, apiServer)
222221
if err != nil {
223222
return err
224223
}
@@ -227,7 +226,7 @@ func (b *Bootstrap) Run(destDir string) error {
227226
klog.Infof("Successfully generated MachineConfigs from node.Configs.")
228227

229228
if len(kconfigs) > 0 {
230-
kconfigs, err := kubeletconfig.RunKubeletBootstrap(b.templatesDir, kconfigs, cconfig, fgAccess, nodeConfig, pools, apiServer)
229+
kconfigs, err := kubeletconfig.RunKubeletBootstrap(b.templatesDir, kconfigs, cconfig, fgHandler, nodeConfig, pools, apiServer)
231230
if err != nil {
232231
return err
233232
}

pkg/controller/common/controller_context.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ type ControllerContext struct {
6565
ImageInformerFactory imageinformers.SharedInformerFactory
6666
RouteInformerFactory routeinformers.SharedInformerFactory
6767

68-
FeatureGateAccess featuregates.FeatureGateAccess
68+
FeatureGatesHandler FeatureGatesHandler
6969

7070
AvailableResources map[schema.GroupVersionResource]bool
7171

@@ -136,7 +136,6 @@ func CreateControllerContext(ctx context.Context, cb *clients.Builder) *Controll
136136
configSharedInformer.Config().V1().ClusterVersions(), configSharedInformer.Config().V1().FeatureGates(),
137137
recorder,
138138
)
139-
140139
go featureGateAccessor.Run(ctx)
141140

142141
return &ControllerContext{
@@ -157,7 +156,7 @@ func CreateControllerContext(ctx context.Context, cb *clients.Builder) *Controll
157156
InformersStarted: make(chan struct{}),
158157
ResyncPeriod: resyncPeriod(),
159158
KubeMAOSharedInformer: kubeMAOSharedInformer,
160-
FeatureGateAccess: featureGateAccessor,
159+
FeatureGatesHandler: NewFeatureGatesAccessHandler(featureGateAccessor),
161160
ImageInformerFactory: imageSharedInformer,
162161
RouteInformerFactory: routeSharedInformer,
163162
}

0 commit comments

Comments
 (0)