@@ -167,18 +167,6 @@ func (r *MachineReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr e
167
167
}
168
168
169
169
defer func () {
170
- // Always update the readyCondition with the summary of the machine conditions.
171
- conditions .SetSummary (m ,
172
- conditions .WithConditions (
173
- clusterv1 .BootstrapReadyCondition ,
174
- clusterv1 .InfrastructureReadyCondition ,
175
- // TODO: add MHC conditions here
176
- ),
177
- conditions .WithStepCounterIfOnly (
178
- clusterv1 .BootstrapReadyCondition ,
179
- clusterv1 .InfrastructureReadyCondition ,
180
- ),
181
- )
182
170
183
171
r .reconcilePhase (ctx , m )
184
172
@@ -188,7 +176,7 @@ func (r *MachineReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr e
188
176
if reterr == nil {
189
177
patchOpts = append (patchOpts , patch.WithStatusObservedGeneration {})
190
178
}
191
- if err := patchHelper . Patch (ctx , m , patchOpts ... ); err != nil {
179
+ if err := patchMachine (ctx , patchHelper , m , patchOpts ... ); err != nil {
192
180
reterr = kerrors .NewAggregate ([]error {reterr , err })
193
181
}
194
182
}()
@@ -214,6 +202,37 @@ func (r *MachineReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr e
214
202
return r .reconcile (ctx , cluster , m )
215
203
}
216
204
205
+ func patchMachine (ctx context.Context , patchHelper * patch.Helper , machine * clusterv1.Machine , options ... patch.Option ) error {
206
+ // Always update the readyCondition by summarizing the state of other conditions.
207
+ // A step counter is added to represent progress during the provisioning process (instead we are hiding it
208
+ // after provisioning - e.g. when a MHC condition exists - or during the deletion process).
209
+ conditions .SetSummary (machine ,
210
+ conditions .WithConditions (
211
+ clusterv1 .BootstrapReadyCondition ,
212
+ clusterv1 .InfrastructureReadyCondition ,
213
+ // TODO: add MHC conditions here
214
+ ),
215
+ conditions .WithStepCounterIf (machine .ObjectMeta .DeletionTimestamp .IsZero ()),
216
+ conditions .WithStepCounterIfOnly (
217
+ clusterv1 .BootstrapReadyCondition ,
218
+ clusterv1 .InfrastructureReadyCondition ,
219
+ ),
220
+ )
221
+
222
+ // Patch the object, ignoring conflicts on the conditions owned by this controller.
223
+ // Also, if requested, we are adding additional options like e.g. Patch ObservedGeneration when issuing the
224
+ // patch at the end of the reconcile loop.
225
+ options = append (options ,
226
+ patch.WithOwnedConditions {Conditions : []clusterv1.ConditionType {
227
+ clusterv1 .ReadyCondition ,
228
+ clusterv1 .BootstrapReadyCondition ,
229
+ clusterv1 .InfrastructureReadyCondition ,
230
+ }},
231
+ )
232
+
233
+ return patchHelper .Patch (ctx , machine , options ... )
234
+ }
235
+
217
236
func (r * MachineReconciler ) reconcile (ctx context.Context , cluster * clusterv1.Cluster , m * clusterv1.Machine ) (ctrl.Result , error ) {
218
237
logger := r .Log .WithValues ("machine" , m .Name , "namespace" , m .Namespace )
219
238
logger = logger .WithValues ("cluster" , cluster .Name )
@@ -275,13 +294,26 @@ func (r *MachineReconciler) reconcileDelete(ctx context.Context, cluster *cluste
275
294
if annotations .HasWithPrefix (clusterv1 .PreDrainDeleteHookAnnotationPrefix , m .ObjectMeta .Annotations ) {
276
295
return ctrl.Result {}, nil
277
296
}
278
- // Drain node before deletion.
297
+ // Drain node before deletion and issue a patch in order to make this operation visible to the users .
279
298
if _ , exists := m .ObjectMeta .Annotations [clusterv1 .ExcludeNodeDrainingAnnotation ]; ! exists {
299
+ patchHelper , err := patch .NewHelper (m , r .Client )
300
+ if err != nil {
301
+ return ctrl.Result {}, err
302
+ }
303
+
280
304
logger .Info ("Draining node" , "node" , m .Status .NodeRef .Name )
305
+ conditions .MarkFalse (m , clusterv1 .DrainingSucceededCondition , "Draining" , clusterv1 .DrainingReason , "Draining the node before deletion" )
306
+ if err := patchMachine (ctx , patchHelper , m ); err != nil {
307
+ return ctrl.Result {}, errors .Wrap (err , "failed to patch Machine" )
308
+ }
309
+
281
310
if err := r .drainNode (ctx , cluster , m .Status .NodeRef .Name , m .Name ); err != nil {
311
+ conditions .MarkFalse (m , clusterv1 .DrainingSucceededCondition , clusterv1 .DrainingFailedReason , clusterv1 .ConditionSeverityWarning , err .Error ())
282
312
r .recorder .Eventf (m , corev1 .EventTypeWarning , "FailedDrainNode" , "error draining Machine's node %q: %v" , m .Status .NodeRef .Name , err )
283
313
return ctrl.Result {}, err
284
314
}
315
+
316
+ conditions .MarkTrue (m , clusterv1 .DrainingSucceededCondition )
285
317
r .recorder .Eventf (m , corev1 .EventTypeNormal , "SuccessfulDrainNode" , "success draining Machine's node %q" , m .Status .NodeRef .Name )
286
318
}
287
319
}
@@ -292,9 +324,14 @@ func (r *MachineReconciler) reconcileDelete(ctx context.Context, cluster *cluste
292
324
return ctrl.Result {}, nil
293
325
}
294
326
295
- if ok , err := r .reconcileDeleteExternal (ctx , m ); ! ok || err != nil {
296
- // Return early and don't remove the finalizer if we got an error or
297
- // the external reconciliation deletion isn't ready.
327
+ // Return early and don't remove the finalizer if we got an error or
328
+ // the external reconciliation deletion isn't ready.
329
+
330
+ if ok , err := r .reconcileDeleteInfrastructure (ctx , m ); ! ok || err != nil {
331
+ return ctrl.Result {}, err
332
+ }
333
+
334
+ if ok , err := r .reconcileDeleteBootstrap (ctx , m ); ! ok || err != nil {
298
335
return ctrl.Result {}, err
299
336
}
300
337
@@ -441,41 +478,70 @@ func (r *MachineReconciler) deleteNode(ctx context.Context, cluster *clusterv1.C
441
478
return nil
442
479
}
443
480
444
- // reconcileDeleteExternal tries to delete external references, returning true if it cannot find any.
445
- func (r * MachineReconciler ) reconcileDeleteExternal (ctx context.Context , m * clusterv1.Machine ) (bool , error ) {
446
- objects := []* unstructured.Unstructured {}
447
- references := []* corev1.ObjectReference {
448
- m .Spec .Bootstrap .ConfigRef ,
449
- & m .Spec .InfrastructureRef ,
481
+ func (r * MachineReconciler ) reconcileDeleteBootstrap (ctx context.Context , m * clusterv1.Machine ) (bool , error ) {
482
+ obj , err := r .reconcileDeleteExternal (ctx , m , m .Spec .Bootstrap .ConfigRef )
483
+ if err != nil {
484
+ return false , err
450
485
}
451
486
452
- // Loop over the references and try to retrieve it with the client.
453
- for _ , ref := range references {
454
- if ref == nil {
455
- continue
456
- }
487
+ if obj == nil {
488
+ // Marks the bootstrap as deleted
489
+ conditions . MarkFalse ( m , clusterv1 . BootstrapReadyCondition , clusterv1 . DeletedReason , clusterv1 . ConditionSeverityInfo , "" )
490
+ return true , nil
491
+ }
457
492
458
- obj , err := external .Get (ctx , r .Client , ref , m .Namespace )
459
- if err != nil && ! apierrors .IsNotFound (errors .Cause (err )) {
460
- return false , errors .Wrapf (err , "failed to get %s %q for Machine %q in namespace %q" ,
461
- ref .GroupVersionKind (), ref .Name , m .Name , m .Namespace )
462
- }
463
- if obj != nil {
464
- objects = append (objects , obj )
465
- }
493
+ // Report a summary of current status of the bootstrap object defined for this machine.
494
+ conditions .SetMirror (m , clusterv1 .BootstrapReadyCondition ,
495
+ conditions .UnstructuredGetter (obj ),
496
+ conditions .WithFallbackValue (false , clusterv1 .DeletingReason , clusterv1 .ConditionSeverityInfo , "" ),
497
+ )
498
+ return false , nil
499
+ }
500
+
501
+ func (r * MachineReconciler ) reconcileDeleteInfrastructure (ctx context.Context , m * clusterv1.Machine ) (bool , error ) {
502
+ obj , err := r .reconcileDeleteExternal (ctx , m , & m .Spec .InfrastructureRef )
503
+ if err != nil {
504
+ return false , err
505
+ }
506
+
507
+ if obj == nil {
508
+ // Marks the infrastructure as deleted
509
+ conditions .MarkFalse (m , clusterv1 .InfrastructureReadyCondition , clusterv1 .DeletedReason , clusterv1 .ConditionSeverityInfo , "" )
510
+ return true , nil
511
+ }
512
+
513
+ // Report a summary of current status of the bootstrap object defined for this machine.
514
+ conditions .SetMirror (m , clusterv1 .InfrastructureReadyCondition ,
515
+ conditions .UnstructuredGetter (obj ),
516
+ conditions .WithFallbackValue (false , clusterv1 .DeletingReason , clusterv1 .ConditionSeverityInfo , "" ),
517
+ )
518
+ return false , nil
519
+ }
520
+
521
+ // reconcileDeleteExternal tries to delete external references.
522
+ func (r * MachineReconciler ) reconcileDeleteExternal (ctx context.Context , m * clusterv1.Machine , ref * corev1.ObjectReference ) (* unstructured.Unstructured , error ) {
523
+ if ref == nil {
524
+ return nil , nil
525
+ }
526
+
527
+ // get the external object
528
+ obj , err := external .Get (ctx , r .Client , ref , m .Namespace )
529
+ if err != nil && ! apierrors .IsNotFound (errors .Cause (err )) {
530
+ return nil , errors .Wrapf (err , "failed to get %s %q for Machine %q in namespace %q" ,
531
+ ref .GroupVersionKind (), ref .Name , m .Name , m .Namespace )
466
532
}
467
533
468
- // Issue a delete request for any object that has been found.
469
- for _ , obj := range objects {
534
+ if obj != nil {
535
+ // Issue a delete request.
470
536
if err := r .Client .Delete (ctx , obj ); err != nil && ! apierrors .IsNotFound (err ) {
471
- return false , errors .Wrapf (err ,
537
+ return obj , errors .Wrapf (err ,
472
538
"failed to delete %v %q for Machine %q in namespace %q" ,
473
539
obj .GroupVersionKind (), obj .GetName (), m .Name , m .Namespace )
474
540
}
475
541
}
476
542
477
543
// Return true if there are no more external objects.
478
- return len ( objects ) == 0 , nil
544
+ return obj , nil
479
545
}
480
546
481
547
func (r * MachineReconciler ) shouldAdopt (m * clusterv1.Machine ) bool {
0 commit comments