Skip to content

Commit 6af01b8

Browse files
committed
drain node by infraMachine ProviderID
1 parent afc36d4 commit 6af01b8

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

internal/controllers/machine/machine_controller.go

+15-4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import (
5353
"sigs.k8s.io/cluster-api/controllers/external"
5454
"sigs.k8s.io/cluster-api/controllers/noderefutil"
5555
"sigs.k8s.io/cluster-api/feature"
56+
"sigs.k8s.io/cluster-api/internal/contract"
5657
"sigs.k8s.io/cluster-api/internal/controllers/machine/drain"
5758
"sigs.k8s.io/cluster-api/util"
5859
"sigs.k8s.io/cluster-api/util/annotations"
@@ -435,7 +436,7 @@ func (r *Reconciler) reconcileDelete(ctx context.Context, s *scope) (ctrl.Result
435436
s.deletingReason = clusterv1.MachineDeletingV1Beta2Reason
436437
s.deletingMessage = "Deletion started"
437438

438-
err := r.isDeleteNodeAllowed(ctx, cluster, m)
439+
err := r.isDeleteNodeAllowed(ctx, cluster, m, s.infraMachine)
439440
isDeleteNodeAllowed := err == nil
440441
if err != nil {
441442
switch err {
@@ -713,14 +714,24 @@ func (r *Reconciler) nodeVolumeDetachTimeoutExceeded(machine *clusterv1.Machine)
713714

714715
// isDeleteNodeAllowed returns nil only if the Machine's NodeRef is not nil
715716
// and if the Machine is not the last control plane node in the cluster.
716-
func (r *Reconciler) isDeleteNodeAllowed(ctx context.Context, cluster *clusterv1.Cluster, machine *clusterv1.Machine) error {
717+
func (r *Reconciler) isDeleteNodeAllowed(ctx context.Context, cluster *clusterv1.Cluster, machine *clusterv1.Machine, infraMachine *unstructured.Unstructured) error {
717718
log := ctrl.LoggerFrom(ctx)
718719
// Return early if the cluster is being deleted.
719720
if !cluster.DeletionTimestamp.IsZero() {
720721
return errClusterIsBeingDeleted
721722
}
722723

723-
if machine.Status.NodeRef == nil && machine.Spec.ProviderID != nil {
724+
var providerID string
725+
if machine.Spec.ProviderID != nil {
726+
providerID = *machine.Spec.ProviderID
727+
} else if infraMachine != nil {
728+
// Fallback to retrieve from infraMachine.
729+
if providerIDFromInfraMachine, err := contract.InfrastructureMachine().ProviderID().Get(infraMachine); err == nil {
730+
providerID = *providerIDFromInfraMachine
731+
}
732+
}
733+
734+
if machine.Status.NodeRef == nil && providerID != "" {
724735
// If we don't have a node reference, but a provider id has been set,
725736
// try to retrieve the node one more time.
726737
//
@@ -731,7 +742,7 @@ func (r *Reconciler) isDeleteNodeAllowed(ctx context.Context, cluster *clusterv1
731742
if err != nil {
732743
log.Error(err, "Failed to get cluster client while deleting Machine and checking for nodes")
733744
} else {
734-
node, err := r.getNode(ctx, remoteClient, *machine.Spec.ProviderID)
745+
node, err := r.getNode(ctx, remoteClient, providerID)
735746
if err != nil && err != ErrNodeNotFound {
736747
log.Error(err, "Failed to get node while deleting Machine")
737748
} else if err == nil {

internal/controllers/machine/machine_controller_test.go

+53-2
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
25302530
name string
25312531
cluster *clusterv1.Cluster
25322532
machine *clusterv1.Machine
2533+
infraMachine *unstructured.Unstructured
25332534
expectedError error
25342535
}{
25352536
{
@@ -2556,6 +2557,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
25562557
},
25572558
Status: clusterv1.MachineStatus{},
25582559
},
2560+
infraMachine: nil,
25592561
expectedError: errNilNodeRef,
25602562
},
25612563
{
@@ -2586,6 +2588,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
25862588
},
25872589
},
25882590
},
2591+
infraMachine: nil,
25892592
expectedError: errNoControlPlaneNodes,
25902593
},
25912594
{
@@ -2618,6 +2621,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
26182621
},
26192622
},
26202623
},
2624+
infraMachine: nil,
26212625
expectedError: errNoControlPlaneNodes,
26222626
},
26232627
{
@@ -2648,6 +2652,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
26482652
},
26492653
},
26502654
},
2655+
infraMachine: nil,
26512656
expectedError: nil,
26522657
},
26532658
{
@@ -2661,6 +2666,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
26612666
},
26622667
},
26632668
machine: &clusterv1.Machine{},
2669+
infraMachine: nil,
26642670
expectedError: errClusterIsBeingDeleted,
26652671
},
26662672
{
@@ -2699,6 +2705,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
26992705
},
27002706
},
27012707
},
2708+
infraMachine: nil,
27022709
expectedError: nil,
27032710
},
27042711
{
@@ -2737,6 +2744,7 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
27372744
},
27382745
},
27392746
},
2747+
infraMachine: nil,
27402748
expectedError: errControlPlaneIsBeingDeleted,
27412749
},
27422750
{
@@ -2775,8 +2783,40 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
27752783
},
27762784
},
27772785
},
2786+
infraMachine: nil,
27782787
expectedError: errControlPlaneIsBeingDeleted,
27792788
},
2789+
{
2790+
name: "no nodeRef, infrastructure machine has providerID",
2791+
cluster: &clusterv1.Cluster{
2792+
ObjectMeta: metav1.ObjectMeta{
2793+
Name: "test-cluster",
2794+
Namespace: metav1.NamespaceDefault,
2795+
},
2796+
},
2797+
machine: &clusterv1.Machine{
2798+
ObjectMeta: metav1.ObjectMeta{
2799+
Name: "created",
2800+
Namespace: metav1.NamespaceDefault,
2801+
Labels: map[string]string{
2802+
clusterv1.ClusterNameLabel: "test-cluster",
2803+
},
2804+
Finalizers: []string{clusterv1.MachineFinalizer},
2805+
},
2806+
Spec: clusterv1.MachineSpec{
2807+
ClusterName: "test-cluster",
2808+
InfrastructureRef: corev1.ObjectReference{},
2809+
Bootstrap: clusterv1.Bootstrap{DataSecretName: ptr.To("data")},
2810+
},
2811+
Status: clusterv1.MachineStatus{},
2812+
},
2813+
infraMachine: &unstructured.Unstructured{Object: map[string]interface{}{
2814+
"spec": map[string]interface{}{
2815+
"providerID": "test-node-a",
2816+
},
2817+
}},
2818+
expectedError: nil,
2819+
},
27802820
}
27812821

