diff --git a/controlplane/kubeadm/internal/controllers/controller_test.go b/controlplane/kubeadm/internal/controllers/controller_test.go index ff79e501ac45..0ecfb72382c9 100644 --- a/controlplane/kubeadm/internal/controllers/controller_test.go +++ b/controlplane/kubeadm/internal/controllers/controller_test.go @@ -1567,6 +1567,7 @@ func TestKubeadmControlPlaneReconciler_syncMachines(t *testing.T) { NodeDrainTimeout: duration5s, NodeVolumeDetachTimeout: duration5s, NodeDeletionTimeout: duration5s, + ReadinessGates: mandatoryMachineReadinessGates, }, } g.Expect(env.Create(ctx, deletingMachine, client.FieldOwner(classicManager))).To(Succeed()) diff --git a/controlplane/kubeadm/internal/controllers/helpers.go b/controlplane/kubeadm/internal/controllers/helpers.go index ef46f9092c65..aab89e40cc17 100644 --- a/controlplane/kubeadm/internal/controllers/helpers.go +++ b/controlplane/kubeadm/internal/controllers/helpers.go @@ -47,6 +47,15 @@ import ( "sigs.k8s.io/cluster-api/util/secret" ) +// mandatoryMachineReadinessGates are readinessGates KCP enforces to be set on machine it owns. +var mandatoryMachineReadinessGates = []clusterv1.MachineReadinessGate{ + {ConditionType: string(controlplanev1.KubeadmControlPlaneMachineAPIServerPodHealthyV1Beta2Condition)}, + {ConditionType: string(controlplanev1.KubeadmControlPlaneMachineControllerManagerPodHealthyV1Beta2Condition)}, + {ConditionType: string(controlplanev1.KubeadmControlPlaneMachineSchedulerPodHealthyV1Beta2Condition)}, + {ConditionType: string(controlplanev1.KubeadmControlPlaneMachineEtcdPodHealthyV1Beta2Condition)}, + {ConditionType: string(controlplanev1.KubeadmControlPlaneMachineEtcdMemberHealthyV1Beta2Condition)}, +} + func (r *KubeadmControlPlaneReconciler) reconcileKubeconfig(ctx context.Context, controlPlane *internal.ControlPlane) (ctrl.Result, error) { log := ctrl.LoggerFrom(ctx) @@ -443,7 +452,29 @@ func (r *KubeadmControlPlaneReconciler) computeDesiredMachine(kcp *controlplanev if existingMachine != nil { desiredMachine.Spec.InfrastructureRef = existingMachine.Spec.InfrastructureRef desiredMachine.Spec.Bootstrap.ConfigRef = existingMachine.Spec.Bootstrap.ConfigRef + desiredMachine.Spec.ReadinessGates = existingMachine.Spec.ReadinessGates } + ensureMandatoryReadinessGates(desiredMachine) return desiredMachine, nil } + +func ensureMandatoryReadinessGates(m *clusterv1.Machine) { + if m.Spec.ReadinessGates == nil { + m.Spec.ReadinessGates = mandatoryMachineReadinessGates + return + } + + for _, want := range mandatoryMachineReadinessGates { + found := false + for _, got := range m.Spec.ReadinessGates { + if got.ConditionType == want.ConditionType { + found = true + break + } + } + if !found { + m.Spec.ReadinessGates = append(m.Spec.ReadinessGates, want) + } + } +} diff --git a/controlplane/kubeadm/internal/controllers/helpers_test.go b/controlplane/kubeadm/internal/controllers/helpers_test.go index 28108cf9b81b..e6c289cdb4b7 100644 --- a/controlplane/kubeadm/internal/controllers/helpers_test.go +++ b/controlplane/kubeadm/internal/controllers/helpers_test.go @@ -539,6 +539,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { NodeDrainTimeout: kcp.Spec.MachineTemplate.NodeDrainTimeout, NodeDeletionTimeout: kcp.Spec.MachineTemplate.NodeDeletionTimeout, NodeVolumeDetachTimeout: kcp.Spec.MachineTemplate.NodeVolumeDetachTimeout, + ReadinessGates: mandatoryMachineReadinessGates, } g.Expect(createdMachine.Name).To(HavePrefix(kcp.Name)) g.Expect(createdMachine.Namespace).To(Equal(kcp.Namespace)) @@ -601,6 +602,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { ConfigRef: bootstrapRef, }, InfrastructureRef: *infraRef, + ReadinessGates: []clusterv1.MachineReadinessGate{{ConditionType: "Foo"}}, }, } @@ -621,6 +623,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { NodeDrainTimeout: kcp.Spec.MachineTemplate.NodeDrainTimeout, NodeDeletionTimeout: kcp.Spec.MachineTemplate.NodeDeletionTimeout, NodeVolumeDetachTimeout: kcp.Spec.MachineTemplate.NodeVolumeDetachTimeout, + ReadinessGates: append([]clusterv1.MachineReadinessGate{{ConditionType: "Foo"}}, mandatoryMachineReadinessGates...), } g.Expect(updatedMachine.Namespace).To(Equal(kcp.Namespace)) g.Expect(updatedMachine.OwnerReferences).To(HaveLen(1))