Skip to content

Commit 8f48a58

Browse files
committed
Add MachinePool Machine implementation in core CAPI components
1 parent da10c33 commit 8f48a58

File tree

8 files changed

+796
-12
lines changed

8 files changed

+796
-12
lines changed

api/v1beta1/machine_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ const (
4343
// MachineDeploymentNameLabel is the label set on machines if they're controlled by MachineDeployment.
4444
MachineDeploymentNameLabel = "cluster.x-k8s.io/deployment-name"
4545

46+
// MachinePoolNameLabel is the label indicating the name of the MachinePool a Machine is controlled by.
47+
// Note: The value of this label may be a hash if the MachinePool name is longer than 63 characters.
48+
MachinePoolNameLabel = "cluster.x-k8s.io/pool-name"
49+
4650
// MachineControlPlaneNameLabel is the label set on machines if they're controlled by a ControlPlane.
4751
// Note: The value of this label may be a hash if the control plane name is longer than 63 characters.
4852
MachineControlPlaneNameLabel = "cluster.x-k8s.io/control-plane-name"

api/v1beta1/machine_webhook.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,16 @@ func (m *Machine) validate(old *Machine) error {
9494
var allErrs field.ErrorList
9595
specPath := field.NewPath("spec")
9696
if m.Spec.Bootstrap.ConfigRef == nil && m.Spec.Bootstrap.DataSecretName == nil {
97-
allErrs = append(
98-
allErrs,
99-
field.Required(
100-
specPath.Child("bootstrap", "data"),
101-
"expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated",
102-
),
103-
)
97+
// MachinePool Machines don't have a bootstrap configRef, so don't require it. The bootstrap config is instead owned by the MachinePool.
98+
if !isMachinePoolMachine(m) {
99+
allErrs = append(
100+
allErrs,
101+
field.Required(
102+
specPath.Child("bootstrap", "data"),
103+
"expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated",
104+
),
105+
)
106+
}
104107
}
105108

106109
if m.Spec.Bootstrap.ConfigRef != nil && m.Spec.Bootstrap.ConfigRef.Namespace != m.Namespace {
@@ -143,3 +146,13 @@ func (m *Machine) validate(old *Machine) error {
143146
}
144147
return apierrors.NewInvalid(GroupVersion.WithKind("Machine").GroupKind(), m.Name, allErrs)
145148
}
149+
150+
func isMachinePoolMachine(m *Machine) bool {
151+
for _, owner := range m.OwnerReferences {
152+
if owner.Kind == "MachinePool" {
153+
return true
154+
}
155+
}
156+
157+
return false
158+
}

api/v1beta1/machine_webhook_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,59 @@ func TestMachineClusterNameImmutable(t *testing.T) {
213213
}
214214
}
215215

216+
func TestIsMachinePoolMachine(t *testing.T) {
217+
tests := []struct {
218+
name string
219+
machine Machine
220+
isMPM bool
221+
}{
222+
{
223+
name: "machine is a MachinePoolMachine",
224+
machine: Machine{
225+
ObjectMeta: metav1.ObjectMeta{
226+
OwnerReferences: []metav1.OwnerReference{
227+
{
228+
Kind: "MachinePool",
229+
},
230+
},
231+
},
232+
},
233+
isMPM: true,
234+
},
235+
{
236+
name: "machine is not a MachinePoolMachine",
237+
machine: Machine{
238+
ObjectMeta: metav1.ObjectMeta{
239+
OwnerReferences: []metav1.OwnerReference{
240+
{
241+
Kind: "NotMachinePool",
242+
},
243+
},
244+
},
245+
},
246+
isMPM: false,
247+
},
248+
{
249+
name: "machine is not a MachinePoolMachine, no owner references",
250+
machine: Machine{
251+
ObjectMeta: metav1.ObjectMeta{
252+
OwnerReferences: nil,
253+
},
254+
},
255+
isMPM: false,
256+
},
257+
}
258+
259+
for _, tt := range tests {
260+
t.Run(tt.name, func(t *testing.T) {
261+
g := NewWithT(t)
262+
263+
result := isMachinePoolMachine(&tt.machine)
264+
g.Expect(result).To(Equal(tt.isMPM))
265+
})
266+
}
267+
}
268+
216269
func TestMachineVersionValidation(t *testing.T) {
217270
tests := []struct {
218271
name string

docs/book/src/developer/architecture/controllers/machine-pool.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# MachinePool Controller
1+
# MachinePool Controller
22

33
![](../../../images/cluster-admission-machinepool-controller.png)
44

@@ -95,8 +95,11 @@ The `status` object **may** define several fields that do not affect functionali
9595

9696
* `failureReason` - is a string that explains why a fatal error has occurred, if possible.
9797
* `failureMessage` - is a string that holds the message contained by the error.
98+
* `infrastructureMachineKind` - the kind of the InfraMachines. This should be set if the InfrastructureMachinePool plans to support MachinePool Machines.
9899

99-
Example:
100+
**Note:** Infrastructure providers can support MachinePool Machines by having the InfraMachinePool set the `infrastructureMachineKind` to the kind of their InfrastructureMachines. The InfrastructureMachinePool will be responsible for creating InfrastructureMachines as the MachinePool is scaled up, and the MachinePool controller will create Machines for each InfrastructureMachine and set the ownerRef. The InfrastructureMachinePool will be responsible for deleting the Machines as the MachinePool is scaled down in order for the Machine deletion workflow to function properly. In addition, the InfrastructureMachines must also have the following labels set by the InfrastructureMachinePool: `cluster.x-k8s.io/cluster-name` and `cluster.x-k8s.io/pool-name`. The `MachinePoolNameLabel` must also be formatted with `capilabels.MustFormatValue()` so that it will not exceed character limits.
101+
102+
Example
100103
```yaml
101104
kind: MyMachinePool
102105
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
@@ -106,6 +109,7 @@ spec:
106109
- cloud:////my-cloud-provider-id-1
107110
status:
108111
ready: true
112+
infrastructureMachineKind: InfrastructureMachine
109113
```
110114

111115
#### Externally Managed Autoscaler
@@ -133,6 +137,7 @@ spec:
133137
status:
134138
ready: true
135139
phase: Scaling
140+
infrastructureMachineKind: InfrastructureMachine
136141
```
137142

138143
It is the provider's responsibility to update Cluster API's `Spec.Replicas` property to the value observed in the underlying infra environment as it changes in response to external autoscaling behaviors. Once that is done, and the number of providerID items is equal to the `Spec.Replicas` property, the MachinePools's `Status.Phase` property will be set to `Running` by Cluster API.

docs/book/src/developer/providers/migrations/v1.4-to-v1.5.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ maintainers of providers and consumers of our Go API.
2929

3030
### API Changes
3131

32-
-
32+
- InfrastructureMachinePools now include an optional status field for `infrastructureMachineKind`. This allows infrastructure providers to support MachinePool Machines by having the InfraMachinePool set the `infrastructureMachineKind` to the kind of their InfrastructureMachines. The InfrastructureMachinePool will be responsible for creating InfrastructureMachines as the MachinePool is scaled up, and the MachinePool controller will create Machines for each InfrastructureMachine and set the ownerRef. The InfrastructureMachinePool will be responsible for deleting the Machines as the MachinePool is scaled down in order for the Machine deletion workflow to function properly. In addition, the InfrastructureMachines must also have the following labels set by the InfrastructureMachinePool: `cluster.x-k8s.io/cluster-name` and `cluster.x-k8s.io/pool-name`. The `MachinePoolNameLabel` must also be formatted with `capilabels.MustFormatValue()` so that it will not exceed character limits. See the [MachinePool Machines proposal](https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20220209-machinepool-machines.md) for more details and the [CAPD implementation](https://github.com/kubernetes-sigs/cluster-api/pull/8842) for a reference.
3333

3434
### Other
3535

docs/book/src/reference/labels_and_annotations.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
| Label | Note |
5-
|:------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
5+
| :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
66
| cluster.x-k8s.io/cluster-name | It is set on machines linked to a cluster and external objects(bootstrap and infrastructure providers). |
77
| topology.cluster.x-k8s.io/owned | It is set on all the object which are managed as part of a ClusterTopology. |
88
| topology.cluster.x-k8s.io/deployment-name | It is set on the generated MachineDeployment objects to track the name of the MachineDeployment topology it represents. |
@@ -13,14 +13,15 @@
1313
| cluster.x-k8s.io/set-name | It is set on machines if they're controlled by MachineSet. The value of this label may be a hash if the MachineSet name is longer than 63 characters. |
1414
| cluster.x-k8s.io/control-plane-name | It is set on machines if they're controlled by a control plane. The value of this label may be a hash if the control plane name is longer than 63 characters. |
1515
| cluster.x-k8s.io/deployment-name | It is set on machines if they're controlled by a MachineDeployment. |
16+
| cluster.x-k8s.io/pool-name | It is set on machines if they're controlled by a MachinePool. |
1617
| machine-template-hash | It is applied to Machines in a MachineDeployment containing the hash of the template. |
1718
<br>
1819

1920

2021
**Supported Annotations:**
2122

2223
| Annotation | Note |
23-
|:-----------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
24+
| :--------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2425
| clusterctl.cluster.x-k8s.io/skip-crd-name-preflight-check | Can be placed on provider CRDs, so that clusterctl doesn't emit an error if the CRD doesn't comply with Cluster APIs naming scheme. Only CRDs that are referenced by core Cluster API CRDs have to comply with the naming scheme. |
2526
| clusterctl.cluster.x-k8s.io/delete-for-move | DeleteForMoveAnnotation will be set to objects that are going to be deleted from the source cluster after being moved to the target cluster during the clusterctl move operation. It will help any validation webhook to take decision based on it. |
2627
| unsafe.topology.cluster.x-k8s.io/disable-update-class-name-check | It can be used to disable the webhook check on update that disallows a pre-existing Cluster to be populated with Topology information and Class. |

0 commit comments

Comments
 (0)