Skip to content

Commit 9d20ebf

Browse files
committed
ClusterClass: also consider MD unavailableReplicas for rollout
Signed-off-by: Stefan Büringer [email protected]
1 parent 46c3438 commit 9d20ebf

File tree

3 files changed

+124
-50
lines changed

3 files changed

+124
-50
lines changed

internal/controllers/topology/cluster/conditions_test.go

Lines changed: 96 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,11 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
178178
Object: builder.MachineDeployment("ns1", "md0-abc123").
179179
WithReplicas(2).
180180
WithStatus(clusterv1.MachineDeploymentStatus{
181-
Replicas: int32(1),
182-
UpdatedReplicas: int32(1),
183-
ReadyReplicas: int32(1),
184-
AvailableReplicas: int32(1),
181+
Replicas: int32(1),
182+
UpdatedReplicas: int32(1),
183+
ReadyReplicas: int32(1),
184+
AvailableReplicas: int32(1),
185+
UnavailableReplicas: int32(0),
185186
}).
186187
Build(),
187188
},
@@ -220,10 +221,11 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
220221
Object: builder.MachineDeployment("ns1", "md0-abc123").
221222
WithReplicas(2).
222223
WithStatus(clusterv1.MachineDeploymentStatus{
223-
Replicas: int32(2),
224-
UpdatedReplicas: int32(2),
225-
ReadyReplicas: int32(2),
226-
AvailableReplicas: int32(2),
224+
Replicas: int32(2),
225+
UpdatedReplicas: int32(2),
226+
ReadyReplicas: int32(2),
227+
AvailableReplicas: int32(2),
228+
UnavailableReplicas: int32(0),
227229
}).
228230
Build(),
229231
},
@@ -264,10 +266,11 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
264266
Object: builder.MachineDeployment("ns1", "md0-abc123").
265267
WithReplicas(2).
266268
WithStatus(clusterv1.MachineDeploymentStatus{
267-
Replicas: int32(2),
268-
UpdatedReplicas: int32(2),
269-
ReadyReplicas: int32(2),
270-
AvailableReplicas: int32(2),
269+
Replicas: int32(2),
270+
UpdatedReplicas: int32(2),
271+
ReadyReplicas: int32(2),
272+
AvailableReplicas: int32(2),
273+
UnavailableReplicas: int32(0),
271274
}).
272275
Build(),
273276
},
@@ -344,7 +347,7 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
344347
wantConditionStatus: corev1.ConditionTrue,
345348
},
346349
{
347-
name: "should set the condition to false is some machine deployments have not picked the new version because other machine deployments are rolling out",
350+
name: "should set the condition to false is some machine deployments have not picked the new version because other machine deployments are rolling out (not all replicas ready)",
348351
reconcileErr: nil,
349352
cluster: &clusterv1.Cluster{},
350353
s: &scope.Scope{
@@ -367,10 +370,12 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
367370
WithReplicas(2).
368371
WithVersion("v1.22.0").
369372
WithStatus(clusterv1.MachineDeploymentStatus{
370-
Replicas: int32(1),
371-
UpdatedReplicas: int32(1),
372-
ReadyReplicas: int32(1),
373-
AvailableReplicas: int32(1),
373+
// MD is not ready because we don't have 2 updated, ready and available replicas.
374+
Replicas: int32(2),
375+
UpdatedReplicas: int32(1),
376+
ReadyReplicas: int32(1),
377+
AvailableReplicas: int32(1),
378+
UnavailableReplicas: int32(0),
374379
}).
375380
Build(),
376381
},
@@ -379,10 +384,70 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
379384
WithReplicas(2).
380385
WithVersion("v1.21.2").
381386
WithStatus(clusterv1.MachineDeploymentStatus{
382-
Replicas: int32(2),
383-
UpdatedReplicas: int32(2),
384-
ReadyReplicas: int32(2),
385-
AvailableReplicas: int32(2),
387+
Replicas: int32(2),
388+
UpdatedReplicas: int32(2),
389+
ReadyReplicas: int32(2),
390+
AvailableReplicas: int32(2),
391+
UnavailableReplicas: int32(0),
392+
}).
393+
Build(),
394+
},
395+
},
396+
},
397+
UpgradeTracker: func() *scope.UpgradeTracker {
398+
ut := scope.NewUpgradeTracker()
399+
ut.ControlPlane.PendingUpgrade = false
400+
ut.MachineDeployments.MarkPendingUpgrade("md1-abc123")
401+
return ut
402+
}(),
403+
HookResponseTracker: scope.NewHookResponseTracker(),
404+
},
405+
wantConditionStatus: corev1.ConditionFalse,
406+
wantConditionReason: clusterv1.TopologyReconciledMachineDeploymentsUpgradePendingReason,
407+
},
408+
{
409+
name: "should set the condition to false is some machine deployments have not picked the new version because other machine deployments are rolling out (unavailable replica)",
410+
reconcileErr: nil,
411+
cluster: &clusterv1.Cluster{},
412+
s: &scope.Scope{
413+
Blueprint: &scope.ClusterBlueprint{
414+
Topology: &clusterv1.Topology{
415+
Version: "v1.22.0",
416+
},
417+
},
418+
Current: &scope.ClusterState{
419+
Cluster: &clusterv1.Cluster{},
420+
ControlPlane: &scope.ControlPlaneState{
421+
Object: builder.ControlPlane("ns1", "controlplane1").
422+
WithVersion("v1.22.0").
423+
WithReplicas(3).
424+
Build(),
425+
},
426+
MachineDeployments: scope.MachineDeploymentsStateMap{
427+
"md0": &scope.MachineDeploymentState{
428+
Object: builder.MachineDeployment("ns1", "md0-abc123").
429+
WithReplicas(2).
430+
WithVersion("v1.22.0").
431+
WithStatus(clusterv1.MachineDeploymentStatus{
432+
// MD is not ready because we still have an unavailable replica.
433+
Replicas: int32(2),
434+
UpdatedReplicas: int32(2),
435+
ReadyReplicas: int32(2),
436+
AvailableReplicas: int32(2),
437+
UnavailableReplicas: int32(1),
438+
}).
439+
Build(),
440+
},
441+
"md1": &scope.MachineDeploymentState{
442+
Object: builder.MachineDeployment("ns1", "md1-abc123").
443+
WithReplicas(2).
444+
WithVersion("v1.21.2").
445+
WithStatus(clusterv1.MachineDeploymentStatus{
446+
Replicas: int32(2),
447+
UpdatedReplicas: int32(2),
448+
ReadyReplicas: int32(2),
449+
AvailableReplicas: int32(2),
450+
UnavailableReplicas: int32(0),
386451
}).
387452
Build(),
388453
},
@@ -423,10 +488,11 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
423488
WithReplicas(2).
424489
WithVersion("v1.22.0").
425490
WithStatus(clusterv1.MachineDeploymentStatus{
426-
Replicas: int32(1),
427-
UpdatedReplicas: int32(1),
428-
ReadyReplicas: int32(1),
429-
AvailableReplicas: int32(1),
491+
Replicas: int32(1),
492+
UpdatedReplicas: int32(1),
493+
ReadyReplicas: int32(1),
494+
AvailableReplicas: int32(1),
495+
UnavailableReplicas: int32(0),
430496
}).
431497
Build(),
432498
},
@@ -435,10 +501,11 @@ func TestReconcileTopologyReconciledCondition(t *testing.T) {
435501
WithReplicas(2).
436502
WithVersion("v1.22.0").
437503
WithStatus(clusterv1.MachineDeploymentStatus{
438-
Replicas: int32(2),
439-
UpdatedReplicas: int32(2),
440-
ReadyReplicas: int32(2),
441-
AvailableReplicas: int32(2),
504+
Replicas: int32(2),
505+
UpdatedReplicas: int32(2),
506+
ReadyReplicas: int32(2),
507+
AvailableReplicas: int32(2),
508+
UnavailableReplicas: int32(0),
442509
}).
443510
Build(),
444511
},

internal/controllers/topology/cluster/desired_state_test.go

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -634,22 +634,24 @@ func TestComputeControlPlaneVersion(t *testing.T) {
634634
WithGeneration(int64(1)).
635635
WithReplicas(int32(2)).
636636
WithStatus(clusterv1.MachineDeploymentStatus{
637-
ObservedGeneration: 2,
638-
Replicas: 2,
639-
UpdatedReplicas: 2,
640-
AvailableReplicas: 2,
641-
ReadyReplicas: 2,
637+
ObservedGeneration: 2,
638+
Replicas: 2,
639+
UpdatedReplicas: 2,
640+
AvailableReplicas: 2,
641+
ReadyReplicas: 2,
642+
UnavailableReplicas: 0,
642643
}).
643644
Build()
644645
machineDeploymentRollingOut := builder.MachineDeployment("test-namespace", "md2").
645646
WithGeneration(int64(1)).
646647
WithReplicas(int32(2)).
647648
WithStatus(clusterv1.MachineDeploymentStatus{
648-
ObservedGeneration: 2,
649-
Replicas: 1,
650-
UpdatedReplicas: 1,
651-
AvailableReplicas: 1,
652-
ReadyReplicas: 1,
649+
ObservedGeneration: 2,
650+
Replicas: 1,
651+
UpdatedReplicas: 1,
652+
AvailableReplicas: 1,
653+
ReadyReplicas: 1,
654+
UnavailableReplicas: 0,
653655
}).
654656
Build()
655657

@@ -1769,6 +1771,7 @@ func TestComputeMachineDeploymentVersion(t *testing.T) {
17691771
// - md.spec.replicas == md.status.replicas
17701772
// - md.spec.replicas == md.status.updatedReplicas
17711773
// - md.spec.replicas == md.status.readyReplicas
1774+
// - md.status.unavailableReplicas == 0
17721775
// - md.Generation < md.status.observedGeneration
17731776
//
17741777
// A machine deployment is considered upgrading if any of the above conditions
@@ -1777,22 +1780,24 @@ func TestComputeMachineDeploymentVersion(t *testing.T) {
17771780
WithGeneration(1).
17781781
WithReplicas(2).
17791782
WithStatus(clusterv1.MachineDeploymentStatus{
1780-
ObservedGeneration: 2,
1781-
Replicas: 2,
1782-
UpdatedReplicas: 2,
1783-
AvailableReplicas: 2,
1784-
ReadyReplicas: 2,
1783+
ObservedGeneration: 2,
1784+
Replicas: 2,
1785+
UpdatedReplicas: 2,
1786+
AvailableReplicas: 2,
1787+
ReadyReplicas: 2,
1788+
UnavailableReplicas: 0,
17851789
}).
17861790
Build()
17871791
machineDeploymentRollingOut := builder.MachineDeployment("test-namespace", "md-2").
17881792
WithGeneration(1).
17891793
WithReplicas(2).
17901794
WithStatus(clusterv1.MachineDeploymentStatus{
1791-
ObservedGeneration: 2,
1792-
Replicas: 1,
1793-
UpdatedReplicas: 1,
1794-
AvailableReplicas: 1,
1795-
ReadyReplicas: 1,
1795+
ObservedGeneration: 2,
1796+
Replicas: 1,
1797+
UpdatedReplicas: 1,
1798+
AvailableReplicas: 1,
1799+
ReadyReplicas: 1,
1800+
UnavailableReplicas: 1,
17961801
}).
17971802
Build()
17981803

internal/controllers/topology/cluster/scope/state.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,7 @@ type MachineDeploymentState struct {
9494
// A machine deployment is considered upgrading if:
9595
// - if any of the replicas of the machine deployment is not ready.
9696
func (md *MachineDeploymentState) IsRollingOut() bool {
97-
return !mdutil.DeploymentComplete(md.Object, &md.Object.Status) || *md.Object.Spec.Replicas != md.Object.Status.ReadyReplicas
97+
return !mdutil.DeploymentComplete(md.Object, &md.Object.Status) ||
98+
*md.Object.Spec.Replicas != md.Object.Status.ReadyReplicas ||
99+
md.Object.Status.UnavailableReplicas > 0
98100
}

0 commit comments

Comments
 (0)