Skip to content

Commit 920bcd2

Browse files
committed
Implement MachinePool Machines in CAPI, CAPD, and clusterctl
1 parent 98341e3 commit 920bcd2

28 files changed

+1508
-159
lines changed

api/v1beta1/common_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ const (
3737
// update that disallows a pre-existing Cluster to be populated with Topology information and Class.
3838
ClusterTopologyUnsafeUpdateClassNameAnnotation = "unsafe.topology.cluster.x-k8s.io/disable-update-class-name-check"
3939

40+
// MachinePoolOwnedLabel is the label set on Machines and InfraMachines linked to a MachinePool.
41+
MachinePoolOwnedLabel = "machinepool.cluster.x-k8s.io/owned"
42+
4043
// ProviderNameLabel is the label set on components in the provider manifest.
4144
// This label allows to easily identify all the components belonging to a provider; the clusterctl
4245
// tool uses this label for implementing provider's lifecycle operations.

api/v1beta1/machine_webhook.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
apierrors "k8s.io/apimachinery/pkg/api/errors"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
2627
"k8s.io/apimachinery/pkg/runtime"
2728
"k8s.io/apimachinery/pkg/util/validation/field"
2829
ctrl "sigs.k8s.io/controller-runtime"
@@ -57,7 +58,10 @@ func (m *Machine) Default() {
5758
}
5859

5960
if m.Spec.InfrastructureRef.Namespace == "" {
60-
m.Spec.InfrastructureRef.Namespace = m.Namespace
61+
// Don't autofill namespace for MachinePoolMachines
62+
if _, isMachinePoolMachine := m.Labels[MachinePoolOwnedLabel]; !isMachinePoolMachine {
63+
m.Spec.InfrastructureRef.Namespace = m.Namespace
64+
}
6165
}
6266

6367
if m.Spec.Version != nil && !strings.HasPrefix(*m.Spec.Version, "v") {
@@ -93,13 +97,17 @@ func (m *Machine) validate(old *Machine) error {
9397
var allErrs field.ErrorList
9498
specPath := field.NewPath("spec")
9599
if m.Spec.Bootstrap.ConfigRef == nil && m.Spec.Bootstrap.DataSecretName == nil {
96-
allErrs = append(
97-
allErrs,
98-
field.Required(
99-
specPath.Child("bootstrap", "data"),
100-
"expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated",
101-
),
102-
)
100+
// Don't require bootstrap data for MachinePoolMachines
101+
if _, isMachinePoolMachine := m.Labels[MachinePoolOwnedLabel]; !isMachinePoolMachine {
102+
allErrs = append(
103+
allErrs,
104+
field.Required(
105+
specPath.Child("bootstrap", "data"),
106+
"expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated",
107+
),
108+
)
109+
}
110+
103111
}
104112

105113
if m.Spec.Bootstrap.ConfigRef != nil && m.Spec.Bootstrap.ConfigRef.Namespace != m.Namespace {

cmd/clusterctl/client/tree/discovery.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package tree
1818

1919
import (
2020
"context"
21+
"fmt"
2122

2223
corev1 "k8s.io/api/core/v1"
2324
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -112,8 +113,10 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
112113
tree.Add(m, machineInfra, ObjectMetaName("MachineInfrastructure"), NoEcho(true))
113114
}
114115

115-
if machineBootstrap, err := external.Get(ctx, c, m.Spec.Bootstrap.ConfigRef, cluster.Namespace); err == nil {
116-
tree.Add(m, machineBootstrap, ObjectMetaName("BootstrapConfig"), NoEcho(true))
116+
if m.Spec.Bootstrap.ConfigRef != nil {
117+
if machineBootstrap, err := external.Get(ctx, c, m.Spec.Bootstrap.ConfigRef, cluster.Namespace); err == nil {
118+
tree.Add(m, machineBootstrap, ObjectMetaName("BootstrapConfig"), NoEcho(true))
119+
}
117120
}
118121
}
119122
}
@@ -142,24 +145,25 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
142145
return nil, err
143146
}
144147

145-
// Handles orphan machines.
146-
if len(machineMap) < len(machinesList.Items) {
147-
other := VirtualObject(cluster.Namespace, "OtherGroup", "Other")
148-
tree.Add(workers, other)
149-
150-
for i := range machinesList.Items {
151-
m := &machinesList.Items[i]
152-
if _, ok := machineMap[m.Name]; ok {
153-
continue
154-
}
155-
addMachineFunc(other, m)
156-
}
157-
}
158148
}
159149

160150
if len(machinePoolList.Items) > 0 { // Add MachinePool objects
161151
tree.Add(cluster, workers)
162-
addMachinePoolsToObjectTree(ctx, c, cluster.Namespace, workers, machinePoolList, tree)
152+
addMachinePoolsToObjectTree(ctx, c, cluster.Namespace, workers, machinePoolList, machinesList, tree, addMachineFunc)
153+
}
154+
155+
// Handles orphan machines.
156+
if len(machineMap) < len(machinesList.Items) {
157+
other := VirtualObject(cluster.Namespace, "OtherGroup", "Other")
158+
tree.Add(workers, other)
159+
160+
for i := range machinesList.Items {
161+
m := &machinesList.Items[i]
162+
if _, ok := machineMap[m.Name]; ok {
163+
continue
164+
}
165+
addMachineFunc(other, m)
166+
}
163167
}
164168

165169
return tree, nil
@@ -263,20 +267,30 @@ func addMachineDeploymentToObjectTree(ctx context.Context, c client.Client, clus
263267
return nil
264268
}
265269

266-
func addMachinePoolsToObjectTree(ctx context.Context, c client.Client, namespace string, workers *unstructured.Unstructured, machinePoolList *expv1.MachinePoolList, tree *ObjectTree) {
270+
func addMachinePoolsToObjectTree(ctx context.Context, c client.Client, namespace string, workers *unstructured.Unstructured, machinePoolList *expv1.MachinePoolList, machinesList *clusterv1.MachineList, tree *ObjectTree, addMachineFunc func(parent client.Object, m *clusterv1.Machine)) {
267271
for i := range machinePoolList.Items {
268272
mp := &machinePoolList.Items[i]
269-
_, visible := tree.Add(workers, mp)
273+
_, visible := tree.Add(workers, mp, GroupingObject(true))
270274

271275
if visible {
272276
if machinePoolBootstrap, err := external.Get(ctx, c, mp.Spec.Template.Spec.Bootstrap.ConfigRef, namespace); err == nil {
273277
tree.Add(mp, machinePoolBootstrap, ObjectMetaName("BootstrapConfig"), NoEcho(true))
274278
}
275279

276280
if machinePoolInfra, err := external.Get(ctx, c, &mp.Spec.Template.Spec.InfrastructureRef, namespace); err == nil {
277-
tree.Add(mp, machinePoolInfra, ObjectMetaName("MachineInfrastructure"), NoEcho(true))
281+
tree.Add(mp, machinePoolInfra, ObjectMetaName("MachinePoolInfrastructure"), NoEcho(true))
278282
}
279283
}
284+
285+
machines := selectMachinesControlledBy(machinesList, mp)
286+
287+
for m := range machines {
288+
fmt.Printf("Machine %s is controlled by MachinePool %s\n", machines[m].Name, mp.Name)
289+
}
290+
291+
for _, w := range machines {
292+
addMachineFunc(mp, w)
293+
}
280294
}
281295
}
282296

exp/api/v1beta1/machinepool_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import (
2727
const (
2828
// MachinePoolFinalizer is used to ensure deletion of dependencies (nodes, infra).
2929
MachinePoolFinalizer = "machinepool.cluster.x-k8s.io"
30+
31+
// MachinePoolNameLabel is the label indicating the name of the MachinePool a Machine is controleld by.
32+
// Note: The value of this label may be a hash if the MachinePool name is longer than 63 characters.
33+
MachinePoolNameLabel = "cluster.x-k8s.io/pool-name"
3034
)
3135

3236
// ANCHOR: MachinePoolSpec

exp/internal/controllers/machinepool_controller_noderef.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func (r *MachinePoolReconciler) reconcileNodeRefs(ctx context.Context, cluster *
8585
return ctrl.Result{}, errors.Wrapf(err, "failed to get node references")
8686
}
8787

88+
log.Info("Node ref for mp is result is", "machinepool", mp.Name, "result", nodeRefsResult)
8889
mp.Status.ReadyReplicas = int32(nodeRefsResult.ready)
8990
mp.Status.AvailableReplicas = int32(nodeRefsResult.available)
9091
mp.Status.UnavailableReplicas = mp.Status.Replicas - mp.Status.AvailableReplicas

0 commit comments

Comments
 (0)