diff --git a/api/v1beta1/condition_consts.go b/api/v1beta1/condition_consts.go index 7b1a5483b7b4..ff798aa3ef0e 100644 --- a/api/v1beta1/condition_consts.go +++ b/api/v1beta1/condition_consts.go @@ -228,6 +228,14 @@ const ( // machines required (i.e. Spec.Replicas-MaxUnavailable when MachineDeploymentStrategyType = RollingUpdate) are up and running for at least minReadySeconds. MachineDeploymentAvailableCondition ConditionType = "Available" + // MachineSetReadyCondition reports a summary of current status of the MachineSet owned by the MachineDeployment. + MachineSetReadyCondition ConditionType = "MachineSetReady" + + // WaitingForMachineSetFallbackReason (Severity=Info) documents a MachineDeployment waiting for the underlying MachineSet + // to be available. + // NOTE: This reason is used only as a fallback when the MachineSet object is not reporting its own ready condition. + WaitingForMachineSetFallbackReason = "WaitingForMachineSet" + // WaitingForAvailableMachinesReason (Severity=Warning) reflects the fact that the required minimum number of machines for a machinedeployment are not available. WaitingForAvailableMachinesReason = "WaitingForAvailableMachines" ) diff --git a/internal/controllers/machinedeployment/machinedeployment_sync.go b/internal/controllers/machinedeployment/machinedeployment_sync.go index 546ecd85f86f..af0ac4cbd1b8 100644 --- a/internal/controllers/machinedeployment/machinedeployment_sync.go +++ b/internal/controllers/machinedeployment/machinedeployment_sync.go @@ -499,6 +499,17 @@ func (r *Reconciler) syncDeploymentStatus(allMSs []*clusterv1.MachineSet, newMS } else { conditions.MarkFalse(md, clusterv1.MachineDeploymentAvailableCondition, clusterv1.WaitingForAvailableMachinesReason, clusterv1.ConditionSeverityWarning, "Minimum availability requires %d replicas, current %d available", minReplicasNeeded, md.Status.AvailableReplicas) } + + if newMS != nil { + // Report a summary of current status of the MachineSet object owned by this MachineDeployment. + conditions.SetMirror(md, clusterv1.MachineSetReadyCondition, + newMS, + conditions.WithFallbackValue(false, clusterv1.WaitingForMachineSetFallbackReason, clusterv1.ConditionSeverityInfo, ""), + ) + } else { + conditions.MarkFalse(md, clusterv1.MachineSetReadyCondition, clusterv1.WaitingForMachineSetFallbackReason, clusterv1.ConditionSeverityInfo, "MachineSet not found") + } + return nil } diff --git a/internal/controllers/machinedeployment/machinedeployment_sync_test.go b/internal/controllers/machinedeployment/machinedeployment_sync_test.go index 0367d3d0cbe0..82472e72b0c1 100644 --- a/internal/controllers/machinedeployment/machinedeployment_sync_test.go +++ b/internal/controllers/machinedeployment/machinedeployment_sync_test.go @@ -430,7 +430,7 @@ func newTestMachineDeployment(pds *int32, replicas, statusReplicas, updatedRepli } // helper to create MS with given availableReplicas. -func newTestMachinesetWithReplicas(name string, specReplicas, statusReplicas, availableReplicas int32) *clusterv1.MachineSet { +func newTestMachinesetWithReplicas(name string, specReplicas, statusReplicas, availableReplicas int32, conditions clusterv1.Conditions) *clusterv1.MachineSet { return &clusterv1.MachineSet{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -443,6 +443,7 @@ func newTestMachinesetWithReplicas(name string, specReplicas, statusReplicas, av Status: clusterv1.MachineSetStatus{ AvailableReplicas: availableReplicas, Replicas: statusReplicas, + Conditions: conditions, }, } } @@ -460,7 +461,7 @@ func TestSyncDeploymentStatus(t *testing.T) { name: "Deployment not available: MachineDeploymentAvailableCondition should exist and be false", d: newTestMachineDeployment(&pds, 3, 2, 2, 2, clusterv1.Conditions{}), oldMachineSets: []*clusterv1.MachineSet{}, - newMachineSet: newTestMachinesetWithReplicas("foo", 3, 2, 2), + newMachineSet: newTestMachinesetWithReplicas("foo", 3, 2, 2, clusterv1.Conditions{}), expectedConditions: []*clusterv1.Condition{ { Type: clusterv1.MachineDeploymentAvailableCondition, @@ -474,7 +475,7 @@ func TestSyncDeploymentStatus(t *testing.T) { name: "Deployment Available: MachineDeploymentAvailableCondition should exist and be true", d: newTestMachineDeployment(&pds, 3, 3, 3, 3, clusterv1.Conditions{}), oldMachineSets: []*clusterv1.MachineSet{}, - newMachineSet: newTestMachinesetWithReplicas("foo", 3, 3, 3), + newMachineSet: newTestMachinesetWithReplicas("foo", 3, 3, 3, clusterv1.Conditions{}), expectedConditions: []*clusterv1.Condition{ { Type: clusterv1.MachineDeploymentAvailableCondition, @@ -482,6 +483,41 @@ func TestSyncDeploymentStatus(t *testing.T) { }, }, }, + { + name: "MachineSet exist: MachineSetReadyCondition should exist and mirror MachineSet Ready condition", + d: newTestMachineDeployment(&pds, 3, 3, 3, 3, clusterv1.Conditions{}), + oldMachineSets: []*clusterv1.MachineSet{}, + newMachineSet: newTestMachinesetWithReplicas("foo", 3, 3, 3, clusterv1.Conditions{ + { + Type: clusterv1.ReadyCondition, + Status: corev1.ConditionFalse, + Reason: "TestErrorResaon", + Message: "test error messsage", + }, + }), + expectedConditions: []*clusterv1.Condition{ + { + Type: clusterv1.MachineSetReadyCondition, + Status: corev1.ConditionFalse, + Reason: "TestErrorResaon", + Message: "test error messsage", + }, + }, + }, + { + name: "MachineSet doesn't exist: MachineSetReadyCondition should exist and be false", + d: newTestMachineDeployment(&pds, 3, 3, 3, 3, clusterv1.Conditions{}), + oldMachineSets: []*clusterv1.MachineSet{}, + newMachineSet: nil, + expectedConditions: []*clusterv1.Condition{ + { + Type: clusterv1.MachineSetReadyCondition, + Status: corev1.ConditionFalse, + Severity: clusterv1.ConditionSeverityInfo, + Reason: clusterv1.WaitingForMachineSetFallbackReason, + }, + }, + }, } for _, test := range tests {