Skip to content

Commit 8003f3f

Browse files
authored
Merge pull request kubernetes-sigs#8842 from Jont828/mpm-capd
✨ Add MachinePool Machine implementation to CAPD components
2 parents 9f7c446 + 80ef9d2 commit 8003f3f

File tree

16 files changed

+752
-525
lines changed

16 files changed

+752
-525
lines changed

exp/internal/controllers/machinepool_controller_phases.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"sigs.k8s.io/cluster-api/util/annotations"
4848
"sigs.k8s.io/cluster-api/util/conditions"
4949
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
50+
"sigs.k8s.io/cluster-api/util/labels"
5051
"sigs.k8s.io/cluster-api/util/labels/format"
5152
"sigs.k8s.io/cluster-api/util/patch"
5253
)
@@ -485,12 +486,10 @@ func computeDesiredMachine(mp *expv1.MachinePool, infraMachine *unstructured.Uns
485486
func (r *MachinePoolReconciler) infraMachineToMachinePoolMapper(ctx context.Context, o client.Object) []ctrl.Request {
486487
log := ctrl.LoggerFrom(ctx)
487488

488-
labels := o.GetLabels()
489-
_, machinePoolOwned := labels[clusterv1.MachinePoolNameLabel]
490-
if machinePoolOwned {
491-
machinePool, err := utilexp.GetMachinePoolByLabels(ctx, r.Client, o.GetNamespace(), labels)
489+
if labels.IsMachinePoolOwned(o) {
490+
machinePool, err := utilexp.GetMachinePoolByLabels(ctx, r.Client, o.GetNamespace(), o.GetLabels())
492491
if err != nil {
493-
log.Error(err, "failed to get MachinePool for InfraMachine", "infraMachine", klog.KObj(o), "labels", labels)
492+
log.Error(err, "failed to get MachinePool for InfraMachine", "infraMachine", klog.KObj(o), "labels", o.GetLabels())
494493
return nil
495494
}
496495
if machinePool != nil {

internal/webhooks/machine.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
3232

3333
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
34+
"sigs.k8s.io/cluster-api/util/labels"
3435
"sigs.k8s.io/cluster-api/util/version"
3536
)
3637

@@ -120,7 +121,7 @@ func (webhook *Machine) validate(oldM, newM *clusterv1.Machine) error {
120121
specPath := field.NewPath("spec")
121122
if newM.Spec.Bootstrap.ConfigRef == nil && newM.Spec.Bootstrap.DataSecretName == nil {
122123
// MachinePool Machines don't have a bootstrap configRef, so don't require it. The bootstrap config is instead owned by the MachinePool.
123-
if !isMachinePoolMachine(newM) {
124+
if !labels.IsMachinePoolOwned(newM) {
124125
allErrs = append(
125126
allErrs,
126127
field.Required(
@@ -171,19 +172,3 @@ func (webhook *Machine) validate(oldM, newM *clusterv1.Machine) error {
171172
}
172173
return apierrors.NewInvalid(clusterv1.GroupVersion.WithKind("Machine").GroupKind(), newM.Name, allErrs)
173174
}
174-
175-
func isMachinePoolMachine(m *clusterv1.Machine) bool {
176-
if m.Labels != nil {
177-
if _, ok := m.Labels[clusterv1.MachinePoolNameLabel]; ok {
178-
return true
179-
}
180-
}
181-
182-
for _, owner := range m.OwnerReferences {
183-
if owner.Kind == "MachinePool" {
184-
return true
185-
}
186-
}
187-
188-
return false
189-
}

internal/webhooks/machine_test.go

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -220,60 +220,6 @@ func TestMachineClusterNameImmutable(t *testing.T) {
220220
}
221221
}
222222

223-
func TestIsMachinePoolMachine(t *testing.T) {
224-
tests := []struct {
225-
name string
226-
machine clusterv1.Machine
227-
isMPM bool
228-
}{
229-
{
230-
name: "machine is a MachinePoolMachine",
231-
machine: clusterv1.Machine{
232-
ObjectMeta: metav1.ObjectMeta{
233-
OwnerReferences: []metav1.OwnerReference{
234-
{
235-
Kind: "MachinePool",
236-
},
237-
},
238-
},
239-
},
240-
isMPM: true,
241-
},
242-
{
243-
name: "machine is not a MachinePoolMachine",
244-
machine: clusterv1.Machine{
245-
ObjectMeta: metav1.ObjectMeta{
246-
OwnerReferences: []metav1.OwnerReference{
247-
{
248-
Kind: "NotMachinePool",
249-
},
250-
},
251-
},
252-
},
253-
isMPM: false,
254-
},
255-
{
256-
name: "machine is not a MachinePoolMachine, no owner references",
257-
machine: clusterv1.Machine{
258-
ObjectMeta: metav1.ObjectMeta{
259-
OwnerReferences: nil,
260-
},
261-
},
262-
isMPM: false,
263-
},
264-
}
265-
266-
for i := range tests {
267-
tt := tests[i]
268-
t.Run(tt.name, func(t *testing.T) {
269-
g := NewWithT(t)
270-
271-
result := isMachinePoolMachine(&tt.machine)
272-
g.Expect(result).To(Equal(tt.isMPM))
273-
})
274-
}
275-
}
276-
277223
func TestMachineVersionValidation(t *testing.T) {
278224
tests := []struct {
279225
name string

test/e2e/clusterclass_rollout.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"sigs.k8s.io/cluster-api/test/framework"
4848
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
4949
"sigs.k8s.io/cluster-api/util"
50+
"sigs.k8s.io/cluster-api/util/labels"
5051
"sigs.k8s.io/cluster-api/util/patch"
5152
)
5253

@@ -246,6 +247,8 @@ func ClusterClassRolloutSpec(ctx context.Context, inputGetter func() ClusterClas
246247
})
247248
By("Verifying all Machines are replaced through rollout")
248249
Eventually(func(g Gomega) {
250+
// Note: This excludes MachinePool Machines as they are not replaced by rollout yet.
251+
// This is tracked by https://github.com/kubernetes-sigs/cluster-api/issues/8858.
249252
machinesAfterUpgrade := getMachinesByCluster(ctx, input.BootstrapClusterProxy.GetClient(), clusterResources.Cluster)
250253
g.Expect(machinesAfterUpgrade.HasAny(machinesBeforeUpgrade.UnsortedList()...)).To(BeFalse(), "All Machines must be replaced through rollout")
251254
}, input.E2EConfig.GetIntervals(specName, "wait-control-plane")...).Should(Succeed())
@@ -898,15 +901,19 @@ func mustMetadata(metadata *clusterv1.ObjectMeta, err error) *clusterv1.ObjectMe
898901
}
899902

900903
// getMachinesByCluster gets the Machines of a Cluster and returns them as a Set of Machine names.
904+
// Note: This excludes MachinePool Machines as they are not replaced by rollout yet.
901905
func getMachinesByCluster(ctx context.Context, client client.Client, cluster *clusterv1.Cluster) sets.Set[string] {
902906
machines := sets.Set[string]{}
903907
machinesByCluster := framework.GetMachinesByCluster(ctx, framework.GetMachinesByClusterInput{
904908
Lister: client,
905909
ClusterName: cluster.Name,
906910
Namespace: cluster.Namespace,
907911
})
908-
for _, m := range machinesByCluster {
909-
machines.Insert(m.Name)
912+
for i := range machinesByCluster {
913+
m := machinesByCluster[i]
914+
if !labels.IsMachinePoolOwned(&m) {
915+
machines.Insert(m.Name)
916+
}
910917
}
911918
return machines
912919
}
@@ -935,7 +942,7 @@ func getMDTopology(cluster *clusterv1.Cluster, md *clusterv1.MachineDeployment)
935942
return nil
936943
}
937944

938-
// getMPClass looks up the MachinePoolClass for a md in the ClusterClass.
945+
// getMPClass looks up the MachinePoolClass for a MachinePool in the ClusterClass.
939946
func getMPClass(cluster *clusterv1.Cluster, clusterClass *clusterv1.ClusterClass, mp *expv1.MachinePool) *clusterv1.MachinePoolClass {
940947
mpTopology := getMPTopology(cluster, mp)
941948

test/framework/ownerreference_helpers.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
4040
addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1"
4141
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
42+
infraexpv1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/api/v1beta1"
4243
"sigs.k8s.io/cluster-api/util/patch"
4344
)
4445

@@ -288,6 +289,8 @@ var (
288289
dockerMachinePoolTemplateKind = "DockerMachinePoolTemplate"
289290
dockerClusterKind = "DockerCluster"
290291
dockerClusterTemplateKind = "DockerClusterTemplate"
292+
293+
dockerMachinePoolController = metav1.OwnerReference{Kind: dockerMachinePoolKind, APIVersion: infraexpv1.GroupVersion.String()}
291294
)
292295

293296
// DockerInfraOwnerReferenceAssertions maps Docker Infrastructure types to functions which return an error if the passed
@@ -296,8 +299,9 @@ var (
296299
// That document should be updated if these references change.
297300
var DockerInfraOwnerReferenceAssertions = map[string]func([]metav1.OwnerReference) error{
298301
dockerMachineKind: func(owners []metav1.OwnerReference) error {
299-
// The DockerMachine must be owned and controlled by a Machine.
300-
return HasExactOwners(owners, machineController)
302+
// The DockerMachine must be owned and controlled by a Machine or a DockerMachinePool.
303+
return HasOneOfExactOwners(owners, []metav1.OwnerReference{machineController}, []metav1.OwnerReference{machineController, dockerMachinePoolController})
304+
301305
},
302306
dockerMachineTemplateKind: func(owners []metav1.OwnerReference) error {
303307
// Base DockerMachineTemplates referenced in a ClusterClass must be owned by the ClusterClass.

test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepools.yaml

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/infrastructure/docker/config/rbac/role.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ rules:
5151
- get
5252
- list
5353
- watch
54+
- apiGroups:
55+
- cluster.x-k8s.io
56+
resources:
57+
- machines
58+
verbs:
59+
- delete
60+
- get
61+
- list
62+
- watch
5463
- apiGroups:
5564
- infrastructure.cluster.x-k8s.io
5665
resources:

test/infrastructure/docker/exp/api/v1alpha4/conversion.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,40 @@ limitations under the License.
1717
package v1alpha4
1818

1919
import (
20+
apiconversion "k8s.io/apimachinery/pkg/conversion"
2021
"sigs.k8s.io/controller-runtime/pkg/conversion"
2122

2223
infraexpv1 "sigs.k8s.io/cluster-api/test/infrastructure/docker/exp/api/v1beta1"
24+
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
2325
)
2426

2527
func (src *DockerMachinePool) ConvertTo(dstRaw conversion.Hub) error {
2628
dst := dstRaw.(*infraexpv1.DockerMachinePool)
2729

28-
return Convert_v1alpha4_DockerMachinePool_To_v1beta1_DockerMachinePool(src, dst, nil)
30+
if err := Convert_v1alpha4_DockerMachinePool_To_v1beta1_DockerMachinePool(src, dst, nil); err != nil {
31+
return err
32+
}
33+
34+
// Manually restore data.
35+
restored := &infraexpv1.DockerMachinePool{}
36+
if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok {
37+
return err
38+
}
39+
40+
dst.Status.InfrastructureMachineKind = restored.Status.InfrastructureMachineKind
41+
42+
return nil
2943
}
3044

3145
func (dst *DockerMachinePool) ConvertFrom(srcRaw conversion.Hub) error {
3246
src := srcRaw.(*infraexpv1.DockerMachinePool)
3347

34-
return Convert_v1beta1_DockerMachinePool_To_v1alpha4_DockerMachinePool(src, dst, nil)
48+
if err := Convert_v1beta1_DockerMachinePool_To_v1alpha4_DockerMachinePool(src, dst, nil); err != nil {
49+
return err
50+
}
51+
52+
// Preserve Hub data on down-conversion except for metadata
53+
return utilconversion.MarshalData(src, dst)
3554
}
3655

3756
func (src *DockerMachinePoolList) ConvertTo(dstRaw conversion.Hub) error {
@@ -45,3 +64,8 @@ func (dst *DockerMachinePoolList) ConvertFrom(srcRaw conversion.Hub) error {
4564

4665
return Convert_v1beta1_DockerMachinePoolList_To_v1alpha4_DockerMachinePoolList(src, dst, nil)
4766
}
67+
68+
func Convert_v1beta1_DockerMachinePoolStatus_To_v1alpha4_DockerMachinePoolStatus(in *infraexpv1.DockerMachinePoolStatus, out *DockerMachinePoolStatus, s apiconversion.Scope) error {
69+
// NOTE: custom conversion func is required because Status.InfrastructureMachineKind has been added in v1beta1.
70+
return autoConvert_v1beta1_DockerMachinePoolStatus_To_v1alpha4_DockerMachinePoolStatus(in, out, s)
71+
}

test/infrastructure/docker/exp/api/v1alpha4/zz_generated.conversion.go

Lines changed: 2 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/infrastructure/docker/exp/api/v1beta1/dockermachinepool_types.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ type DockerMachinePoolStatus struct {
8282
// Conditions defines current service state of the DockerMachinePool.
8383
// +optional
8484
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
85+
86+
// InfrastructureMachineKind is the kind of the infrastructure resources behind MachinePool Machines.
87+
// +optional
88+
InfrastructureMachineKind string `json:"infrastructureMachineKind,omitempty"`
8589
}
8690

8791
// DockerMachinePoolInstanceStatus contains status information about a DockerMachinePool.
@@ -130,13 +134,13 @@ type DockerMachinePool struct {
130134
}
131135

132136
// GetConditions returns the set of conditions for this object.
133-
func (c *DockerMachinePool) GetConditions() clusterv1.Conditions {
134-
return c.Status.Conditions
137+
func (d *DockerMachinePool) GetConditions() clusterv1.Conditions {
138+
return d.Status.Conditions
135139
}
136140

137141
// SetConditions sets the conditions on this object.
138-
func (c *DockerMachinePool) SetConditions(conditions clusterv1.Conditions) {
139-
c.Status.Conditions = conditions
142+
func (d *DockerMachinePool) SetConditions(conditions clusterv1.Conditions) {
143+
d.Status.Conditions = conditions
140144
}
141145

142146
// +kubebuilder:object:root=true

0 commit comments

Comments
 (0)