Skip to content

Commit 0908bfc

Browse files
authored
šŸ› MachineSet should allow scale down operations to proceed when templates don't exist (#10913)
Signed-off-by: Vince Prignano <[email protected]>
1 parent 42f7b89 commit 0908bfc

File tree

2 files changed

+109
-37
lines changed

2 files changed

+109
-37
lines changed

ā€Žinternal/controllers/machineset/machineset_controller.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,12 @@ func (r *Reconciler) reconcile(ctx context.Context, cluster *clusterv1.Cluster,
240240
}
241241

242242
// Make sure to reconcile the external infrastructure reference.
243-
if err := reconcileExternalTemplateReference(ctx, r.Client, cluster, &machineSet.Spec.Template.Spec.InfrastructureRef); err != nil {
243+
if err := r.reconcileExternalTemplateReference(ctx, cluster, machineSet, &machineSet.Spec.Template.Spec.InfrastructureRef); err != nil {
244244
return ctrl.Result{}, err
245245
}
246246
// Make sure to reconcile the external bootstrap reference, if any.
247247
if machineSet.Spec.Template.Spec.Bootstrap.ConfigRef != nil {
248-
if err := reconcileExternalTemplateReference(ctx, r.Client, cluster, machineSet.Spec.Template.Spec.Bootstrap.ConfigRef); err != nil {
248+
if err := r.reconcileExternalTemplateReference(ctx, cluster, machineSet, machineSet.Spec.Template.Spec.Bootstrap.ConfigRef); err != nil {
249249
return ctrl.Result{}, err
250250
}
251251
}
@@ -1139,21 +1139,36 @@ func (r *Reconciler) reconcileUnhealthyMachines(ctx context.Context, cluster *cl
11391139
return ctrl.Result{}, nil
11401140
}
11411141

1142-
func reconcileExternalTemplateReference(ctx context.Context, c client.Client, cluster *clusterv1.Cluster, ref *corev1.ObjectReference) error {
1142+
func (r *Reconciler) reconcileExternalTemplateReference(ctx context.Context, cluster *clusterv1.Cluster, ms *clusterv1.MachineSet, ref *corev1.ObjectReference) error {
11431143
if !strings.HasSuffix(ref.Kind, clusterv1.TemplateSuffix) {
11441144
return nil
11451145
}
11461146

1147-
if err := utilconversion.UpdateReferenceAPIContract(ctx, c, ref); err != nil {
1147+
if err := utilconversion.UpdateReferenceAPIContract(ctx, r.Client, ref); err != nil {
11481148
return err
11491149
}
11501150

1151-
obj, err := external.Get(ctx, c, ref, cluster.Namespace)
1151+
obj, err := external.Get(ctx, r.Client, ref, cluster.Namespace)
11521152
if err != nil {
1153+
if apierrors.IsNotFound(err) {
1154+
if _, ok := ms.Labels[clusterv1.MachineDeploymentNameLabel]; !ok {
1155+
// If the MachineSet is not in a MachineDeployment, return the error immediately.
1156+
return err
1157+
}
1158+
// When the MachineSet is part of a MachineDeployment but isn't the current revision, we should
1159+
// ignore the not found references and allow the controller to proceed.
1160+
owner, err := r.getOwnerMachineDeployment(ctx, ms)
1161+
if err != nil {
1162+
return err
1163+
}
1164+
if owner.Annotations[clusterv1.RevisionAnnotation] != ms.Annotations[clusterv1.RevisionAnnotation] {
1165+
return nil
1166+
}
1167+
}
11531168
return err
11541169
}
11551170

1156-
patchHelper, err := patch.NewHelper(obj, c)
1171+
patchHelper, err := patch.NewHelper(obj, r.Client)
11571172
if err != nil {
11581173
return err
11591174
}

ā€Žinternal/controllers/machineset/machineset_controller_test.go

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,71 @@ func TestMachineSetReconciler(t *testing.T) {
8484
duration5m := &metav1.Duration{Duration: 5 * time.Minute}
8585
replicas := int32(2)
8686
version := "v1.14.2"
87+
machineTemplateSpec := clusterv1.MachineTemplateSpec{
88+
ObjectMeta: clusterv1.ObjectMeta{
89+
Labels: map[string]string{
90+
"label-1": "true",
91+
},
92+
Annotations: map[string]string{
93+
"annotation-1": "true",
94+
"precedence": "MachineSet",
95+
},
96+
},
97+
Spec: clusterv1.MachineSpec{
98+
ClusterName: testCluster.Name,
99+
Version: &version,
100+
Bootstrap: clusterv1.Bootstrap{
101+
ConfigRef: &corev1.ObjectReference{
102+
APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1",
103+
Kind: "GenericBootstrapConfigTemplate",
104+
Name: "ms-template",
105+
},
106+
},
107+
InfrastructureRef: corev1.ObjectReference{
108+
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
109+
Kind: "GenericInfrastructureMachineTemplate",
110+
Name: "ms-template",
111+
},
112+
NodeDrainTimeout: duration10m,
113+
NodeDeletionTimeout: duration10m,
114+
NodeVolumeDetachTimeout: duration10m,
115+
},
116+
}
117+
118+
machineDeployment := &clusterv1.MachineDeployment{
119+
ObjectMeta: metav1.ObjectMeta{
120+
GenerateName: "md-",
121+
Namespace: namespace.Name,
122+
Annotations: map[string]string{
123+
clusterv1.RevisionAnnotation: "10",
124+
},
125+
},
126+
Spec: clusterv1.MachineDeploymentSpec{
127+
ClusterName: testCluster.Name,
128+
Replicas: &replicas,
129+
Template: machineTemplateSpec,
130+
},
131+
}
132+
g.Expect(env.Create(ctx, machineDeployment)).To(Succeed())
133+
87134
instance := &clusterv1.MachineSet{
88135
ObjectMeta: metav1.ObjectMeta{
89136
GenerateName: "ms-",
90137
Namespace: namespace.Name,
91138
Labels: map[string]string{
92-
"label-1": "true",
139+
"label-1": "true",
140+
clusterv1.MachineDeploymentNameLabel: machineDeployment.Name,
141+
},
142+
Annotations: map[string]string{
143+
clusterv1.RevisionAnnotation: "10",
144+
},
145+
OwnerReferences: []metav1.OwnerReference{
146+
{
147+
APIVersion: clusterv1.GroupVersion.String(),
148+
Kind: "MachineDeployment",
149+
Name: machineDeployment.Name,
150+
UID: machineDeployment.UID,
151+
},
93152
},
94153
},
95154
Spec: clusterv1.MachineSetSpec{
@@ -100,36 +159,7 @@ func TestMachineSetReconciler(t *testing.T) {
100159
"label-1": "true",
101160
},
102161
},
103-
Template: clusterv1.MachineTemplateSpec{
104-
ObjectMeta: clusterv1.ObjectMeta{
105-
Labels: map[string]string{
106-
"label-1": "true",
107-
},
108-
Annotations: map[string]string{
109-
"annotation-1": "true",
110-
"precedence": "MachineSet",
111-
},
112-
},
113-
Spec: clusterv1.MachineSpec{
114-
ClusterName: testCluster.Name,
115-
Version: &version,
116-
Bootstrap: clusterv1.Bootstrap{
117-
ConfigRef: &corev1.ObjectReference{
118-
APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1",
119-
Kind: "GenericBootstrapConfigTemplate",
120-
Name: "ms-template",
121-
},
122-
},
123-
InfrastructureRef: corev1.ObjectReference{
124-
APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1",
125-
Kind: "GenericInfrastructureMachineTemplate",
126-
Name: "ms-template",
127-
},
128-
NodeDrainTimeout: duration10m,
129-
NodeDeletionTimeout: duration10m,
130-
NodeVolumeDetachTimeout: duration10m,
131-
},
132-
},
162+
Template: machineTemplateSpec,
133163
},
134164
}
135165

@@ -405,6 +435,33 @@ func TestMachineSetReconciler(t *testing.T) {
405435

406436
// Validate that the controller set the cluster name label in selector.
407437
g.Expect(instance.Status.Selector).To(ContainSubstring(testCluster.Name))
438+
439+
t.Log("Verifying MachineSet can be scaled down when templates don't exist, and MachineSet is not current")
440+
g.Expect(env.CleanupAndWait(ctx, bootstrapTmpl)).To(Succeed())
441+
g.Expect(env.CleanupAndWait(ctx, infraTmpl)).To(Succeed())
442+
443+
t.Log("Updating Replicas on MachineSet")
444+
patchHelper, err = patch.NewHelper(instance, env)
445+
g.Expect(err).ToNot(HaveOccurred())
446+
instance.SetAnnotations(map[string]string{
447+
clusterv1.RevisionAnnotation: "9",
448+
})
449+
instance.Spec.Replicas = ptr.To(int32(1))
450+
g.Expect(patchHelper.Patch(ctx, instance)).Should(Succeed())
451+
452+
// Verify that we have 1 replicas.
453+
g.Eventually(func() (ready int) {
454+
if err := env.List(ctx, machines, client.InNamespace(namespace.Name)); err != nil {
455+
return -1
456+
}
457+
for _, m := range machines.Items {
458+
if !m.DeletionTimestamp.IsZero() {
459+
continue
460+
}
461+
ready++
462+
}
463+
return
464+
}, timeout*3).Should(BeEquivalentTo(1))
408465
})
409466
}
410467

0 commit comments

Comments
Ā (0)