@@ -174,59 +174,60 @@ func (r *ReconcileMachineSet) Reconcile(ctx context.Context, request reconcile.R
174174 }
175175
176176 if r .gate .Enabled (featuregate .Feature (openshiftfeatures .FeatureGateMachineAPIMigration )) {
177- machineSetName := machineSet .GetName ()
178- machineSetCopy := machineSet .DeepCopy ()
179- // Check Status.AuthoritativeAPI. If it's not set to MachineAPI. Set the
180- // paused condition true and return early.
181- //
182- // Once we have a webhook, we want to remove the check that the AuthoritativeAPI
183- // field is populated.
184- if machineSet .Status .AuthoritativeAPI != "" &&
185- machineSet .Status .AuthoritativeAPI != machinev1 .MachineAuthorityMachineAPI {
186- conditions .Set (machineSetCopy , conditions .TrueConditionWithReason (
187- machine .PausedCondition ,
188- machine .PausedConditionReason ,
189- "The AuthoritativeAPI is set to %s" , string (machineSet .Status .AuthoritativeAPI ),
190- ))
191-
192- _ , err := updateMachineSetStatus (r .Client , machineSet , machineSetCopy .Status )
193- if err != nil && ! apierrors .IsNotFound (err ) {
194- klog .Errorf ("%v: error updating status: %v" , machineSetName , err )
195- return reconcile.Result {}, fmt .Errorf ("error updating status: %w" , err )
196- } else if apierrors .IsNotFound (err ) {
197- return reconcile.Result {}, nil
177+ switch machineSet .Status .AuthoritativeAPI {
178+ case "" :
179+ // An empty .status.authoritativeAPI normally means the resource has not yet been reconciled
180+ // by the migration controller, which has the responsibility for propagating .spec.authoritativeAPI to the status.
181+ // Pause the resource and take no further action but return until that field is populated.
182+ desiredCondition := conditions .TrueConditionWithReason (
183+ machine .PausedCondition , machine .PausedConditionReason ,
184+ "The AuthoritativeAPI status is not yet set" ,
185+ )
186+
187+ if _ , err := r .ensureUpdatedPausedCondition (machineSet , desiredCondition ,
188+ fmt .Sprintf ("%v: machine set .status.authoritativeAPI is not yet set, ensuring machine set is paused" , machineSet .Name )); err != nil {
189+ return reconcile.Result {}, fmt .Errorf ("failed to ensure paused condition: %w" , err )
198190 }
191+ klog .Infof ("%v: machine set is paused, taking no further action" , machineSet .Name )
199192
200- klog .Infof ("%v: machine set is paused, taking no further action" , machineSetName )
201193 return reconcile.Result {}, nil
202- }
203194
204- var pausedFalseReason string
205- if machineSet .Status .AuthoritativeAPI != "" {
206- pausedFalseReason = fmt .Sprintf ("The AuthoritativeAPI is set to %s" , string (machineSet .Status .AuthoritativeAPI ))
207- } else {
208- pausedFalseReason = "The AuthoritativeAPI is not set"
209- }
195+ case machinev1 .MachineAuthorityClusterAPI , machinev1 .MachineAuthorityMigrating :
196+ // In case .status.authoritativeAPI is set to machinev1.MachineAuthorityClusterAPI, machinev1.MachineAuthorityMigrating
197+ // the resource should be paused and not reconciled further.
198+ desiredCondition := conditions .TrueConditionWithReason (
199+ machine .PausedCondition , machine .PausedConditionReason ,
200+ "The AuthoritativeAPI status is set to '%s'" , string (machineSet .Status .AuthoritativeAPI ),
201+ )
202+
203+ if _ , err := r .ensureUpdatedPausedCondition (machineSet , desiredCondition ,
204+ fmt .Sprintf ("%v: machine set .status.authoritativeAPI is set to '%s', ensuring machine set is paused" , machineSet .Name , machineSet .Status .AuthoritativeAPI )); err != nil {
205+ return reconcile.Result {}, fmt .Errorf ("failed to ensure paused condition: %w" , err )
206+ }
210207
211- // Set the paused condition to false, continue reconciliation
212- conditions .Set (machineSetCopy , conditions .FalseCondition (
213- machine .PausedCondition ,
214- machine .NotPausedConditionReason ,
215- machinev1 .ConditionSeverityInfo ,
216- "%s" ,
217- pausedFalseReason ,
218- ))
208+ klog .Infof ("%v: machine set is paused, taking no further action" , machineSet .Name )
219209
220- var err error
221- machineSet , err = updateMachineSetStatus (r .Client , machineSet , machineSetCopy .Status )
222- if err != nil && ! apierrors .IsNotFound (err ) {
223- klog .Errorf ("%v: error updating status: %v" , machineSetName , err )
224- return reconcile.Result {}, fmt .Errorf ("error updating status: %w" , err )
225- } else if apierrors .IsNotFound (err ) {
226210 return reconcile.Result {}, nil
227- }
228211
229- klog .Infof ("%v: setting paused to false and continuing reconcile" , machineSetName )
212+ case machinev1 .MachineAuthorityMachineAPI :
213+ // The authority is MachineAPI and the resource should not be paused.
214+ desiredCondition := conditions .FalseCondition (
215+ machine .PausedCondition , machine .NotPausedConditionReason , machinev1 .ConditionSeverityInfo , "%s" ,
216+ fmt .Sprintf ("The AuthoritativeAPI status is set to '%s'" , string (machineSet .Status .AuthoritativeAPI )),
217+ )
218+
219+ if updated , err := r .ensureUpdatedPausedCondition (machineSet , desiredCondition ,
220+ fmt .Sprintf ("%v: machine set .status.authoritativeAPI is set to '%s', unpausing machine set" , machineSet .Name , machineSet .Status .AuthoritativeAPI )); err != nil {
221+ return reconcile.Result {}, fmt .Errorf ("failed to ensure paused condition: %w" , err )
222+ } else if updated {
223+ klog .Infof ("%v: setting machine set paused condition to false" , machineSet .Name )
224+ }
225+
226+ // Fallthrough and continue reconciliation.
227+ default :
228+ klog .Errorf ("%v: invalid .status.authoritativeAPI '%s'" , machineSet .Name , machineSet .Status .AuthoritativeAPI )
229+ return reconcile.Result {}, nil // Do not return an error to avoid immediate requeue.
230+ }
230231 }
231232
232233 result , err := r .reconcile (ctx , machineSet )
@@ -329,6 +330,23 @@ func (r *ReconcileMachineSet) reconcile(ctx context.Context, machineSet *machine
329330 return reconcile.Result {}, nil
330331}
331332
333+ // ensureUpdatedPausedCondition updates the paused condition if needed.
334+ func (r * ReconcileMachineSet ) ensureUpdatedPausedCondition (ms * machinev1.MachineSet , desiredCondition * machinev1.Condition , logMessage string ) (bool , error ) {
335+ newMs := ms .DeepCopy ()
336+ if ! conditions .IsEquivalentTo (conditions .Get (ms , machine .PausedCondition ), desiredCondition ) {
337+ klog .Info (logMessage )
338+ conditions .Set (newMs , desiredCondition )
339+ if _ , err := updateMachineSetStatus (r .Client , ms , newMs .Status ); err != nil {
340+ klog .Errorf ("%v: error updating status: %v" , newMs .Name , err )
341+ return false , fmt .Errorf ("error updating status for machine set %s: %w" , newMs .Name , err )
342+ }
343+
344+ return true , nil
345+ }
346+
347+ return false , nil
348+ }
349+
332350// syncReplicas essentially scales machine resources up and down.
333351func (r * ReconcileMachineSet ) syncReplicas (ms * machinev1.MachineSet , machines []* machinev1.Machine ) error {
334352 if ms .Spec .Replicas == nil {
0 commit comments