Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions api/v1alpha1/nutanix_node_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ type NutanixMachineDetails struct {
// systemDiskSize is size (in Quantity format) of the system disk of the VM
// The minimum systemDiskSize is 20Gi bytes
SystemDiskSize resource.Quantity `json:"systemDiskSize"`

// add the virtual machines to the project defined in Prism Central.
// The project must already be present in the Prism Central.
// +optional
Project *NutanixResourceIdentifier `json:"project,omitempty"`
}

func (NutanixMachineDetails) VariableSchema() clusterv1.VariableSchema {
Expand Down Expand Up @@ -112,6 +117,10 @@ func (NutanixMachineDetails) VariableSchema() clusterv1.VariableSchema {
Description: "systemDiskSize is size (in Quantity format) of the system disk of the VM eg. 20Gi",
Type: "string",
},
"project": NutanixResourceIdentifier{}.VariableSchemaFromDescription(
//nolint:lll // Long description.
"add the virtual machines to the project defined in Prism Central. The project must already be present in the Prism Central.",
).OpenAPIV3Schema,
},
Required: []string{
"vcpusPerSocket",
Expand Down
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions docs/content/customization/nutanix/machine-details.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ spec:
name: os-image-name
type: name
memorySize: 4Gi
project:
type: name
name: project-name
subnets:
- name: subnet-name
type: name
Expand All @@ -47,6 +50,9 @@ spec:
name: os-image-name
type: name
memorySize: 4Gi
project:
type: name
name: project-name
subnets:
- name: subnet-name
type: name
Expand Down Expand Up @@ -78,6 +84,9 @@ spec:
name: os-image-name
type: name
memorySize: 4Gi
project:
type: name
name: project-name
providerID: nutanix://vm-uuid
subnet:
- name: subnet-name
Expand Down Expand Up @@ -108,6 +117,9 @@ spec:
name: os-image-name
type: name
memorySize: 4Gi
project:
type: name
name: project-name
providerID: nutanix://vm-uuid
subnet:
- name: subnet-name
Expand Down
5 changes: 5 additions & 0 deletions pkg/handlers/nutanix/mutation/machinedetails/inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/utils/ptr"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -116,6 +117,10 @@ func (h *nutanixMachineDetailsPatchHandler) Mutate(
spec.AdditionalCategories[i] = capxv1.NutanixCategoryIdentifier(category)
}

if nutanixMachineDetailsVar.Project != nil {
spec.Project = ptr.To(capxv1.NutanixResourceIdentifier(*nutanixMachineDetailsVar.Project))
}

obj.Spec.Template.Spec = spec
return nil
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ var (
Value: "fake-value2",
},
},
Project: ptr.To(v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: ptr.To("fake-project"),
}),
}

matchersForAllFieldsSet = []capitest.JSONPatchMatcher{
Expand Down Expand Up @@ -118,6 +122,14 @@ var (
),
),
},
{
Operation: "add",
Path: "/spec/template/spec/project",
ValueMatcher: gomega.SatisfyAll(
gomega.HaveKeyWithValue("type", "name"),
gomega.HaveKeyWithValue("name", "fake-project"),
),
},
}
)

Expand Down
188 changes: 85 additions & 103 deletions pkg/handlers/nutanix/mutation/machinedetails/variables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,126 +17,108 @@ import (
)

func TestVariableValidation(t *testing.T) {
testImageName := "fake-image"
testPEClusterName := "fake-pe-cluster"
requiredFields := minimumClusterConfigSpec()

withAdditionalCategories := minimumClusterConfigSpec()
//nolint:lll // gofumpt formats is this way
withAdditionalCategories.ControlPlane.Nutanix.MachineDetails.AdditionalCategories = []v1alpha1.NutanixCategoryIdentifier{
{
Key: "fake-key",
Value: "fake-value1",
},
{
Key: "fake-key",
Value: "fake-value2",
},
}

withProject := minimumClusterConfigSpec()
withProject.ControlPlane.Nutanix.MachineDetails.Project = ptr.To(
v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: ptr.To("fake-project"),
},
)

invalidBootType := minimumClusterConfigSpec()
invalidBootType.ControlPlane.Nutanix.MachineDetails.BootType = "invalid-boot-type"

invalidImageType := minimumClusterConfigSpec()
invalidImageType.ControlPlane.Nutanix.MachineDetails.Image.Type = "invalid-image-type"

invalidClusterType := minimumClusterConfigSpec()
invalidClusterType.ControlPlane.Nutanix.MachineDetails.Cluster.Type = "invalid-cluster-type"

invalidProjectType := minimumClusterConfigSpec()
invalidProjectType.ControlPlane.Nutanix.MachineDetails.Project = ptr.To(
v1alpha1.NutanixResourceIdentifier{
Type: "invalid-project-type",
Name: ptr.To("fake-project"),
},
)

