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