Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Commit aa6feca

Browse files
feat: Add support for CAPX (#6)
* fix: added support for capx * refactor: reuse existing CAPX types * fix: set allowed enums for Nutanix resource types * fix: set required for Nutanix node type * fix: reuse resource.Quantity types * fix: set defaults and validation * fix: rename field to subnets * refactor: fix handlers after API changes * test: add new unit tests * refactor: bring back host instead of address * fix: examples with updated APIs * fix: using latest capx private brach to test kube-vip fix * fix: set namespace for credentialRef The patch failed with the following error: got failure response with message failed to apply JSON patches to input: replace operation does not apply: doc is missing key: /spec/template/spec/prismCentral/credentialRef/namespace: missing value. * docs: fix users example * docs: deploying Calico for Nutanix * fix: added basic docs for nutanix mutations * fix: lint related fixes * docs: minor changes --------- Co-authored-by: Dimitri Koshkin <[email protected]>
1 parent ced51e3 commit aa6feca

Some content is hidden

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

51 files changed

+3290
-40
lines changed

api/v1alpha1/clusterconfig_types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type ClusterConfigSpec struct {
4545
AWS *AWSSpec `json:"aws,omitempty"`
4646
// +optional
4747
Docker *DockerSpec `json:"docker,omitempty"`
48+
// +optional
49+
Nutanix *NutanixSpec `json:"nutanix,omitempty"`
4850

4951
GenericClusterConfig `json:",inline"`
5052

@@ -76,6 +78,16 @@ func (s ClusterConfigSpec) VariableSchema() clusterv1.VariableSchema { //nolint:
7678
}.VariableSchema().OpenAPIV3Schema,
7779
},
7880
)
81+
case s.Nutanix != nil:
82+
maps.Copy(
83+
clusterConfigProps.OpenAPIV3Schema.Properties,
84+
map[string]clusterv1.JSONSchemaProps{
85+
NutanixVariableName: NutanixSpec{}.VariableSchema().OpenAPIV3Schema,
86+
"controlPlane": NodeConfigSpec{
87+
Nutanix: &NutanixNodeSpec{},
88+
}.VariableSchema().OpenAPIV3Schema,
89+
},
90+
)
7991
}
8092

8193
return clusterConfigProps

api/v1alpha1/common_types.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33

44
package v1alpha1
55

6+
import (
7+
"k8s.io/utils/ptr"
8+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
9+
10+
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/variables"
11+
)
12+
13+
const (
14+
APIServerPort = 6443
15+
)
16+
617
// ObjectMeta is metadata that all persisted resources must have, which includes all objects
718
// users must create. This is a copy of customizable fields from metav1.ObjectMeta.
819
//
@@ -23,3 +34,29 @@ type ObjectMeta struct {
2334
// +optional
2435
Annotations map[string]string `json:"annotations,omitempty"`
2536
}
37+
38+
type ControlPlaneEndpointSpec clusterv1.APIEndpoint
39+
40+
func (ControlPlaneEndpointSpec) VariableSchema() clusterv1.VariableSchema {
41+
return clusterv1.VariableSchema{
42+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
43+
Description: "Kubernetes control-plane endpoint configuration",
44+
Type: "object",
45+
Properties: map[string]clusterv1.JSONSchemaProps{
46+
"host": {
47+
Description: "host ip/fqdn for control plane API Server",
48+
Type: "string",
49+
MinLength: ptr.To[int64](1),
50+
},
51+
"port": {
52+
Description: "port for control plane API Server",
53+
Type: "integer",
54+
Default: variables.MustMarshal(APIServerPort),
55+
Minimum: ptr.To[int64](1),
56+
Maximum: ptr.To[int64](65535),
57+
},
58+
},
59+
Required: []string{"host", "port"},
60+
},
61+
}
62+
}

api/v1alpha1/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ const (
1212
ClusterAutoscalerVariableName = "clusterAutoscaler"
1313
// AWSVariableName is the AWS config patch variable name.
1414
AWSVariableName = "aws"
15+
// NutanixVariableName is the Nutanix config patch variable name.
16+
NutanixVariableName = "nutanix"
1517
)

