Skip to content

Commit 22a8cb2

Browse files
refactor(bumpup): CAPI bumps to v1.12.x (#1488)
# v1beta1/v1beta2 Cluster API Testing - Commands and Output --- ## How Has This Been Tested? This change has been tested in three ways: (1) unit tests for the conversion utilities, (2) a bash integration script against a live CAPI cluster, and (3) manual cluster creation and verification. Below are the exact commands run and how to verify the results. ### 1. Unit tests (conversion utilities) **Command:** ```bash cd common && go test ./pkg/capi/utils/... -v -run 'TestConvert|TestConvertRoundtrip|TestConvertUpdateSimulation' ``` **Expected output:** All four tests should PASS: - `TestConvertV1Beta1ClusterToV1Beta2` - `TestConvertV1Beta2ClusterToV1Beta1` - `TestConvertRoundtrip` - `TestConvertUpdateSimulation` **Verification:** Exit code 0; `PASS` for each test. Run from the repo root or from `common/`. --- ### 2. Integration test script (live CAPI cluster) **Prerequisites:** - `kubectl` configured against a cluster with CAPI CRDs and conversion webhooks - ClusterClass `docker-quick-start` (or set `CLUSTER_CLASS` env var) **Option A – Use an existing e2e bootstrap cluster** (after leaving it running): ```bash make e2e-test E2E_LABEL='provider:Docker' E2E_SKIP_CLEANUP=true # After e2e finishes, KUBECONFIG points at the bootstrap cluster ./hack/test-v1beta1-v1beta2-cluster.sh v1beta-test ``` **Option B – Use a dev Kind cluster** (after deploying CAREN locally): ```bash make dev.run-on-kind eval $(make kind.kubeconfig) ./hack/test-v1beta1-v1beta2-cluster.sh v1beta-test ``` **What the script does:** 1. Creates a v1beta1 Cluster with `spec.topology.class: docker-quick-start` and `version: v1.29.0` 2. Fetches the Cluster as v1beta2 and checks `spec.topology.classRef.name` and `spec.topology.version` 3. Applies an updated v1beta1 manifest with `version: v1.30.0` (simulates a GitOps update) 4. Confirms the v1beta2 resource now has `version: v1.30.0` 5. Cleans up the test Cluster and namespace **Verification:** Script exits 0; log line `PASS: v1beta2 Cluster has updated version: v1.30.0`. --- ### 3. Manual cluster creation and verification **Create a management cluster and workload cluster** (from repo root): ```bash make dev.run-on-kind eval $(make kind.kubeconfig) export CLUSTER_NAME=docker-cluster-capi112 export CLUSTER_FILE=examples/capi-quick-start/docker-cluster-cilium-helm-addon.yaml export KUBERNETES_VERSION=v1.30.5 clusterctl generate cluster ${CLUSTER_NAME} \ --from ${CLUSTER_FILE} \ --kubernetes-version ${KUBERNETES_VERSION} \ --worker-machine-count 1 | \ kubectl apply --server-side -f - ``` **Wait for control plane and verify Cluster version:** ```bash kubectl wait clusters/${CLUSTER_NAME} --for=condition=ControlPlaneInitialized --timeout=5m kubectl get cluster ${CLUSTER_NAME} -o jsonpath='{.apiVersion}' && echo kubectl get cluster ${CLUSTER_NAME} -o jsonpath='{.spec.topology.classRef.name}' && echo ``` **Expected:** The Cluster uses v1beta2 storage (or shows conversion); `classRef.name` is set correctly. Runtime hooks process the Cluster without errors. **Cleanup:** ```bash kubectl delete cluster ${CLUSTER_NAME} make kind.delete ``` --- ### 4. envtest limitation The project’s envtest setup uses v1beta2-only storage and no conversion webhooks, so: - v1beta2 Cluster objects can be created and updated directly in envtest - v1beta1 Cluster creation in envtest is not supported (no v1beta1 → v1beta2 conversion) - Full v1beta1 ↔ v1beta2 behavior is validated via unit tests and the integration script against a real CAPI cluster --- ## 1. Conversion Unit Tests ### Command ```bash cd common && go test ./pkg/capi/utils/... -v -run 'TestConvert|TestConvertRoundtrip|TestConvertUpdateSimulation' ``` ### Output ``` === RUN TestConvertV1Beta1ClusterToV1Beta2 === PAUSE TestConvertV1Beta1ClusterToV1Beta2 === RUN TestConvertV1Beta2ClusterToV1Beta1 === PAUSE TestConvertV1Beta2ClusterToV1Beta1 === RUN TestConvertRoundtrip === PAUSE TestConvertRoundtrip === RUN TestConvertUpdateSimulation === PAUSE TestConvertUpdateSimulation === CONT TestConvertV1Beta1ClusterToV1Beta2 === CONT TestConvertRoundtrip === CONT TestConvertV1Beta2ClusterToV1Beta1 === CONT TestConvertUpdateSimulation --- PASS: TestConvertV1Beta1ClusterToV1Beta2 (0.00s) --- PASS: TestConvertUpdateSimulation (0.00s) --- PASS: TestConvertV1Beta2ClusterToV1Beta1 (0.00s) --- PASS: TestConvertRoundtrip (0.00s) PASS ok github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/utils 1.656s ``` ### Tests Coverage | Test | Description | |------|-------------| | `TestConvertV1Beta1ClusterToV1Beta2` | Converts v1beta1 Cluster (topology.class) → v1beta2 (topology.classRef) | | `TestConvertV1Beta2ClusterToV1Beta1` | Converts v1beta2 → v1beta1 | | `TestConvertRoundtrip` | v1beta1 → v1beta2 → v1beta1 roundtrip preserves data | | `TestConvertUpdateSimulation` | Simulates GitOps update: change v1beta1, convert to v1beta2, verify change reflects | --- ## 2. Example v1beta1 Cluster (Input) ```yaml apiVersion: cluster.x-k8s.io/v1beta1 kind: Cluster metadata: name: test-cluster namespace: default spec: topology: class: docker-quick-start # v1beta1: string version: v1.30.0 controlPlane: replicas: 3 ``` --- ## 3. Resulting v1beta2 Cluster (Storage Representation) When the above v1beta1 Cluster is applied to a cluster with CAPI CRDs (and conversion webhooks), the API server converts it for storage. The equivalent v1beta2 representation: ```yaml apiVersion: cluster.x-k8s.io/v1beta2 kind: Cluster metadata: name: test-cluster namespace: default spec: topology: classRef: # v1beta2: object name: docker-quick-start version: v1.30.0 controlPlane: replicas: 3 ``` **Key difference:** v1beta1 uses `spec.topology.class` (string); v1beta2 uses `spec.topology.classRef.name` (object reference). CAPI conversion handles this automatically at API boundaries. --- ## 4. GitOps Update Flow 1. **Create** v1beta1 Cluster (version v1.29.0) 2. **Read** stored resource as v1beta2 → has `classRef` and version v1.29.0 3. **Update** v1beta1 manifest (version v1.30.0) and apply 4. **Verify** v1beta2 reflects the change (version v1.30.0) The conversion logic ensures that when you update the v1beta1 manifest and apply, the underlying stored object (v1beta2) is updated correctly. --- ## 5. Integration Test Script Run against a CAPI-enabled cluster: ```bash ./hack/test-v1beta1-v1beta2-cluster.sh [NAMESPACE] ``` **Prerequisites:** - `kubectl` pointing to a cluster with CAPI CRDs and conversion webhooks - ClusterClass `docker-quick-start` (or set `CLUSTER_CLASS` env var) **Sample run (no cluster available):** ``` [18:17:20] === v1beta1/v1beta2 Cluster API Version Test === [18:17:20] Namespace: v1beta-test [18:17:20] Cluster: v1beta-test-cluster [18:17:20] ClusterClass: docker-quick-start error: error validating "STDIN": error validating data: failed to download openapi: ... ``` *(Failure expected when no cluster is configured.)* **What it does:** 1. Creates a v1beta1 Cluster 2. Fetches it as v1beta2 3. Updates the v1beta1 manifest (version change) 4. Verifies v1beta2 reflects the update 5. Cleans up --- ## 6. envtest Note The project's envtest environment uses **v1beta2-only storage** (no conversion webhooks). Therefore: - You can create/update v1beta2 Cluster objects directly in envtest - v1beta1 Cluster creation would fail in envtest (no v1beta1 → v1beta2 conversion) - Full v1beta1 ↔ v1beta2 behavior is exercised in real CAPI clusters or via the conversion unit tests above --- ## 7. Conversion Utilities Located in `common/pkg/capi/utils/utils.go`: ```go // ConvertV1Beta1ClusterToV1Beta2 - used by runtime hooks when receiving v1beta1 requests func ConvertV1Beta1ClusterToV1Beta2(src *clusterv1beta1.Cluster) (*clusterv1beta2.Cluster, error) // ConvertV1Beta2ClusterToV1Beta1 - reverse conversion func ConvertV1Beta2ClusterToV1Beta1(src *clusterv1beta2.Cluster) (*clusterv1beta1.Cluster, error) ``` These are used by lifecycle handlers (CCM, CSI, CNI, registry, etc.) when the CAPI runtime hooks receive v1beta1 Cluster in requests; they convert to v1beta2 for internal processing.
1 parent dd5bf9a commit 22a8cb2

File tree

406 files changed

+7323
-4594
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

406 files changed

+7323
-4594
lines changed

.golangci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ linters:
6464
- style
6565
importas:
6666
alias:
67-
- pkg: sigs.k8s.io/cluster-api/api/v1beta1
68-
alias: clusterv1
67+
- pkg: sigs.k8s.io/cluster-api/api/core/v1beta2
68+
alias: clusterv1beta2
6969
no-unaliased: false
7070
lll:
7171
line-length: 120
@@ -151,6 +151,10 @@ linters:
151151
- gocritic
152152
path: internal/test/envtest
153153
text: 'hugeParam: input is heavy'
154+
# CAPI v1beta1 packages are deprecated in v1.12+; suppress until the full v1beta2 migration is complete.
155+
- linters:
156+
- staticcheck
157+
text: 'SA1019:.*is deprecated'
154158

155159
# START kube-api-linter rules
156160
- path: ".*"
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
Copyright 2026 Nutanix
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
capiv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" //nolint:staticcheck // suppress complaining on Deprecated package
22+
)
23+
24+
const (
25+
// Kind represents the Kind of AHVMetroZone
26+
AHVMetroZoneKind = "AHVMetroZone"
27+
28+
// AHVMetroZoneFinalizer is the finalizer used by the AHVMetroZone controller to block
29+
// deletion of the AHVMetroZone object if there are references to this object by other resources.
30+
AHVMetroZoneFinalizer = "infrastructure.cluster.x-k8s.io/ahvmetrozone"
31+
)
32+
33+
// AHVMetroZoneSpec defines the desired state of AHVMetroZone
34+
type AHVMetroZoneSpec struct {
35+
// zones defines the Prism Element zones of the AHV Metro Domain.
36+
// +kubebuilder:validation:MinItems=2
37+
// +listType=map
38+
// +listMapKey=name
39+
Zones []MetroZone `json:"zones"`
40+
41+
// placement defines the VM provisioning placement strategy
42+
Placement VMPlacement `json:"placement"`
43+
}
44+
45+
// MetroZone defines a Prism Element zone of the AHV Metro Domain.
46+
type MetroZone struct {
47+
// name is the unique name of the metro zone.
48+
// +kubebuilder:validation:Required
49+
// +kubebuilder:validation:MinLength=1
50+
// +kubebuilder:validation:MaxLength=64
51+
Name string `json:"name"`
52+
53+
// prismElement is the identifier of the Prism Element.
54+
// +kubebuilder:validation:Required
55+
PrismElement NutanixResourceIdentifier `json:"prismElement"`
56+
57+
// subnets holds a list of identifiers (one or more) of the subnets.
58+
// The subnets should already exist in PC and there is no duplicate items configured.
59+
// +kubebuilder:validation:MinItems=1
60+
// +kubebuilder:validation:MaxItems=32
61+
Subnets []NutanixResourceIdentifier `json:"subnets"`
62+
}
63+
64+
// VMPlacementStrategy is an enumeration of VM placement strategies.
65+
type VMPlacementStrategy string
66+
67+
const (
68+
// PreferredStrategy is the VM placement strategy with the specified preferred zone.
69+
PreferredStrategy VMPlacementStrategy = "Preferred"
70+
71+
// RandomStrategy is the VM placement strategy with random choice of zone.
72+
RandomStrategy VMPlacementStrategy = "Random"
73+
)
74+
75+
// VMPlacement defines the placement strategy when provisioning a VM.
76+
// +kubebuilder:validation:XValidation:rule=`self.strategy != "Preferred" || (has(self.preferredZone) && self.preferredZone != "")`,message="preferredZone is required for Preferred strategy."
77+
type VMPlacement struct {
78+
// strategy defines the VM placement strategy of Preferred or Random,
79+
// with Preferred as the default. When the strategy is Preferred, the
80+
// preferredZone must be specified.
81+
// +kubebuilder:validation:Required
82+
// +kubebuilder:default="Preferred"
83+
// +kubebuilder:validation:Enum:=Preferred;Random
84+
Strategy VMPlacementStrategy `json:"strategy"`
85+
86+
// preferredZone specifies the VM should be provisioned to the specified
87+
// preferred zone. When the preferred zone is not available, or being
88+
// evacuated (e.g. in maintainence), the VM will be provisioned to the
89+
// remaining zone. This field is required to set when the VM placement
90+
// strategy is set to Preferred.
91+
// +optional
92+
PreferredZone *string `json:"preferredZone,omitempty"`
93+
}
94+
95+
// AHVMetroZoneStatus defines the observed state of AHVMetroZone resource.
96+
type AHVMetroZoneStatus struct {
97+
// conditions represent the latest states of the AHVMetroZone.
98+
// +optional
99+
Conditions []capiv1beta1.Condition `json:"conditions,omitempty"`
100+
101+
// v1beta2 groups all the fields that will be added or modified in AHVMetroZone's status with the v1beta2 version.
102+
// +optional
103+
V1Beta2 *AHVMetroZoneV1Beta2Status `json:"v1beta2,omitempty"`
104+
}
105+
106+
// AHVMetroZoneV1Beta2Status groups all the fields that will be added or modified in AHVMetroZoneStatus with the v1beta2 version.
107+
// See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.
108+
type AHVMetroZoneV1Beta2Status struct {
109+
// conditions represents the observations of a AHVMetroZone's current state.
110+
// +optional
111+
// +listType=map
112+
// +listMapKey=type
113+
// +kubebuilder:validation:MaxItems=32
114+
Conditions []metav1.Condition `json:"conditions,omitempty"`
115+
}
116+
117+
// +kubebuilder:object:root=true
118+
// +kubebuilder:resource:path=ahvmetrozones,scope=Namespaced,categories=cluster-api
119+
// +kubebuilder:subresource:status
120+
// +kubebuilder:storageversion
121+
// +kubebuilder:metadata:labels=clusterctl.cluster.x-k8s.io/move=
122+
123+
// AHVMetroZone is the Schema for the ahvmetrozones API.
124+
type AHVMetroZone struct {
125+
metav1.TypeMeta `json:",inline"`
126+
metav1.ObjectMeta `json:"metadata,omitempty"`
127+
128+
Spec AHVMetroZoneSpec `json:"spec,omitempty"`
129+
Status AHVMetroZoneStatus `json:"status,omitempty"`
130+
}
131+
132+
// GetConditions returns the set of conditions for this object.
133+
func (z *AHVMetroZone) GetConditions() capiv1beta1.Conditions {
134+
return z.Status.Conditions
135+
}
136+
137+
// SetConditions sets the conditions on this object.
138+
func (z *AHVMetroZone) SetConditions(conditions capiv1beta1.Conditions) {
139+
z.Status.Conditions = conditions
140+
}
141+
142+
// GetV1Beta2Conditions returns the set of conditions for this object.
143+
func (z *AHVMetroZone) GetV1Beta2Conditions() []metav1.Condition {
144+
if z.Status.V1Beta2 == nil {
145+
return nil
146+
}
147+
return z.Status.V1Beta2.Conditions
148+
}
149+
150+
// SetV1Beta2Conditions sets the v1beta2 conditions on this object.
151+
func (z *AHVMetroZone) SetV1Beta2Conditions(conditions []metav1.Condition) {
152+
if z.Status.V1Beta2 == nil {
153+
z.Status.V1Beta2 = &AHVMetroZoneV1Beta2Status{}
154+
}
155+
z.Status.V1Beta2.Conditions = conditions
156+
}
157+
158+
// +kubebuilder:object:root=true
159+
160+
// AHVMetroZoneList contains a list of AHVMetroZone resources
161+
type AHVMetroZoneList struct {
162+
metav1.TypeMeta `json:",inline"`
163+
metav1.ListMeta `json:"metadata,omitempty"`
164+
Items []AHVMetroZone `json:"items"`
165+
}
166+
167+
func init() {
168+
SchemeBuilder.Register(&AHVMetroZone{}, &AHVMetroZoneList{})
169+
}

