From cd1ad35c455712e9aecee295b525484dfc53f5f4 Mon Sep 17 00:00:00 2001 From: Daniel Lipovetsky Date: Tue, 16 Apr 2024 16:39:04 -0700 Subject: [PATCH] feat: Add additionalCategories field to Nutanix machine details patch --- api/v1alpha1/nutanix_node_types.go | 32 +++++++++++++++++++ api/v1alpha1/zz_generated.deepcopy.go | 20 ++++++++++++ .../customization/nutanix/machine-details.md | 9 ++++++ .../nutanix/mutation/machinedetails/inject.go | 8 +++++ .../inject_control_plane_test.go | 24 ++++++++++++++ .../mutation/machinedetails/variables_test.go | 10 ++++++ 6 files changed, 103 insertions(+) diff --git a/api/v1alpha1/nutanix_node_types.go b/api/v1alpha1/nutanix_node_types.go index b02441895..58a7ce3b5 100644 --- a/api/v1alpha1/nutanix_node_types.go +++ b/api/v1alpha1/nutanix_node_types.go @@ -51,6 +51,11 @@ type NutanixMachineDetails struct { // The identifier (uuid or name) can be obtained from the console or API. Subnets []NutanixResourceIdentifier `json:"subnets"` + // List of categories that need to be added to the machines. Categories must already + // exist in Prism Central. One category key can have more than one value. + // +optional + AdditionalCategories []NutanixCategoryIdentifier `json:"additionalCategories,omitempty"` + // Defines the boot type of the virtual machine. Only supports UEFI and Legacy BootType NutanixBootType `json:"bootType,omitempty"` @@ -93,6 +98,12 @@ func (NutanixMachineDetails) VariableSchema() clusterv1.VariableSchema { "subnet identifies the network subnet to use for the machine. The identifier (uuid or name) can be obtained from the console or API.", ).OpenAPIV3Schema), }, + "additionalCategories": { + Type: "array", + //nolint:lll // Description is long. + Description: "List of categories that need to be added to the machines. Categories must already exist in Prism Central. One category key can have more than one value.", + Items: ptr.To(NutanixCategoryIdentifier{}.VariableSchema().OpenAPIV3Schema), + }, "bootType": NutanixBootType( capxv1.NutanixBootTypeLegacy, ).VariableSchema(). @@ -173,3 +184,24 @@ func (NutanixResourceIdentifier) VariableSchemaFromDescription( }, } } + +type NutanixCategoryIdentifier capxv1.NutanixCategoryIdentifier + +func (NutanixCategoryIdentifier) VariableSchema() clusterv1.VariableSchema { + return clusterv1.VariableSchema{ + OpenAPIV3Schema: clusterv1.JSONSchemaProps{ + Description: "Nutanix Category Identifier", + Type: "object", + Properties: map[string]clusterv1.JSONSchemaProps{ + "key": { + Type: "string", + Description: "key is the Key of category in PC.", + }, + "value": { + Type: "string", + Description: "value is the category value linked to the category key in PC.", + }, + }, + }, + } +} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 3d45fbdb7..eb051f5a0 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -732,6 +732,21 @@ func (in *NodeConfigSpec) DeepCopy() *NodeConfigSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixCategoryIdentifier) DeepCopyInto(out *NutanixCategoryIdentifier) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixCategoryIdentifier. +func (in *NutanixCategoryIdentifier) DeepCopy() *NutanixCategoryIdentifier { + if in == nil { + return nil + } + out := new(NutanixCategoryIdentifier) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NutanixMachineDetails) DeepCopyInto(out *NutanixMachineDetails) { *out = *in @@ -745,6 +760,11 @@ func (in *NutanixMachineDetails) DeepCopyInto(out *NutanixMachineDetails) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.AdditionalCategories != nil { + in, out := &in.AdditionalCategories, &out.AdditionalCategories + *out = make([]NutanixCategoryIdentifier, len(*in)) + copy(*out, *in) + } out.SystemDiskSize = in.SystemDiskSize.DeepCopy() } diff --git a/docs/content/customization/nutanix/machine-details.md b/docs/content/customization/nutanix/machine-details.md index 03b218228..e3ff70c14 100644 --- a/docs/content/customization/nutanix/machine-details.md +++ b/docs/content/customization/nutanix/machine-details.md @@ -50,6 +50,9 @@ spec: subnets: - name: subnet-name type: name + additionalCategories: + - key: example-key + value: example-value systemDiskSize: 40Gi vcpuSockets: 2 vcpusPerSocket: 1 @@ -79,6 +82,9 @@ spec: subnet: - name: subnet-name type: name + additionalCategories: + - key: example-key + value: example-value systemDiskSize: 40Gi vcpuSockets: 2 vcpusPerSocket: 1 @@ -106,6 +112,9 @@ spec: subnet: - name: subnet-name type: name + additionalCategories: + - key: example-key + value: example-value systemDiskSize: 40Gi vcpuSockets: 2 vcpusPerSocket: 1 diff --git a/pkg/handlers/nutanix/mutation/machinedetails/inject.go b/pkg/handlers/nutanix/mutation/machinedetails/inject.go index 173329a94..139842ed4 100644 --- a/pkg/handlers/nutanix/mutation/machinedetails/inject.go +++ b/pkg/handlers/nutanix/mutation/machinedetails/inject.go @@ -108,6 +108,14 @@ func (h *nutanixMachineDetailsPatchHandler) Mutate( spec.Subnets[i] = capxv1.NutanixResourceIdentifier(subnet) } + spec.AdditionalCategories = make( + []capxv1.NutanixCategoryIdentifier, + len(nutanixMachineDetailsVar.AdditionalCategories), + ) + for i, category := range nutanixMachineDetailsVar.AdditionalCategories { + spec.AdditionalCategories[i] = capxv1.NutanixCategoryIdentifier(category) + } + obj.Spec.Template.Spec = spec return nil }, diff --git a/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go b/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go index 35b0e74f8..9a87d6eec 100644 --- a/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go +++ b/pkg/handlers/nutanix/mutation/machinedetails/inject_control_plane_test.go @@ -41,6 +41,16 @@ var ( Name: ptr.To("fake-subnet"), }, }, + AdditionalCategories: []v1alpha1.NutanixCategoryIdentifier{ + { + Key: "fake-key", + Value: "fake-value", + }, + { + Key: "fake-key2", + Value: "fake-value2", + }, + }, } matchersForAllFieldsSet = []capitest.JSONPatchMatcher{ @@ -94,6 +104,20 @@ var ( Path: "/spec/template/spec/subnet", ValueMatcher: gomega.HaveLen(1), }, + { + Operation: "add", + Path: "/spec/template/spec/additionalCategories", + ValueMatcher: gomega.ContainElements( + gomega.SatisfyAll( + gomega.HaveKeyWithValue("key", "fake-key"), + gomega.HaveKeyWithValue("value", "fake-value"), + ), + gomega.SatisfyAll( + gomega.HaveKeyWithValue("key", "fake-key2"), + gomega.HaveKeyWithValue("value", "fake-value2"), + ), + ), + }, } ) diff --git a/pkg/handlers/nutanix/mutation/machinedetails/variables_test.go b/pkg/handlers/nutanix/mutation/machinedetails/variables_test.go index f5eceb4ad..b9dda5d33 100644 --- a/pkg/handlers/nutanix/mutation/machinedetails/variables_test.go +++ b/pkg/handlers/nutanix/mutation/machinedetails/variables_test.go @@ -45,6 +45,16 @@ func TestVariableValidation(t *testing.T) { 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", + }, + }, }, }, },