Skip to content

Commit f1cb7da

Browse files
committed
Apply labels to Machines if they're part of a MD or MS
1 parent 3bed0c5 commit f1cb7da

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed

api/v1alpha3/machine_types.go

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ const (
3131

3232
// ExcludeNodeDrainingAnnotation annotation explicitly skips node draining if set
3333
ExcludeNodeDrainingAnnotation = "machine.cluster.x-k8s.io.io/exclude-node-draining"
34+
35+
// MachineSetLabelName is the label set on machines if they're controlled by MachineSet
36+
MachineSetLabelName = "cluster.x-k8s.io/set-name"
37+
38+
// MachineDeploymentLabelName is the label set on machines if they're controlled by MachineDeployment
39+
MachineDeploymentLabelName = "cluster.x-k8s.io/deployment-name"
3440
)
3541

3642
// ANCHOR: MachineSpec

controllers/machine_controller.go

+37
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ func (r *MachineReconciler) reconcile(ctx context.Context, cluster *clusterv1.Cl
157157

158158
// Call the inner reconciliation methods.
159159
reconciliationErrors := []error{
160+
r.reconcileLables(ctx, m),
160161
r.reconcileBootstrap(ctx, m),
161162
r.reconcileInfrastructure(ctx, m),
162163
r.reconcileNodeRef(ctx, cluster, m),
@@ -181,6 +182,42 @@ func (r *MachineReconciler) reconcile(ctx context.Context, cluster *clusterv1.Cl
181182
return res, kerrors.NewAggregate(errs)
182183
}
183184

185+
func (r *MachineReconciler) reconcileLables(ctx context.Context, m *clusterv1.Machine) error {
186+
logger := r.Log.WithValues("machine", m.Name, "namespace", m.Namespace)
187+
188+
if m.Labels == nil {
189+
m.Labels = make(map[string]string)
190+
}
191+
192+
// return early if machine already has both the labels for machineSet and machineDeployment controller
193+
if m.Labels[clusterv1.MachineDeploymentLabelName] != "" && m.Labels[clusterv1.MachineSetLabelName] != "" {
194+
return nil
195+
}
196+
197+
machineControllerRef := metav1.GetControllerOf(m)
198+
// return early if machine is not controlled by any machineSet
199+
if machineControllerRef == nil {
200+
return nil
201+
}
202+
203+
ms := &clusterv1.MachineSet{}
204+
err := r.Client.Get(ctx, client.ObjectKey{
205+
Namespace: m.Namespace,
206+
Name: machineControllerRef.Name,
207+
}, ms)
208+
if err != nil {
209+
logger.Error(err, "failed to get owner machineset", "machineset", machineControllerRef.Name)
210+
return err
211+
}
212+
m.Labels[clusterv1.MachineSetLabelName] = machineControllerRef.Name
213+
214+
if machineSetControllerRef := metav1.GetControllerOf(ms); machineSetControllerRef != nil {
215+
m.Labels[clusterv1.MachineDeploymentLabelName] = machineSetControllerRef.Name
216+
}
217+
218+
return nil
219+
}
220+
184221
func (r *MachineReconciler) reconcileDelete(ctx context.Context, cluster *clusterv1.Cluster, m *clusterv1.Machine) (ctrl.Result, error) {
185222
logger := r.Log.WithValues("machine", m.Name, "namespace", m.Namespace)
186223
logger = logger.WithValues("cluster", cluster.Name)

controllers/machine_controller_test.go

+125
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package controllers
1818

1919
import (
20+
"context"
21+
"reflect"
2022
"testing"
2123

2224
. "github.com/onsi/gomega"
@@ -26,6 +28,7 @@ import (
2628
"k8s.io/apimachinery/pkg/runtime"
2729
"k8s.io/apimachinery/pkg/types"
2830
"k8s.io/client-go/kubernetes/scheme"
31+
"k8s.io/klog/klogr"
2932
"k8s.io/utils/pointer"
3033
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
3134
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -553,3 +556,125 @@ func TestRemoveMachineFinalizerAfterDeleteReconcile(t *testing.T) {
553556
Expect(mr.Client.Get(ctx, key, m)).ToNot(HaveOccurred())
554557
Expect(m.ObjectMeta.Finalizers).To(Equal([]string{metav1.FinalizerDeleteDependents}))
555558
}
559+
560+
func TestMachineReconciler_reconcileLables(t *testing.T) {
561+
RegisterTestingT(t)
562+
563+
err := clusterv1.AddToScheme(scheme.Scheme)
564+
Expect(err).NotTo(HaveOccurred())
565+
566+
tests := []struct {
567+
name string
568+
m *clusterv1.Machine
569+
ms *clusterv1.MachineSet
570+
md *clusterv1.MachineDeployment
571+
expectedLabels map[string]string
572+
wantErr bool
573+
}{
574+
{
575+
name: "no controller, machine should not have labels",
576+
m: &clusterv1.Machine{
577+
ObjectMeta: metav1.ObjectMeta{
578+
Name: "test-machine",
579+
Namespace: corev1.NamespaceDefault,
580+
},
581+
},
582+
expectedLabels: map[string]string{},
583+
wantErr: false,
584+
},
585+
{
586+
name: "controlled by machineset",
587+
m: &clusterv1.Machine{
588+
ObjectMeta: metav1.ObjectMeta{
589+
Name: "test-machine",
590+
Namespace: corev1.NamespaceDefault,
591+
OwnerReferences: []metav1.OwnerReference{
592+
{
593+
APIVersion: clusterv1.GroupVersion.String(),
594+
Kind: machineSetKind.String(),
595+
Name: "test-ms",
596+
Controller: pointer.BoolPtr(true),
597+
BlockOwnerDeletion: nil,
598+
},
599+
},
600+
},
601+
},
602+
ms: &clusterv1.MachineSet{
603+
ObjectMeta: metav1.ObjectMeta{
604+
Name: "test-ms",
605+
Namespace: corev1.NamespaceDefault,
606+
},
607+
},
608+
expectedLabels: map[string]string{
609+
clusterv1.MachineSetLabelName: "test-ms",
610+
},
611+
wantErr: false,
612+
},
613+
{
614+
name: "controlled by machinedeployment",
615+
m: &clusterv1.Machine{
616+
ObjectMeta: metav1.ObjectMeta{
617+
Name: "test-machine",
618+
Namespace: corev1.NamespaceDefault,
619+
OwnerReferences: []metav1.OwnerReference{
620+
{
621+
APIVersion: clusterv1.GroupVersion.String(),
622+
Kind: machineSetKind.String(),
623+
Name: "test-ms",
624+
Controller: pointer.BoolPtr(true),
625+
BlockOwnerDeletion: nil,
626+
},
627+
},
628+
},
629+
},
630+
ms: &clusterv1.MachineSet{
631+
ObjectMeta: metav1.ObjectMeta{
632+
Name: "test-ms",
633+
Namespace: corev1.NamespaceDefault,
634+
OwnerReferences: []metav1.OwnerReference{
635+
{
636+
APIVersion: clusterv1.GroupVersion.String(),
637+
Kind: machineDeploymentKind.String(),
638+
Name: "test-md",
639+
Controller: pointer.BoolPtr(true),
640+
BlockOwnerDeletion: nil,
641+
},
642+
},
643+
},
644+
},
645+
md: &clusterv1.MachineDeployment{
646+
ObjectMeta: metav1.ObjectMeta{
647+
Name: "test-md",
648+
Namespace: corev1.NamespaceDefault,
649+
},
650+
},
651+
expectedLabels: map[string]string{
652+
clusterv1.MachineSetLabelName: "test-ms",
653+
clusterv1.MachineDeploymentLabelName: "test-md",
654+
},
655+
wantErr: false,
656+
},
657+
}
658+
for _, tt := range tests {
659+
t.Run(tt.name, func(t *testing.T) {
660+
c := fake.NewFakeClientWithScheme(scheme.Scheme, tt.m)
661+
if tt.ms != nil {
662+
c = fake.NewFakeClientWithScheme(scheme.Scheme, tt.m, tt.ms)
663+
}
664+
if tt.md != nil {
665+
c = fake.NewFakeClientWithScheme(scheme.Scheme, tt.m, tt.ms, tt.md)
666+
}
667+
668+
r := &MachineReconciler{
669+
Log: klogr.New(),
670+
Client: c,
671+
}
672+
if err := r.reconcileLables(context.Background(), tt.m); (err != nil) != tt.wantErr {
673+
t.Errorf("reconcileLables() error = %v, wantErr %v", err, tt.wantErr)
674+
}
675+
if !reflect.DeepEqual(tt.m.Labels, tt.expectedLabels) {
676+
t.Errorf("expected labels %v, got %v", tt.expectedLabels, tt.m.Labels)
677+
}
678+
})
679+
}
680+
}

0 commit comments

Comments
 (0)