api/external/github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1/conditions.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ limitations under the License.
1616

1717
package v1beta1
1818

19-
import capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
19+
import capiv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" //nolint:staticcheck // suppress complaining on Deprecated package
2020

2121
const (
22+
Succeeded = "Succeeded"
23+
2224
DeletionFailed = "DeletionFailed"
2325

2426
VolumeGroupDetachFailed = "VolumeGroupDetachFailed"
@@ -28,49 +30,50 @@ const (
2830
const (
2931
// FailureDomainSafeForDeletionCondition indicates whether the failure domain object is safe for deletion,
3032
// ie., when it is not used or referenced by other resources
31-
FailureDomainSafeForDeletionCondition capiv1.ConditionType = "FailureDomainSafeForDeletion"
33+
FailureDomainSafeForDeletionCondition capiv1beta1.ConditionType = "FailureDomainSafeForDeletion"
3234

3335
// FailureDomainInUseReason indicates that the failure domain is used by
3436
// Machines and/or referenced by cluster
3537
FailureDomainInUseReason = "FailureDomainInUse"
3638

3739
// NoFailureDomainsConfiguredCondition indicates no failure domains have been configured
38-
NoFailureDomainsConfiguredCondition capiv1.ConditionType = "NoFailureDomainsConfigured"
40+
NoFailureDomainsConfiguredCondition capiv1beta1.ConditionType = "NoFailureDomainsConfigured"
3941

4042
// FailureDomainsValidatedCondition indicates whether the failure domains are configured correctly or not.
41-
FailureDomainsValidatedCondition capiv1.ConditionType = "FailureDomainsValidated"
43+
FailureDomainsValidatedCondition capiv1beta1.ConditionType = "FailureDomainsValidated"
4244

4345
// FailureDomainsMisconfiguredReason (Severity=Warning) indicates that some of the failure domains
4446
// are misconfigured.
4547
FailureDomainsMisconfiguredReason = "FailureDomainsMisconfigured"
48+
49+
// FailureDomainsValidatedCondition indicates that the failure domains are being validated.
50+
FailureDomainsValidationInProgressReason = "FailureDomainsValidationInProgress"
4651
)
4752

4853
const (
4954
// ClusterCategoryCreatedCondition indicates the status of the category linked to the NutanixCluster
50-
ClusterCategoryCreatedCondition capiv1.ConditionType = "ClusterCategoryCreated"
55+
ClusterCategoryCreatedCondition capiv1beta1.ConditionType = "ClusterCategoryCreated"
5156

5257
ClusterCategoryCreationFailed = "ClusterCategoryCreationFailed"
5358
)
5459

5560
const (
5661
// PrismCentralClientCondition indicates the status of the client used to connect to Prism Central
57-
PrismCentralClientCondition capiv1.ConditionType = "PrismClientInit"
58-
PrismCentralV4ClientCondition capiv1.ConditionType = "PrismClientV4Init"
59-
PrismCentralConvergedV4ClientCondition capiv1.ConditionType = "PrismClientConvergedV4Init"
62+
PrismCentralClientCondition capiv1beta1.ConditionType = "PrismClientInit"
63+
PrismCentralConvergedV4ClientCondition capiv1beta1.ConditionType = "PrismClientConvergedV4Init"
6064

6165
PrismCentralClientInitializationFailed = "PrismClientInitFailed"
62-
PrismCentralV4ClientInitializationFailed = "PrismClientV4InitFailed"
6366
PrismCentralConvergedV4ClientInitializationFailed = "PrismClientConvergedV4InitFailed"
6467
)
6568

6669
const (
6770
// VMProvisionedCondition shows the status of the VM provisioning process
68-
VMProvisionedCondition capiv1.ConditionType = "VMProvisioned"
71+
VMProvisionedCondition capiv1beta1.ConditionType = "VMProvisioned"
6972

7073
VMProvisionedTaskFailed = "FailedVMTask"
7174

7275
// VMAddressesAssignedCondition shows the status of the process of assigning the VM addresses
73-
VMAddressesAssignedCondition capiv1.ConditionType = "VMAddressesAssigned"
76+
VMAddressesAssignedCondition capiv1beta1.ConditionType = "VMAddressesAssigned"
7477

7578
VMAddressesFailed = "VMAddressesFailed"
7679
VMBootTypeInvalid = "VMBootTypeInvalid"
@@ -81,14 +84,14 @@ const (
8184

8285
const (
8386
// VMAddressesAssignedCondition shows the status of the process of assigning the VMs to a project
84-
ProjectAssignedCondition capiv1.ConditionType = "ProjectAssigned"
87+
ProjectAssignedCondition capiv1beta1.ConditionType = "ProjectAssigned"
8588

8689
ProjectAssignationFailed = "ProjectAssignationFailed"
8790
)
8891

8992
const (
9093
// CredentialRefSecretOwnerSetCondition shows the status of setting the Owner
91-
CredentialRefSecretOwnerSetCondition capiv1.ConditionType = "CredentialRefSecretOwnerSet"
94+
CredentialRefSecretOwnerSetCondition capiv1beta1.ConditionType = "CredentialRefSecretOwnerSet"
9295

9396
CredentialRefSecretOwnerSetFailed = "CredentialRefSecretOwnerSetFailed"
9497
TrustBundleSecretOwnerSetCondition = "TrustBundleSecretOwnerSet"

api/external/github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1/nutanix_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ const (
6161

6262
// NutanixResourceIdentifier holds the identity of a Nutanix PC resource (cluster, image, subnet, etc.)
6363
// +union
64+
// +kubebuilder:validation:XValidation:rule="self.type == 'name' ? has(self.name) : !has(self.name)",message="'name' must be set when type is 'name', and forbidden otherwise"
65+
// +kubebuilder:validation:XValidation:rule="self.type == 'uuid' ? has(self.uuid) && self.uuid.contains('-') : !has(self.uuid)",message="'uuid' must be set when type is 'uuid', and forbidden otherwise"
6466
type NutanixResourceIdentifier struct {
6567
// Type is the identifier type to use for this resource.
6668
// +kubebuilder:validation:Required
@@ -69,10 +71,14 @@ type NutanixResourceIdentifier struct {
6971

7072
// uuid is the UUID of the resource in the PC.
7173
// +optional
74+
// +kubebuilder:validation:Format=uuid
75+
// +kubebuilder:validation:MaxLength=36
76+
// +kubebuilder:validation:MinLength=36
7277
UUID *string `json:"uuid,omitempty"`
7378

7479
// name is the resource name in the PC
7580
// +optional
81+
// +kubebuilder:validation:MinLength=1
7682
Name *string `json:"name,omitempty"`
7783
}
7884

api/external/github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1/nutanixcluster_types.go

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
credentialTypes "github.com/nutanix-cloud-native/prism-go-client/environment/credentials"
2424
corev1 "k8s.io/api/core/v1"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26-
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
26+
capiv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" //nolint:staticcheck // suppress complaining on Deprecated package
2727
)
2828

2929
const (
@@ -52,7 +52,7 @@ type NutanixClusterSpec struct {
5252
// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
5353
// host can be either DNS name or ip address
5454
// +optional
55-
ControlPlaneEndpoint capiv1.APIEndpoint `json:"controlPlaneEndpoint"`
55+
ControlPlaneEndpoint capiv1beta1.APIEndpoint `json:"controlPlaneEndpoint"`
5656

5757
// prismCentral holds the endpoint address and port to access the Nutanix Prism Central.
5858
// When a cluster-wide proxy is installed, by default, this endpoint will be accessed via the proxy.
@@ -90,11 +90,11 @@ type NutanixClusterStatus struct {
9090

9191
// failureDomains are a list of failure domains configured in the
9292
// cluster's spec and validated by the cluster controller.
93-
FailureDomains capiv1.FailureDomains `json:"failureDomains,omitempty"`
93+
FailureDomains capiv1beta1.FailureDomains `json:"failureDomains,omitempty"`
9494

9595
// Conditions defines current service state of the NutanixCluster.
9696
// +optional
97-
Conditions capiv1.Conditions `json:"conditions,omitempty"`
97+
Conditions capiv1beta1.Conditions `json:"conditions,omitempty"`
9898

9999
// Will be set in case of failure of Cluster instance
100100
// +optional
@@ -103,6 +103,21 @@ type NutanixClusterStatus struct {
103103
// Will be set in case of failure of Cluster instance
104104
// +optional
105105
FailureMessage *string `json:"failureMessage,omitempty"`
106+
107+
// v1beta2 groups all the fields that will be added or modified in NutanixCluster's status with the v1beta2 version.
108+
// +optional
109+
V1Beta2 *NutanixClusterV1Beta2Status `json:"v1beta2,omitempty"`
110+
}
111+
112+
// NutanixClusterV1Beta2Status groups all the fields that will be added or modified in NutanixClusterStatus with the v1beta2 version.
113+
// See https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20240916-improve-status-in-CAPI-resources.md for more context.
114+
type NutanixClusterV1Beta2Status struct {
115+
// conditions represents the observations of a NutanixCluster's current state.
116+
// +optional
117+
// +listType=map
118+
// +listMapKey=type
119+
// +kubebuilder:validation:MaxItems=32
120+
Conditions []metav1.Condition `json:"conditions,omitempty"`
106121
}
107122

108123
// +kubebuilder:object:root=true
@@ -156,15 +171,31 @@ type NutanixFailureDomainConfig struct {
156171
}
157172

158173
// GetConditions returns the set of conditions for this object.
159-
func (ncl *NutanixCluster) GetConditions() capiv1.Conditions {
174+
func (ncl *NutanixCluster) GetConditions() capiv1beta1.Conditions {
160175
return ncl.Status.Conditions
161176
}
162177

163178
// SetConditions sets the conditions on this object.
164-
func (ncl *NutanixCluster) SetConditions(conditions capiv1.Conditions) {
179+
func (ncl *NutanixCluster) SetConditions(conditions capiv1beta1.Conditions) {
165180
ncl.Status.Conditions = conditions
166181
}
167182

183+
// GetV1Beta2Conditions returns the set of v1beta2 conditions for this object.
184+
func (ncl *NutanixCluster) GetV1Beta2Conditions() []metav1.Condition {
185+
if ncl.Status.V1Beta2 == nil {
186+
return nil
187+
}
188+
return ncl.Status.V1Beta2.Conditions
189+
}
190+
191+
// SetV1Beta2Conditions sets the v1beta2 conditions on this object.
192+
func (ncl *NutanixCluster) SetV1Beta2Conditions(conditions []metav1.Condition) {
193+
if ncl.Status.V1Beta2 == nil {
194+
ncl.Status.V1Beta2 = &NutanixClusterV1Beta2Status{}
195+
}
196+
ncl.Status.V1Beta2.Conditions = conditions
197+
}
198+
168199
func (ncl *NutanixCluster) GetPrismCentralCredentialRef() (*credentialTypes.NutanixCredentialReference, error) {
169200
prismCentralInfo := ncl.Spec.PrismCentral
170201
if prismCentralInfo == nil {

0 commit comments

Comments
 (0)