27822822
emp := &unstructured.Unstructured{
@@ -2815,6 +2855,15 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
28152855
empBeingDeleted.SetDeletionTimestamp(&metav1.Time{Time: time.Now()})
28162856
empBeingDeleted.SetFinalizers([]string{"block-deletion"})
28172857

2858+
testNodeA := &corev1.Node{
2859+
ObjectMeta: metav1.ObjectMeta{
2860+
Name: "node-a",
2861+
},
2862+
Spec: corev1.NodeSpec{
2863+
ProviderID: "test-node-a",
2864+
},
2865+
}
2866+
28182867
for _, tc := range testCases {
28192868
t.Run(tc.name, func(t *testing.T) {
28202869
g := NewWithT(t)
@@ -2874,11 +2923,13 @@ func TestIsDeleteNodeAllowed(t *testing.T) {
28742923
mcpBeingDeleted,
28752924
empBeingDeleted,
28762925
).Build()
2926+
remoteClient := fake.NewClientBuilder().WithIndex(&corev1.Node{}, "spec.providerID", index.NodeByProviderID).WithObjects(testNodeA).Build()
28772927
mr := &Reconciler{
2878-
Client: c,
2928+
Client: c,
2929+
ClusterCache: clustercache.NewFakeClusterCache(remoteClient, client.ObjectKeyFromObject(tc.cluster)),
28792930
}
28802931

2881-
err := mr.isDeleteNodeAllowed(ctx, tc.cluster, tc.machine)
2932+
err := mr.isDeleteNodeAllowed(ctx, tc.cluster, tc.machine, tc.infraMachine)
28822933
if tc.expectedError == nil {
28832934
g.Expect(err).ToNot(HaveOccurred())
28842935
} else {

0 commit comments

Comments
 (0)