Skip to content

Commit

Permalink
Implement MachinePool Machines in CAPI, CAPD, and clusterctl
Browse files Browse the repository at this point in the history
  • Loading branch information
Jont828 committed Feb 9, 2023
1 parent bc98c72 commit 29f27a9
Show file tree
Hide file tree
Showing 27 changed files with 1,507 additions and 158 deletions.
3 changes: 3 additions & 0 deletions api/v1beta1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ const (
// update that disallows a pre-existing Cluster to be populated with Topology information and Class.
ClusterTopologyUnsafeUpdateClassNameAnnotation = "unsafe.topology.cluster.x-k8s.io/disable-update-class-name-check"

// MachinePoolOwnedLabel is the label set on Machines and InfraMachines linked to a MachinePool.
MachinePoolOwnedLabel = "machinepool.cluster.x-k8s.io/owned"

// ProviderNameLabel is the label set on components in the provider manifest.
// This label allows to easily identify all the components belonging to a provider; the clusterctl
// tool uses this label for implementing provider's lifecycle operations.
Expand Down
24 changes: 16 additions & 8 deletions api/v1beta1/machine_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -57,7 +58,10 @@ func (m *Machine) Default() {
}

if m.Spec.InfrastructureRef.Namespace == "" {
m.Spec.InfrastructureRef.Namespace = m.Namespace
// Don't autofill namespace for MachinePoolMachines
if _, isMachinePoolMachine := m.Labels[MachinePoolOwnedLabel]; !isMachinePoolMachine {
m.Spec.InfrastructureRef.Namespace = m.Namespace
}
}

if m.Spec.Version != nil && !strings.HasPrefix(*m.Spec.Version, "v") {
Expand Down Expand Up @@ -93,13 +97,17 @@ func (m *Machine) validate(old *Machine) error {
var allErrs field.ErrorList
specPath := field.NewPath("spec")
if m.Spec.Bootstrap.ConfigRef == nil && m.Spec.Bootstrap.DataSecretName == nil {
allErrs = append(
allErrs,
field.Required(
specPath.Child("bootstrap", "data"),
"expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated",
),
)
// Don't require bootstrap data for MachinePoolMachines
if _, isMachinePoolMachine := m.Labels[MachinePoolOwnedLabel]; !isMachinePoolMachine {
allErrs = append(
allErrs,
field.Required(
specPath.Child("bootstrap", "data"),
"expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated",
),
)
}

}

if m.Spec.Bootstrap.ConfigRef != nil && m.Spec.Bootstrap.ConfigRef.Namespace != m.Namespace {
Expand Down
52 changes: 33 additions & 19 deletions cmd/clusterctl/client/tree/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package tree

import (
"context"
"fmt"

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

if machineBootstrap, err := external.Get(ctx, c, m.Spec.Bootstrap.ConfigRef, cluster.Namespace); err == nil {
tree.Add(m, machineBootstrap, ObjectMetaName("BootstrapConfig"), NoEcho(true))
if m.Spec.Bootstrap.ConfigRef != nil {
if machineBootstrap, err := external.Get(ctx, c, m.Spec.Bootstrap.ConfigRef, cluster.Namespace); err == nil {
tree.Add(m, machineBootstrap, ObjectMetaName("BootstrapConfig"), NoEcho(true))
}
}
}
}
Expand Down Expand Up @@ -142,24 +145,25 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
return nil, err
}

// Handles orphan machines.
if len(machineMap) < len(machinesList.Items) {
other := VirtualObject(cluster.Namespace, "OtherGroup", "Other")
tree.Add(workers, other)

for i := range machinesList.Items {
m := &machinesList.Items[i]
if _, ok := machineMap[m.Name]; ok {
continue
}
addMachineFunc(other, m)
}
}
}

if len(machinePoolList.Items) > 0 { // Add MachinePool objects
tree.Add(cluster, workers)
addMachinePoolsToObjectTree(ctx, c, cluster.Namespace, workers, machinePoolList, tree)
addMachinePoolsToObjectTree(ctx, c, cluster.Namespace, workers, machinePoolList, machinesList, tree, addMachineFunc)
}

// Handles orphan machines.
if len(machineMap) < len(machinesList.Items) {
other := VirtualObject(cluster.Namespace, "OtherGroup", "Other")
tree.Add(workers, other)

for i := range machinesList.Items {
m := &machinesList.Items[i]
if _, ok := machineMap[m.Name]; ok {
continue
}
addMachineFunc(other, m)
}
}

return tree, nil
Expand Down Expand Up @@ -263,20 +267,30 @@ func addMachineDeploymentToObjectTree(ctx context.Context, c client.Client, clus
return nil
}

func addMachinePoolsToObjectTree(ctx context.Context, c client.Client, namespace string, workers *unstructured.Unstructured, machinePoolList *expv1.MachinePoolList, tree *ObjectTree) {
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)) {
for i := range machinePoolList.Items {
mp := &machinePoolList.Items[i]
_, visible := tree.Add(workers, mp)
_, visible := tree.Add(workers, mp, GroupingObject(true))

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

if machinePoolInfra, err := external.Get(ctx, c, &mp.Spec.Template.Spec.InfrastructureRef, namespace); err == nil {
tree.Add(mp, machinePoolInfra, ObjectMetaName("MachineInfrastructure"), NoEcho(true))
tree.Add(mp, machinePoolInfra, ObjectMetaName("MachinePoolInfrastructure"), NoEcho(true))
}
}

machines := selectMachinesControlledBy(machinesList, mp)

for m := range machines {
fmt.Printf("Machine %s is controlled by MachinePool %s\n", machines[m].Name, mp.Name)
}

for _, w := range machines {
addMachineFunc(mp, w)
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions exp/api/v1beta1/machinepool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import (
const (
// MachinePoolFinalizer is used to ensure deletion of dependencies (nodes, infra).
MachinePoolFinalizer = "machinepool.cluster.x-k8s.io"

// MachinePoolNameLabel is the label indicating the name of the MachinePool a Machine is controleld by.
// Note: The value of this label may be a hash if the MachinePool name is longer than 63 characters.
MachinePoolNameLabel = "cluster.x-k8s.io/pool-name"
)

// ANCHOR: MachinePoolSpec
Expand Down
1 change: 1 addition & 0 deletions exp/internal/controllers/machinepool_controller_noderef.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func (r *MachinePoolReconciler) reconcileNodeRefs(ctx context.Context, cluster *
return ctrl.Result{}, errors.Wrapf(err, "failed to get node references")
}

log.Info("Node ref for mp is result is", "machinepool", mp.Name, "result", nodeRefsResult)
mp.Status.ReadyReplicas = int32(nodeRefsResult.ready)
mp.Status.AvailableReplicas = int32(nodeRefsResult.available)
mp.Status.UnavailableReplicas = mp.Status.Replicas - mp.Status.AvailableReplicas
Expand Down
Loading

0 comments on commit 29f27a9

Please sign in to comment.