api/v1alpha1/node_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ type NodeConfigSpec struct {
2929
AWS *AWSNodeSpec `json:"aws,omitempty"`
3030
// +optional
3131
Docker *DockerNodeSpec `json:"docker,omitempty"`
32+
// +optional
33+
Nutanix *NutanixNodeSpec `json:"nutanix,omitempty"`
3234
}
3335

3436
func (s NodeConfigSpec) VariableSchema() clusterv1.VariableSchema {
@@ -49,6 +51,13 @@ func (s NodeConfigSpec) VariableSchema() clusterv1.VariableSchema {
4951
"docker": DockerNodeSpec{}.VariableSchema().OpenAPIV3Schema,
5052
},
5153
)
54+
case s.Nutanix != nil:
55+
maps.Copy(
56+
nodeConfigProps.OpenAPIV3Schema.Properties,
57+
map[string]clusterv1.JSONSchemaProps{
58+
"nutanix": NutanixNodeSpec{}.VariableSchema().OpenAPIV3Schema,
59+
},
60+
)
5261
}
5362

5463
return nodeConfigProps
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright 2024 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
corev1 "k8s.io/api/core/v1"
8+
"k8s.io/utils/ptr"
9+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
10+
11+
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/variables"
12+
)
13+
14+
const (
15+
PrismCentralPort = 9440
16+
)
17+
18+
// NutanixSpec defines the desired state of NutanixCluster.
19+
type NutanixSpec struct {
20+
// ControlPlaneEndpoint represents the endpoint used to communicate with the control plane.
21+
// host can be either DNS name or ip address
22+
ControlPlaneEndpoint clusterv1.APIEndpoint `json:"controlPlaneEndpoint"`
23+
24+
// Nutanix Prism Central endpoint configuration.
25+
PrismCentralEndpoint NutanixPrismCentralEndpointSpec `json:"prismCentralEndpoint"`
26+
}
27+
28+
func (NutanixSpec) VariableSchema() clusterv1.VariableSchema {
29+
return clusterv1.VariableSchema{
30+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
31+
Description: "Nutanix cluster configuration",
32+
Type: "object",
33+
Properties: map[string]clusterv1.JSONSchemaProps{
34+
"controlPlaneEndpoint": ControlPlaneEndpointSpec{}.VariableSchema().OpenAPIV3Schema,
35+
"prismCentralEndpoint": NutanixPrismCentralEndpointSpec{}.VariableSchema().OpenAPIV3Schema,
36+
},
37+
},
38+
}
39+
}
40+
41+
type NutanixPrismCentralEndpointSpec struct {
42+
// host is the DNS name or IP address of the Nutanix Prism Central
43+
Host string `json:"host"`
44+
45+
// port is the port number to access the Nutanix Prism Central
46+
Port int32 `json:"port"`
47+
48+
// use insecure connection to Prism Central endpoint
49+
// +optional
50+
Insecure bool `json:"insecure"`
51+
52+
// A reference to the ConfigMap containing a PEM encoded x509 cert for the RootCA that was used to create
53+
// the certificate for a Prism Central that uses certificates that were issued by a non-publicly trusted RootCA.
54+
// The trust bundle is added to the cert pool used to authenticate the TLS connection to the Prism Central.
55+
// +optional
56+
AdditionalTrustBundle *corev1.LocalObjectReference `json:"additionalTrustBundle,omitempty"`
57+
58+
// A reference to the Secret for credential information for the target Prism Central instance
59+
Credentials corev1.LocalObjectReference `json:"credentials"`
60+
}
61+
62+
func (NutanixPrismCentralEndpointSpec) VariableSchema() clusterv1.VariableSchema {
63+
return clusterv1.VariableSchema{
64+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
65+
Description: "Nutanix Prism Central endpoint configuration",
66+
Type: "object",
67+
Properties: map[string]clusterv1.JSONSchemaProps{
68+
"host": {
69+
Description: "the DNS name or IP address of the Nutanix Prism Central",
70+
Type: "string",
71+
MinLength: ptr.To[int64](1),
72+
},
73+
"port": {
74+
Description: "The port number to access the Nutanix Prism Central",
75+
Type: "integer",
76+
Default: variables.MustMarshal(PrismCentralPort),
77+
Minimum: ptr.To[int64](1),
78+
Maximum: ptr.To[int64](65535),
79+
},
80+
"insecure": {
81+
Description: "Use insecure connection to Prism Central endpoint",
82+
Type: "boolean",
83+
},
84+
"additionalTrustBundle": {
85+
Description: "A reference to the ConfigMap containing a PEM encoded x509 cert for the RootCA " +
86+
"that was used to create the certificate for a Prism Central that uses certificates " +
87+
"that were issued by a non-publicly trusted RootCA." +
88+
"The trust bundle is added to the cert pool used to authenticate the TLS connection " +
89+
"to the Prism Central.",
90+
Type: "object",
91+
Properties: map[string]clusterv1.JSONSchemaProps{
92+
"name": {
93+
Description: "The name of the ConfigMap",
94+
Type: "string",
95+
},
96+
},
97+
Required: []string{"name"},
98+
},
99+
"credentials": {
100+
Description: "A reference to the Secret for credential information" +
101+
"for the target Prism Central instance",
102+
Type: "object",
103+
Properties: map[string]clusterv1.JSONSchemaProps{
104+
"name": {
105+
Description: "The name of the Secret",
106+
Type: "string",
107+
},
108+
},
109+
Required: []string{"name"},
110+
},
111+
},
112+
Required: []string{"host", "port", "credentials"},
113+
},
114+
}
115+
}

