Skip to content

Commit 01fad60

Browse files
Merge pull request #243 from abhinavdahiya/feature-prevent-upgrade
Bug 1730401: prevent automatic upgrades for clusters with cluster operators reporting Upgradeable false
2 parents b0ce53c + aceb5bc commit 01fad60

File tree

12 files changed

+1756
-11
lines changed

12 files changed

+1756
-11
lines changed

pkg/cvo/cvo.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import (
3737
"github.com/openshift/cluster-version-operator/pkg/cvo/internal/dynamicclient"
3838
"github.com/openshift/cluster-version-operator/pkg/internal"
3939
"github.com/openshift/cluster-version-operator/pkg/payload"
40+
"github.com/openshift/cluster-version-operator/pkg/payload/precondition"
41+
preconditioncv "github.com/openshift/cluster-version-operator/pkg/payload/precondition/clusterversion"
4042
"github.com/openshift/cluster-version-operator/pkg/verify"
4143
)
4244

@@ -113,11 +115,18 @@ type Operator struct {
113115
queue workqueue.RateLimitingInterface
114116
// availableUpdatesQueue tracks checking for updates from the update server.
115117
availableUpdatesQueue workqueue.RateLimitingInterface
118+
// upgradeableQueue tracks checking for upgradeable.
119+
upgradeableQueue workqueue.RateLimitingInterface
116120

117121
// statusLock guards access to modifying available updates
118122
statusLock sync.Mutex
119123
availableUpdates *availableUpdates
120124

125+
// upgradeableStatusLock guards access to modifying Upgradeable conditions
126+
upgradeableStatusLock sync.Mutex
127+
upgradeable *upgradeable
128+
upgradeableChecks []upgradeableCheck
129+
121130
// verifier, if provided, will be used to check an update before it is executed.
122131
// Any error will prevent an update payload from being accessed.
123132
verifier verify.Interface
@@ -171,11 +180,9 @@ func New(
171180

172181
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "clusterversion"),
173182
availableUpdatesQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "availableupdates"),
183+
upgradeableQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "upgradeable"),
174184
}
175185

176-
optr.proxyLister = proxyInformer.Lister()
177-
proxyInformer.Informer().AddEventHandler(optr.eventHandler())
178-
179186
cvInformer.Informer().AddEventHandler(optr.eventHandler())
180187

181188
optr.coLister = coInformer.Lister()
@@ -184,8 +191,12 @@ func New(
184191
optr.cvLister = cvInformer.Lister()
185192
optr.cacheSynced = append(optr.cacheSynced, cvInformer.Informer().HasSynced)
186193

194+
optr.proxyLister = proxyInformer.Lister()
187195
optr.cmConfigLister = cmConfigInformer.Lister().ConfigMaps(internal.ConfigNamespace)
188196

197+
// make sure this is initialized after all the listers are initialized
198+
optr.upgradeableChecks = optr.defaultUpgradeableChecks()
199+
189200
if enableMetrics {
190201
if err := optr.registerMetrics(coInformer.Informer()); err != nil {
191202
panic(err)
@@ -225,9 +236,10 @@ func (optr *Operator) InitializeFromPayload(restConfig *rest.Config, burstRestCo
225236

226237
// after the verifier has been loaded, initialize the sync worker with a payload retriever
227238
// which will consume the verifier
228-
optr.configSync = NewSyncWorker(
239+
optr.configSync = NewSyncWorkerWithPreconditions(
229240
optr.defaultPayloadRetriever(),
230241
NewResourceBuilder(restConfig, burstRestConfig, optr.coLister),
242+
optr.defaultPreconditionChecks(),
231243
optr.minimumUpdateCheckInterval,
232244
wait.Backoff{
233245
Duration: time.Second * 10,
@@ -263,6 +275,7 @@ func (optr *Operator) Run(ctx context.Context, workers int) {
263275
go runThrottledStatusNotifier(stopCh, optr.statusInterval, 2, optr.configSync.StatusCh(), func() { optr.queue.Add(optr.queueKey()) })
264276
go optr.configSync.Start(ctx, 16)
265277
go wait.Until(func() { optr.worker(optr.availableUpdatesQueue, optr.availableUpdatesSync) }, time.Second, stopCh)
278+
go wait.Until(func() { optr.worker(optr.upgradeableQueue, optr.upgradeableSync) }, time.Second, stopCh)
266279
go wait.Until(func() {
267280
defer close(workerStopCh)
268281

@@ -292,10 +305,12 @@ func (optr *Operator) eventHandler() cache.ResourceEventHandler {
292305
AddFunc: func(obj interface{}) {
293306
optr.queue.Add(workQueueKey)
294307
optr.availableUpdatesQueue.Add(workQueueKey)
308+
optr.upgradeableQueue.Add(workQueueKey)
295309
},
296310
UpdateFunc: func(old, new interface{}) {
297311
optr.queue.Add(workQueueKey)
298312
optr.availableUpdatesQueue.Add(workQueueKey)
313+
optr.upgradeableQueue.Add(workQueueKey)
299314
},
300315
DeleteFunc: func(obj interface{}) {
301316
optr.queue.Add(workQueueKey)
@@ -432,6 +447,29 @@ func (optr *Operator) availableUpdatesSync(key string) error {
432447
return optr.syncAvailableUpdates(config)
433448
}
434449

450+
// upgradeableSync is triggered on cluster version change (and periodic requeues) to
451+
// sync upgradeableCondition. It only modifies cluster version.
452+
func (optr *Operator) upgradeableSync(key string) error {
453+
startTime := time.Now()
454+
klog.V(4).Infof("Started syncing upgradeable %q (%v)", key, startTime)
455+
defer func() {
456+
klog.V(4).Infof("Finished syncing upgradeable %q (%v)", key, time.Since(startTime))
457+
}()
458+
459+
config, err := optr.cvLister.Get(optr.name)
460+
if apierrors.IsNotFound(err) {
461+
return nil
462+
}
463+
if err != nil {
464+
return err
465+
}
466+
if errs := validation.ValidateClusterVersion(config); len(errs) > 0 {
467+
return nil
468+
}
469+
470+
return optr.syncUpgradeable(config)
471+
}
472+
435473
// isOlderThanLastUpdate returns true if the cluster version is older than
436474
// the last update we saw.
437475
func (optr *Operator) isOlderThanLastUpdate(config *configv1.ClusterVersion) bool {
@@ -608,3 +646,9 @@ func hasReachedLevel(cv *configv1.ClusterVersion, desired configv1.Update) bool
608646
}
609647
return desired.Image == cv.Status.History[0].Image
610648
}
649+
650+
func (optr *Operator) defaultPreconditionChecks() precondition.List {
651+
return []precondition.Precondition{
652+
preconditioncv.NewUpgradeable(optr.cvLister),
653+
}
654+
}

0 commit comments

Comments
 (0)