@@ -36,6 +36,7 @@ import (
36
36
"sigs.k8s.io/cluster-api/controllers/remote"
37
37
"sigs.k8s.io/cluster-api/util"
38
38
"sigs.k8s.io/cluster-api/util/annotations"
39
+ "sigs.k8s.io/cluster-api/util/collections"
39
40
"sigs.k8s.io/cluster-api/util/conditions"
40
41
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
41
42
"sigs.k8s.io/cluster-api/util/patch"
@@ -143,7 +144,7 @@ func (r *MachineSetReconciler) Reconcile(ctx context.Context, req ctrl.Request)
143
144
144
145
defer func () {
145
146
// Always attempt to patch the object and status after each reconciliation.
146
- if err := patchHelper . Patch (ctx , machineSet ); err != nil {
147
+ if err := patchMachineSet (ctx , patchHelper , machineSet ); err != nil {
147
148
reterr = kerrors .NewAggregate ([]error {reterr , err })
148
149
}
149
150
}()
@@ -162,6 +163,28 @@ func (r *MachineSetReconciler) Reconcile(ctx context.Context, req ctrl.Request)
162
163
return result , err
163
164
}
164
165
166
+ func patchMachineSet (ctx context.Context , patchHelper * patch.Helper , machineSet * clusterv1.MachineSet , options ... patch.Option ) error {
167
+ // Always update the readyCondition by summarizing the state of other conditions.
168
+ conditions .SetSummary (machineSet ,
169
+ conditions .WithConditions (
170
+ clusterv1 .MachinesCreatedCondition ,
171
+ clusterv1 .ResizedCondition ,
172
+ clusterv1 .MachinesReadyCondition ,
173
+ ),
174
+ )
175
+
176
+ // Patch the object, ignoring conflicts on the conditions owned by this controller.
177
+ options = append (options ,
178
+ patch.WithOwnedConditions {Conditions : []clusterv1.ConditionType {
179
+ clusterv1 .ReadyCondition ,
180
+ clusterv1 .MachinesCreatedCondition ,
181
+ clusterv1 .ResizedCondition ,
182
+ clusterv1 .MachinesReadyCondition ,
183
+ }},
184
+ )
185
+ return patchHelper .Patch (ctx , machineSet , options ... )
186
+ }
187
+
165
188
func (r * MachineSetReconciler ) reconcile (ctx context.Context , cluster * clusterv1.Cluster , machineSet * clusterv1.MachineSet ) (ctrl.Result , error ) {
166
189
log := ctrl .LoggerFrom (ctx )
167
190
log .V (4 ).Info ("Reconcile MachineSet" )
@@ -350,6 +373,7 @@ func (r *MachineSetReconciler) syncReplicas(ctx context.Context, ms *clusterv1.M
350
373
Labels : machine .Labels ,
351
374
})
352
375
if err != nil {
376
+ conditions .MarkFalse (ms , clusterv1 .MachinesCreatedCondition , clusterv1 .BootstrapTemplateCloningFailedReason , clusterv1 .ConditionSeverityError , err .Error ())
353
377
return errors .Wrapf (err , "failed to clone bootstrap configuration for MachineSet %q in namespace %q" , ms .Name , ms .Namespace )
354
378
}
355
379
machine .Spec .Bootstrap .ConfigRef = bootstrapRef
@@ -364,6 +388,7 @@ func (r *MachineSetReconciler) syncReplicas(ctx context.Context, ms *clusterv1.M
364
388
Annotations : machine .Annotations ,
365
389
})
366
390
if err != nil {
391
+ conditions .MarkFalse (ms , clusterv1 .MachinesCreatedCondition , clusterv1 .InfrastructureTemplateCloningFailedReason , clusterv1 .ConditionSeverityError , err .Error ())
367
392
return errors .Wrapf (err , "failed to clone infrastructure configuration for MachineSet %q in namespace %q" , ms .Name , ms .Namespace )
368
393
}
369
394
machine .Spec .InfrastructureRef = * infraRef
@@ -372,6 +397,8 @@ func (r *MachineSetReconciler) syncReplicas(ctx context.Context, ms *clusterv1.M
372
397
log .Error (err , "Unable to create Machine" , "machine" , machine .Name )
373
398
r .recorder .Eventf (ms , corev1 .EventTypeWarning , "FailedCreate" , "Failed to create machine %q: %v" , machine .Name , err )
374
399
errs = append (errs , err )
400
+ conditions .MarkFalse (ms , clusterv1 .MachinesCreatedCondition , clusterv1 .MachineCreationFailedReason ,
401
+ clusterv1 .ConditionSeverityError , err .Error ())
375
402
376
403
// Try to cleanup the external objects if the Machine creation failed.
377
404
if err := r .Client .Delete (ctx , util .ObjectReferenceToUnstructured (* infraRef )); ! apierrors .IsNotFound (err ) {
@@ -601,6 +628,7 @@ func (r *MachineSetReconciler) updateStatus(ctx context.Context, cluster *cluste
601
628
fullyLabeledReplicasCount := 0
602
629
readyReplicasCount := 0
603
630
availableReplicasCount := 0
631
+ desiredReplicas := * ms .Spec .Replicas
604
632
templateLabel := labels .Set (ms .Spec .Template .Labels ).AsSelectorPreValidated ()
605
633
606
634
for _ , machine := range filteredMachines {
@@ -644,12 +672,35 @@ func (r *MachineSetReconciler) updateStatus(ctx context.Context, cluster *cluste
644
672
newStatus .DeepCopyInto (& ms .Status )
645
673
646
674
log .V (4 ).Info (fmt .Sprintf ("Updating status for %v: %s/%s, " , ms .Kind , ms .Namespace , ms .Name ) +
647
- fmt .Sprintf ("replicas %d->%d (need %d), " , ms .Status .Replicas , newStatus .Replicas , * ms . Spec . Replicas ) +
675
+ fmt .Sprintf ("replicas %d->%d (need %d), " , ms .Status .Replicas , newStatus .Replicas , desiredReplicas ) +
648
676
fmt .Sprintf ("fullyLabeledReplicas %d->%d, " , ms .Status .FullyLabeledReplicas , newStatus .FullyLabeledReplicas ) +
649
677
fmt .Sprintf ("readyReplicas %d->%d, " , ms .Status .ReadyReplicas , newStatus .ReadyReplicas ) +
650
678
fmt .Sprintf ("availableReplicas %d->%d, " , ms .Status .AvailableReplicas , newStatus .AvailableReplicas ) +
651
679
fmt .Sprintf ("sequence No: %v->%v" , ms .Status .ObservedGeneration , newStatus .ObservedGeneration ))
652
680
}
681
+ switch {
682
+ // We are scaling up
683
+ case newStatus .Replicas < desiredReplicas :
684
+ conditions .MarkFalse (ms , clusterv1 .ResizedCondition , clusterv1 .ScalingUpReason , clusterv1 .ConditionSeverityWarning , "Scaling up MachineSet to %d replicas (actual %d)" , desiredReplicas , newStatus .Replicas )
685
+ // We are scaling down
686
+ case newStatus .Replicas > desiredReplicas :
687
+ conditions .MarkFalse (ms , clusterv1 .ResizedCondition , clusterv1 .ScalingDownReason , clusterv1 .ConditionSeverityWarning , "Scaling down MachineSet to %d replicas (actual %d)" , desiredReplicas , newStatus .Replicas )
688
+ // This means that there was no error in generating the desired number of machine objects
689
+ conditions .MarkTrue (ms , clusterv1 .MachinesCreatedCondition )
690
+ default :
691
+ // Make sure last resize operation is marked as completed.
692
+ // NOTE: we are checking the number of machines ready so we report resize completed only when the machines
693
+ // are actually provisioned (vs reporting completed immediately after the last machine object is created). This convention is also used by KCP.
694
+ if newStatus .ReadyReplicas == newStatus .Replicas {
695
+ conditions .MarkTrue (ms , clusterv1 .ResizedCondition )
696
+ }
697
+ // This means that there was no error in generating the desired number of machine objects
698
+ conditions .MarkTrue (ms , clusterv1 .MachinesCreatedCondition )
699
+ }
700
+
701
+ // Aggregate the operational state of all the machines; while aggregating we are adding the
702
+ // source ref (reason@machine/name) so the problem can be easily tracked down to its source machine.
703
+ conditions .SetAggregate (ms , clusterv1 .MachinesReadyCondition , collections .FromMachines (filteredMachines ... ).ConditionGetters (), conditions .AddSourceRef (), conditions .WithStepCounterIf (false ))
653
704
654
705
return nil
655
706
}
0 commit comments