api/v1alpha1/nutanix_node_types.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// Copyright 2024 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package v1alpha1
5+
6+
import (
7+
"k8s.io/apimachinery/pkg/api/resource"
8+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
9+
10+
capxv1 "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/external/github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1"
11+
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/variables"
12+
)
13+
14+
type NutanixNodeSpec struct {
15+
MachineDetails NutanixMachineDetails `json:"machineDetails"`
16+
}
17+
18+
func (NutanixNodeSpec) VariableSchema() clusterv1.VariableSchema {
19+
return clusterv1.VariableSchema{
20+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
21+
Description: "Nutanix Node configuration",
22+
Type: "object",
23+
Properties: map[string]clusterv1.JSONSchemaProps{
24+
"machineDetails": NutanixMachineDetails{}.VariableSchema().OpenAPIV3Schema,
25+
},
26+
Required: []string{"machineDetails"},
27+
},
28+
}
29+
}
30+
31+
type NutanixMachineDetails struct {
32+
// vcpusPerSocket is the number of vCPUs per socket of the VM
33+
VCPUsPerSocket int32 `json:"vcpusPerSocket"`
34+
35+
// vcpuSockets is the number of vCPU sockets of the VM
36+
VCPUSockets int32 `json:"vcpuSockets"`
37+
38+
// memorySize is the memory size (in Quantity format) of the VM
39+
MemorySize resource.Quantity `json:"memorySize"`
40+
41+
// image is to identify the rhcos image uploaded to the Prism Central (PC)
42+
// The image identifier (uuid or name) can be obtained from the Prism Central console
43+
// or using the prism_central API.
44+
Image NutanixResourceIdentifier `json:"image"`
45+
46+
// cluster is to identify the cluster (the Prism Element under management
47+
// of the Prism Central), in which the Machine's VM will be created.
48+
// The cluster identifier (uuid or name) can be obtained from the Prism Central console
49+
// or using the prism_central API.
50+
Cluster NutanixResourceIdentifier `json:"cluster"`
51+
52+
// subnet is to identify the cluster's network subnet to use for the Machine's VM
53+
// The cluster identifier (uuid or name) can be obtained from the Prism Central console
54+
// or using the prism_central API.
55+
Subnets NutanixResourceIdentifiers `json:"subnets"`
56+
57+
// Defines the boot type of the virtual machine. Only supports UEFI and Legacy
58+
BootType NutanixBootType `json:"bootType,omitempty"`
59+
60+
// systemDiskSize is size (in Quantity format) of the system disk of the VM
61+
// The minimum systemDiskSize is 20Gi bytes
62+
SystemDiskSize resource.Quantity `json:"systemDiskSize"`
63+
}
64+
65+
func (NutanixMachineDetails) VariableSchema() clusterv1.VariableSchema {
66+
return clusterv1.VariableSchema{
67+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
68+
Description: "Nutanix Machine configuration",
69+
Type: "object",
70+
Properties: map[string]clusterv1.JSONSchemaProps{
71+
"vcpusPerSocket": {
72+
Description: "vcpusPerSocket is the number of vCPUs per socket of the VM",
73+
Type: "integer",
74+
},
75+
"vcpuSockets": {
76+
Description: "vcpuSockets is the number of vCPU sockets of the VM",
77+
Type: "integer",
78+
},
79+
"memorySize": {
80+
Description: "memorySize is the memory size (in Quantity format) of the VM eg. 4Gi",
81+
Type: "string",
82+
},
83+
"image": NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema,
84+
"cluster": NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema,
85+
"subnets": NutanixResourceIdentifiers{}.VariableSchema().OpenAPIV3Schema,
86+
"bootType": NutanixBootType(capxv1.NutanixBootTypeLegacy).VariableSchema().OpenAPIV3Schema,
87+
"systemDiskSize": {
88+
Description: "systemDiskSize is size (in Quantity format) of the system disk of the VM eg. 20Gi",
89+
Type: "string",
90+
},
91+
},
92+
Required: []string{"vcpusPerSocket", "vcpuSockets", "memorySize", "image", "cluster", "subnets", "systemDiskSize"},
93+
},
94+
}
95+
}
96+
97+
// NutanixIdentifierType is an enumeration of different resource identifier types.
98+
type NutanixIdentifierType capxv1.NutanixIdentifierType
99+
100+
func (NutanixIdentifierType) VariableSchema() clusterv1.VariableSchema {
101+
return clusterv1.VariableSchema{
102+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
103+
Type: "string",
104+
Description: "NutanixIdentifierType is an enumeration of different resource identifier types",
105+
Enum: variables.MustMarshalValuesToEnumJSON(
106+
capxv1.NutanixIdentifierUUID,
107+
capxv1.NutanixIdentifierName,
108+
),
109+
},
110+
}
111+
}
112+
113+
// NutanixBootType is an enumeration of different boot types.
114+
type NutanixBootType capxv1.NutanixBootType
115+
116+
func (NutanixBootType) VariableSchema() clusterv1.VariableSchema {
117+
return clusterv1.VariableSchema{
118+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
119+
Type: "string",
120+
Description: "NutanixBootType is an enumeration of different boot types.",
121+
Enum: variables.MustMarshalValuesToEnumJSON(
122+
capxv1.NutanixBootTypeLegacy,
123+
capxv1.NutanixBootTypeUEFI,
124+
),
125+
},
126+
}
127+
}
128+
129+
type NutanixResourceIdentifier capxv1.NutanixResourceIdentifier
130+
131+
func (NutanixResourceIdentifier) VariableSchema() clusterv1.VariableSchema {
132+
return clusterv1.VariableSchema{
133+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
134+
Description: "Nutanix Resource Identifier",
135+
Type: "object",
136+
Properties: map[string]clusterv1.JSONSchemaProps{
137+
"type": NutanixIdentifierType(capxv1.NutanixIdentifierName).VariableSchema().OpenAPIV3Schema,
138+
"uuid": {
139+
Type: "string",
140+
Description: "uuid is the UUID of the resource in the PC.",
141+
},
142+
"name": {
143+
Type: "string",
144+
Description: "name is the resource name in the PC.",
145+
},
146+
},
147+
},
148+
}
149+
}
150+
151+
type NutanixResourceIdentifiers []NutanixResourceIdentifier
152+
153+
func (NutanixResourceIdentifiers) VariableSchema() clusterv1.VariableSchema {
154+
resourceSchema := NutanixResourceIdentifier{}.VariableSchema().OpenAPIV3Schema
155+
156+
return clusterv1.VariableSchema{
157+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
158+
Description: "Nutanix resource identifier",
159+
Type: "array",
160+
Items: &resourceSchema,
161+
},
162+
}
163+
}

0 commit comments

Comments
 (0)