Skip to content

Commit bae19a2

Browse files
authored
Merge pull request #7593 from killianmuldoon/fix-dual-adoption
🌱 Ensure infra and bootstrap objects are owned by Machines
2 parents fb80f9b + e384bd0 commit bae19a2

File tree

2 files changed

+65
-21
lines changed

2 files changed

+65
-21
lines changed

internal/controllers/machine/machine_controller_phases.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,11 @@ func (r *Reconciler) reconcileExternal(ctx context.Context, cluster *clusterv1.C
116116
return external.ReconcileOutput{}, err
117117
}
118118

119-
// With the migration from v1alpha2 to v1alpha3, Machine controllers should be the owner for the
120-
// infra Machines, hence remove any existing machineset controller owner reference
121-
if controller := metav1.GetControllerOf(obj); controller != nil && controller.Kind == "MachineSet" {
122-
gv, err := schema.ParseGroupVersion(controller.APIVersion)
123-
if err != nil {
124-
return external.ReconcileOutput{}, err
125-
}
126-
if gv.Group == clusterv1.GroupVersion.Group {
127-
ownerRefs := util.RemoveOwnerRef(obj.GetOwnerReferences(), *controller)
128-
obj.SetOwnerReferences(ownerRefs)
129-
}
119+
// removeOnCreateOwnerRefs removes MachineSet and control plane owners from the objects referred to by a Machine.
120+
// These owner references are added initially because Machines don't exist when those objects are created.
121+
// At this point the Machine exists and can be set as the controller reference.
122+
if err := removeOnCreateOwnerRefs(cluster, m, obj); err != nil {
123+
return external.ReconcileOutput{}, err
130124
}
131125

132126
// Set external object ControllerReference to the Machine.
@@ -372,3 +366,33 @@ func (r *Reconciler) reconcileCertificateExpiry(ctx context.Context, _ *clusterv
372366

373367
return ctrl.Result{}, nil
374368
}
369+
370+
// removeOnCreateOwnerRefs will remove any MachineSet or control plane owner references from passed objects.
371+
func removeOnCreateOwnerRefs(cluster *clusterv1.Cluster, m *clusterv1.Machine, obj *unstructured.Unstructured) error {
372+
cpGVK := getControlPlaneGVKForMachine(cluster, m)
373+
for _, owner := range obj.GetOwnerReferences() {
374+
ownerGV, err := schema.ParseGroupVersion(owner.APIVersion)
375+
if err != nil {
376+
return errors.Wrapf(err, "Could not remove ownerReference %v from object %s/%s", owner.String(), obj.GetKind(), obj.GetName())
377+
}
378+
if (ownerGV.Group == clusterv1.GroupVersion.Group && owner.Kind == "MachineSet") ||
379+
(cpGVK != nil && ownerGV.Group == cpGVK.GroupVersion().Group && owner.Kind == cpGVK.Kind) {
380+
ownerRefs := util.RemoveOwnerRef(obj.GetOwnerReferences(), owner)
381+
obj.SetOwnerReferences(ownerRefs)
382+
}
383+
}
384+
return nil
385+
}
386+
387+
// getControlPlaneGVKForMachine returns the Kind of the control plane in the Cluster associated with the Machine.
388+
// This function checks that the Machine is managed by a control plane, and then retrieves the Kind from the Cluster's
389+
// .spec.controlPlaneRef.
390+
func getControlPlaneGVKForMachine(cluster *clusterv1.Cluster, machine *clusterv1.Machine) *schema.GroupVersionKind {
391+
if _, ok := machine.GetLabels()[clusterv1.MachineControlPlaneLabelName]; ok {
392+
if cluster.Spec.ControlPlaneRef != nil {
393+
gvk := cluster.Spec.ControlPlaneRef.GroupVersionKind()
394+
return &gvk
395+
}
396+
}
397+
return nil
398+
}

internal/controllers/machineset/machineset_controller_test.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,24 @@ func TestMachineSetReconciler(t *testing.T) {
228228
g.Expect(im.GetAnnotations()).To(HaveKeyWithValue("annotation-1", "true"), "have annotations of MachineTemplate applied")
229229
g.Expect(im.GetAnnotations()).To(HaveKeyWithValue("precedence", "MachineSet"), "the annotations from the MachineSpec template to overwrite the infrastructure template ones")
230230
g.Expect(im.GetLabels()).To(HaveKeyWithValue("label-1", "true"), "have labels of MachineTemplate applied")
231+
}
232+
g.Eventually(func() bool {
233+
g.Expect(env.List(ctx, infraMachines, client.InNamespace(namespace.Name))).To(Succeed())
234+
// The Machine reconciler should remove the ownerReference to the MachineSet on the InfrastructureMachine.
231235
hasMSOwnerRef := false
232-
for _, o := range im.GetOwnerReferences() {
233-
if o.Kind == machineSetKind.Kind {
234-
hasMSOwnerRef = true
236+
hasMachineOwnerRef := false
237+
for _, im := range infraMachines.Items {
238+
for _, o := range im.GetOwnerReferences() {
239+
if o.Kind == machineSetKind.Kind {
240+
hasMSOwnerRef = true
241+
}
242+
if o.Kind == "Machine" {
243+
hasMachineOwnerRef = true
244+
}
235245
}
236246
}
237-
g.Expect(hasMSOwnerRef).To(BeTrue(), "have ownerRef to MachineSet")
238-
}
247+
return !hasMSOwnerRef && hasMachineOwnerRef
248+
}, timeout).Should(BeTrue(), "infraMachine should not have ownerRef to MachineSet")
239249

240250
t.Log("Creating a BootstrapConfig for each Machine")
241251
bootstrapConfigs := &unstructured.UnstructuredList{}
@@ -251,14 +261,24 @@ func TestMachineSetReconciler(t *testing.T) {
251261
g.Expect(im.GetAnnotations()).To(HaveKeyWithValue("annotation-1", "true"), "have annotations of MachineTemplate applied")
252262
g.Expect(im.GetAnnotations()).To(HaveKeyWithValue("precedence", "MachineSet"), "the annotations from the MachineSpec template to overwrite the bootstrap config template ones")
253263
g.Expect(im.GetLabels()).To(HaveKeyWithValue("label-1", "true"), "have labels of MachineTemplate applied")
264+
}
265+
g.Eventually(func() bool {
266+
g.Expect(env.List(ctx, bootstrapConfigs, client.InNamespace(namespace.Name))).To(Succeed())
267+
// The Machine reconciler should remove the ownerReference to the MachineSet on the Bootstrap object.
254268
hasMSOwnerRef := false
255-
for _, o := range im.GetOwnerReferences() {
256-
if o.Kind == machineSetKind.Kind {
257-
hasMSOwnerRef = true
269+
hasMachineOwnerRef := false
270+
for _, im := range bootstrapConfigs.Items {
271+
for _, o := range im.GetOwnerReferences() {
272+
if o.Kind == machineSetKind.Kind {
273+
hasMSOwnerRef = true
274+
}
275+
if o.Kind == "Machine" {
276+
hasMachineOwnerRef = true
277+
}
258278
}
259279
}
260-
g.Expect(hasMSOwnerRef).To(BeTrue(), "have ownerRef to MachineSet")
261-
}
280+
return !hasMSOwnerRef && hasMachineOwnerRef
281+
}, timeout).Should(BeTrue(), "bootstrap should not have ownerRef to MachineSet")
262282

263283
// Set the infrastructure reference as ready.
264284
for _, m := range machines.Items {

0 commit comments

Comments
 (0)