Skip to content

Commit 280776d

Browse files
authored
Merge pull request #12465 from sbueringer/pr-capd-contract
⚠️ Update ControlPlaneEndpoint InfraCluster contract, align CAPD to infra contracts
2 parents 0d1b567 + 1f85185 commit 280776d

32 files changed

+313
-106
lines changed

docs/book/src/developer/providers/contracts/control-plane.md

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,19 +237,26 @@ in the ControlPlane resource.
237237
type FooControlPlaneSpec struct {
238238
// controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
239239
// +optional
240-
ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint"`
240+
ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint,omitempty,omitzero"`
241241

242242
// See other rules for more details about mandatory/optional fields in ControlPlane spec.
243243
// Other fields SHOULD be added based on the needs of your provider.
244244
}
245245

246246
// APIEndpoint represents a reachable Kubernetes API endpoint.
247+
// +kubebuilder:validation:MinProperties=1
247248
type APIEndpoint struct {
248249
// host is the hostname on which the API server is serving.
249-
Host string `json:"host"`
250-
250+
// +optional
251+
// +kubebuilder:validation:MinLength=1
252+
// +kubebuilder:validation:MaxLength=512
253+
Host string `json:"host,omitempty"`
254+
251255
// port is the port on which the API server is serving.
252-
Port int32 `json:"port"`
256+
// +optional
257+
// +kubebuilder:validation:Minimum=1
258+
// +kubebuilder:validation:Maximum=65535
259+
Port int32 `json:"port,omitempty"`
253260
}
254261
```
255262

@@ -259,6 +266,35 @@ the Cluster controller will surface this info in Cluster's `spec.controlPlaneEnd
259266
If instead you are developing a control plane provider which is NOT responsible to provide a control plane endpoint,
260267
the implementer should exit reconciliation until it sees Cluster's `spec.controlPlaneEndpoint` populated.
261268

269+
<aside class="note warning">
270+
271+
<h1>Compatibility with the deprecated v1beta1 contract</h1>
272+
273+
In order to ease the transition for providers, the v1beta2 version of the Cluster API contract _temporarily_
274+
preserves compatibility with the deprecated v1beta1 contract; compatibility will be removed tentatively in August 2026.
275+
276+
```go
277+
type FooControlPlaneSpec struct {
278+
// controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
279+
// +optional
280+
ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint"`
281+
282+
// See other rules for more details about mandatory/optional fields in ControlPlane spec.
283+
// Other fields SHOULD be added based on the needs of your provider.
284+
}
285+
286+
// APIEndpoint represents a reachable Kubernetes API endpoint.
287+
type APIEndpoint struct {
288+
// host is the hostname on which the API server is serving.
289+
Host string `json:"host"`
290+
291+
// port is the port on which the API server is serving.
292+
Port int32 `json:"port"`
293+
}
294+
```
295+
296+
</aside>
297+
262298
### ControlPlane: replicas
263299

264300
In case you are developing a control plane provider which allows control of the number of replicas of the

docs/book/src/developer/providers/contracts/infra-cluster.md

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,19 +221,26 @@ in the InfraCluster resource.
221221
type FooClusterSpec struct {
222222
// controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
223223
// +optional
224-
ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint"`
224+
ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint,omitempty,omitzero"`
225225

226226
// See other rules for more details about mandatory/optional fields in InfraCluster spec.
227227
// Other fields SHOULD be added based on the needs of your provider.
228228
}
229229

230230
// APIEndpoint represents a reachable Kubernetes API endpoint.
231+
// +kubebuilder:validation:MinProperties=1
231232
type APIEndpoint struct {
232233
// host is the hostname on which the API server is serving.
233-
Host string `json:"host"`
234-
234+
// +optional
235+
// +kubebuilder:validation:MinLength=1
236+
// +kubebuilder:validation:MaxLength=512
237+
Host string `json:"host,omitempty"`
238+
235239
// port is the port on which the API server is serving.
236-
Port int32 `json:"port"`
240+
// +optional
241+
// +kubebuilder:validation:Minimum=1
242+
// +kubebuilder:validation:Maximum=65535
243+
Port int32 `json:"port,omitempty"`
237244
}
238245
```
239246

@@ -243,6 +250,35 @@ the Cluster controller will surface this info in Cluster's `spec.controlPlaneEnd
243250
If instead you are developing an infrastructure provider which is NOT responsible to provide a control plane endpoint,
244251
the implementer should exit reconciliation until it sees Cluster's `spec.controlPlaneEndpoint` populated.
245252