capitest.ValidateDiscoverVariables(
t,
clusterconfig.MetaVariableName,
ptr.To(v1alpha1.ClusterConfigSpec{Nutanix: &v1alpha1.NutanixSpec{}}.VariableSchema()),
true,
nutanixclusterconfig.NewVariable,
capitest.VariableTestDef{
Name: "all fields set",
Vals: v1alpha1.ClusterConfigSpec{
ControlPlane: &v1alpha1.NodeConfigSpec{
Nutanix: &v1alpha1.NutanixNodeSpec{
MachineDetails: v1alpha1.NutanixMachineDetails{
BootType: v1alpha1.NutanixBootType(capxv1.NutanixBootTypeLegacy),
VCPUSockets: 2,
VCPUsPerSocket: 1,
Image: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: &testImageName,
},
Cluster: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: &testPEClusterName,
},
MemorySize: resource.MustParse("8Gi"),
SystemDiskSize: resource.MustParse("40Gi"),
Subnets: []v1alpha1.NutanixResourceIdentifier{},
AdditionalCategories: []v1alpha1.NutanixCategoryIdentifier{
{
Key: "fake-key",
Value: "fake-value1",
},
{
Key: "fake-key",
Value: "fake-value2",
},
},
},
},
},
},
Name: "required fields set",
Vals: requiredFields,
},
capitest.VariableTestDef{
Name: "invalid boot type",
Vals: v1alpha1.ClusterConfigSpec{
ControlPlane: &v1alpha1.NodeConfigSpec{
Nutanix: &v1alpha1.NutanixNodeSpec{
MachineDetails: v1alpha1.NutanixMachineDetails{
BootType: "invalid",
VCPUSockets: 2,
VCPUsPerSocket: 1,
Image: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: &testImageName,
},
Cluster: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: &testPEClusterName,
},
MemorySize: resource.MustParse("8Gi"),
SystemDiskSize: resource.MustParse("40Gi"),
Subnets: []v1alpha1.NutanixResourceIdentifier{},
},
},
},
},
Name: "additional categories set",
Vals: withAdditionalCategories,
},
capitest.VariableTestDef{
Name: "project set",
Vals: withProject,
},
capitest.VariableTestDef{
Name: "invalid boot type",
Vals: invalidBootType,
ExpectError: true,
},
capitest.VariableTestDef{
Name: "invalid image type",
Vals: v1alpha1.ClusterConfigSpec{
ControlPlane: &v1alpha1.NodeConfigSpec{
Nutanix: &v1alpha1.NutanixNodeSpec{
MachineDetails: v1alpha1.NutanixMachineDetails{
BootType: v1alpha1.NutanixBootType(capxv1.NutanixBootTypeLegacy),
VCPUSockets: 2,
VCPUsPerSocket: 1,
Image: v1alpha1.NutanixResourceIdentifier{
Type: "invalid",
Name: &testImageName,
},
Cluster: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: &testPEClusterName,
},
MemorySize: resource.MustParse("8Gi"),
SystemDiskSize: resource.MustParse("40Gi"),
Subnets: []v1alpha1.NutanixResourceIdentifier{},
},
},
},
},
Name: "invalid image type",
Vals: invalidImageType,
ExpectError: true,
},
capitest.VariableTestDef{
Name: "invalid cluster type",
Vals: invalidClusterType,
ExpectError: true,
},
capitest.VariableTestDef{
Name: "invalid cluster type",
Vals: v1alpha1.ClusterConfigSpec{
ControlPlane: &v1alpha1.NodeConfigSpec{
Nutanix: &v1alpha1.NutanixNodeSpec{
MachineDetails: v1alpha1.NutanixMachineDetails{
BootType: v1alpha1.NutanixBootType(capxv1.NutanixBootTypeLegacy),
VCPUSockets: 2,
VCPUsPerSocket: 1,
Image: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: &testImageName,
},
Cluster: v1alpha1.NutanixResourceIdentifier{
Type: "invalid",
Name: &testPEClusterName,
},
MemorySize: resource.MustParse("8Gi"),
SystemDiskSize: resource.MustParse("40Gi"),
Subnets: []v1alpha1.NutanixResourceIdentifier{},
},
Name: "invalid project type",
Vals: invalidProjectType,
ExpectError: true,
},
)
}

func minimumClusterConfigSpec() v1alpha1.ClusterConfigSpec {
return v1alpha1.ClusterConfigSpec{
ControlPlane: &v1alpha1.NodeConfigSpec{
Nutanix: &v1alpha1.NutanixNodeSpec{
MachineDetails: v1alpha1.NutanixMachineDetails{
BootType: v1alpha1.NutanixBootType(capxv1.NutanixBootTypeLegacy),
VCPUSockets: 2,
VCPUsPerSocket: 1,
Image: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: ptr.To("fake-image"),
},
Cluster: v1alpha1.NutanixResourceIdentifier{
Type: capxv1.NutanixIdentifierName,
Name: ptr.To("fake-pe-cluster"),
},
MemorySize: resource.MustParse("8Gi"),
SystemDiskSize: resource.MustParse("40Gi"),
Subnets: []v1alpha1.NutanixResourceIdentifier{},
},
},
ExpectError: true,
},
)
}
}