253+
<aside class="note warning">
254+
255+
<h1>Compatibility with the deprecated v1beta1 contract</h1>
256+
257+
In order to ease the transition for providers, the v1beta2 version of the Cluster API contract _temporarily_
258+
preserves compatibility with the deprecated v1beta1 contract; compatibility will be removed tentatively in August 2026.
259+
260+
```go
261+
type FooClusterSpec struct {
262+
// controlPlaneEndpoint represents the endpoint used to communicate with the control plane.
263+
// +optional
264+
ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint"`
265+
266+
// See other rules for more details about mandatory/optional fields in InfraCluster spec.
267+
// Other fields SHOULD be added based on the needs of your provider.
268+
}
269+
270+
// APIEndpoint represents a reachable Kubernetes API endpoint.
271+
type APIEndpoint struct {
272+
// host is the hostname on which the API server is serving.
273+
Host string `json:"host"`
274+
275+
// port is the port on which the API server is serving.
276+
Port int32 `json:"port"`
277+
}
278+
```
279+
280+
</aside>
281+
246282
### InfraCluster: failure domains
247283

248284
In case you are developing an infrastructure provider which has a notion of failure domains where machines should be

docs/book/src/developer/providers/migrations/v1.10-to-v1.11.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ KubeadmControlPlaneTemplate `spec.template.spec` has been aligned to changes in
437437
Following rules have been changed or are not supported anymore; please read corresponding notes about compatibility
438438
for providers still implementing the v1beta1 contract.
439439

440+
- [InfraCluster: control plane endpoint](../contracts/infra-cluster.md#infracluster-control-plane-endpoint)
440441
- [InfraCluster: failure domains](../contracts/infra-cluster.md#infracluster-failure-domains)
441442
- [InfraCluster: initialization completed](../contracts/infra-cluster.md#infracluster-initialization-completed)
442443
- [InfraCluster: conditions](../contracts/infra-cluster.md#infracluster-conditions)
@@ -488,6 +489,7 @@ for providers still implementing the v1beta1 contract.
488489
Following rules have been changed or are not supported anymore; please read corresponding notes about compatibility
489490
for providers still implementing the v1beta1 contract.
490491

492+
- [ControlPlane: control plane endpoint](../contracts/control-plane.md#controlplane-endpoint)
491493
- [ControlPlane: machines](../contracts/control-plane.md#controlplane-machines)
492494
- [ControlPlane: initialization completed](../contracts/control-plane.md#controlplane-initialization-completed)
493495
- [ControlPlane: replicas](../contracts/control-plane.md#controlplane-replicas)

test/infrastructure/docker/api/v1alpha3/conversion.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ func (dst *DockerMachine) ConvertFrom(srcRaw conversion.Hub) error {
108108
return err
109109
}
110110

111+
if dst.Spec.ProviderID != nil && *dst.Spec.ProviderID == "" {
112+
dst.Spec.ProviderID = nil
113+
}
114+
111115
if err := utilconversion.MarshalData(src, dst); err != nil {
112116
return err
113117
}
@@ -141,6 +145,10 @@ func (dst *DockerMachineTemplate) ConvertFrom(srcRaw conversion.Hub) error {
141145
return err
142146
}
143147

148+
if dst.Spec.Template.Spec.ProviderID != nil && *dst.Spec.Template.Spec.ProviderID == "" {
149+
dst.Spec.Template.Spec.ProviderID = nil
150+
}
151+
144152
// Preserve Hub data on down-conversion except for metadata
145153
if err := utilconversion.MarshalData(src, dst); err != nil {
146154
return err

test/infrastructure/docker/api/v1alpha3/conversion_test.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ func TestFuzzyConversion(t *testing.T) {
4848
}))
4949

5050
t.Run("for DockerMachineTemplate", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
51-
Hub: &infrav1.DockerMachineTemplate{},
52-
Spoke: &DockerMachineTemplate{},
51+
Hub: &infrav1.DockerMachineTemplate{},
52+
Spoke: &DockerMachineTemplate{},
53+
FuzzerFuncs: []fuzzer.FuzzerFuncs{DockerMachineTemplateFuzzFunc},
5354
}))
5455
}
5556

@@ -87,6 +88,7 @@ func hubFailureDomain(in *clusterv1.FailureDomain, c randfill.Continue) {
8788
func DockerMachineFuzzFunc(_ runtimeserializer.CodecFactory) []any {
8889
return []any{
8990
hubDockerMachineStatus,
91+
spokeDockerMachineSpec,
9092
}
9193
}
9294

@@ -105,3 +107,17 @@ func hubDockerMachineStatus(in *infrav1.DockerMachineStatus, c randfill.Continue
105107
}
106108
}
107109
}
110+
111+
func spokeDockerMachineSpec(in *DockerMachineSpec, c randfill.Continue) {
112+
c.FillNoCustom(in)
113+
114+
if in.ProviderID != nil && *in.ProviderID == "" {
115+
in.ProviderID = nil
116+
}
117+
}
118+
119+
func DockerMachineTemplateFuzzFunc(_ runtimeserializer.CodecFactory) []any {
120+
return []any{
121+
spokeDockerMachineSpec,
122+
}
123+
}

test/infrastructure/docker/api/v1alpha3/zz_generated.conversion.go

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

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ func (dst *DockerMachine) ConvertFrom(srcRaw conversion.Hub) error {
136136
return err
137137
}
138138

139+
if dst.Spec.ProviderID != nil && *dst.Spec.ProviderID == "" {
140+
dst.Spec.ProviderID = nil
141+
}
142+
139143
if err := utilconversion.MarshalData(src, dst); err != nil {
140144
return err
141145
}
@@ -169,6 +173,10 @@ func (dst *DockerMachineTemplate) ConvertFrom(srcRaw conversion.Hub) error {
169173
return err
170174
}
171175

176+
if dst.Spec.Template.Spec.ProviderID != nil && *dst.Spec.Template.Spec.ProviderID == "" {
177+
dst.Spec.Template.Spec.ProviderID = nil
178+
}
179+
172180
// Preserve Hub data on down-conversion except for metadata
173181
if err := utilconversion.MarshalData(src, dst); err != nil {
174182
return err

test/infrastructure/docker/api/v1alpha4/conversion_test.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ func TestFuzzyConversion(t *testing.T) {
5454
}))
5555

5656
t.Run("for DockerMachineTemplate", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
57-
Hub: &infrav1.DockerMachineTemplate{},
58-
Spoke: &DockerMachineTemplate{},
57+
Hub: &infrav1.DockerMachineTemplate{},
58+
Spoke: &DockerMachineTemplate{},
59+
FuzzerFuncs: []fuzzer.FuzzerFuncs{DockerMachineTemplateFuzzFunc},
5960
}))
6061
}
6162

@@ -99,6 +100,7 @@ func DockerClusterTemplateFuzzFunc(_ runtimeserializer.CodecFactory) []any {
99100
func DockerMachineFuzzFunc(_ runtimeserializer.CodecFactory) []any {
100101
return []any{
101102
hubDockerMachineStatus,
103+
spokeDockerMachineSpec,
102104
}
103105
}
104106

@@ -117,3 +119,17 @@ func hubDockerMachineStatus(in *infrav1.DockerMachineStatus, c randfill.Continue
117119
}
118120
}
119121
}
122+
123+
func spokeDockerMachineSpec(in *DockerMachineSpec, c randfill.Continue) {
124+
c.FillNoCustom(in)
125+
126+
if in.ProviderID != nil && *in.ProviderID == "" {
127+
in.ProviderID = nil
128+
}
129+
}
130+
131+
func DockerMachineTemplateFuzzFunc(_ runtimeserializer.CodecFactory) []any {
132+
return []any{
133+
spokeDockerMachineSpec,
134+
}
135+
}

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

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

0 commit comments

Comments
 (0)