From bb6cf4d3b6cc182d8c3d0e4b5718a4591c1e66fc Mon Sep 17 00:00:00 2001
From: okozachenko1203
schedulerHintAdditionalProperties
SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints +to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, +such as specifying certain host aggregates or availability zones.
+schedulerHintAdditionalProperties
SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints +to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, +such as specifying certain host aggregates or availability zones.
+schedulerHintAdditionalProperties
SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints +to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, +such as specifying certain host aggregates or availability zones.
+schedulerHintAdditionalProperties
SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints +to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, +such as specifying certain host aggregates or availability zones.
+schedulerHintAdditionalProperties
SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints +to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, +such as specifying certain host aggregates or availability zones.
++(Appears on: +OpenStackMachineSpec) +
++
SchedulerHintAdditionalProperty represents a single additional property for a scheduler hint. +It includes a Name to identify the property and a Value that can be of various types.
+ +Field | +Description | +
---|---|
+name + +string + + |
+
+ Name is the name of the scheduler hint property. +It is a unique identifier for the property. + |
+
+value + + +SchedulerHintAdditionalValue + + + |
+
+ Value is the value of the scheduler hint property, which can be of various types +(e.g., bool, string, int). The type is indicated by the Value.Type field. + |
+
+(Appears on: +SchedulerHintAdditionalProperty) +
++
SchedulerHintAdditionalValue represents the value of a scheduler hint property. +The value can be of various types: Bool, String, or Number. +The Type field indicates the type of the value being used.
+ +Field | +Description | +
---|---|
+type + + +SchedulerHintValueType + + + |
+
+ Type represents the type of the value. +Valid values are Bool, String, and Number. + |
+
+bool + +bool + + |
+
+ Bool is the boolean value of the scheduler hint, used when Type is “Bool”. +This field is required if type is ‘Bool’, and must not be set otherwise. + |
+
+number + +int + + |
+
+ Number is the integer value of the scheduler hint, used when Type is “Number”. +This field is required if type is ‘Number’, and must not be set otherwise. + |
+
+string + +string + + |
+
+ String is the string value of the scheduler hint, used when Type is “String”. +This field is required if type is ‘String’, and must not be set otherwise. + |
+
string
alias)+(Appears on: +SchedulerHintAdditionalValue) +
++
SchedulerHintValueType is the type that represents allowed values for the Type field.
+ +Value | +Description | +
---|---|
"Bool" |
++ |
"Number" |
++ |
"String" |
++ |
diff --git a/hack/codegen/openapi/zz_generated.openapi.go b/hack/codegen/openapi/zz_generated.openapi.go index 35b305b44a..22e4d15847 100644 --- a/hack/codegen/openapi/zz_generated.openapi.go +++ b/hack/codegen/openapi/zz_generated.openapi.go @@ -444,6 +444,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.Router": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_Router(ref), "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.RouterFilter": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_RouterFilter(ref), "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.RouterParam": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_RouterParam(ref), + "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalProperty": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SchedulerHintAdditionalProperty(ref), + "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalValue": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SchedulerHintAdditionalValue(ref), "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SecurityGroupFilter(ref), "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupParam": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SecurityGroupParam(ref), "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupRuleSpec": schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SecurityGroupRuleSpec(ref), @@ -16711,12 +16713,34 @@ func schema_sigsk8sio_cluster_api_provider_openstack_api_v1alpha1_OpenStackServe Ref: ref("k8s.io/api/core/v1.LocalObjectReference"), }, }, + "schedulerHintAdditionalProperties": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "name", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, such as specifying certain host aggregates or availability zones.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalProperty"), + }, + }, + }, + }, + }, }, Required: []string{"flavor", "identityRef", "image", "ports", "sshKeyName"}, }, }, Dependencies: []string{ - "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.TypedLocalObjectReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.AdditionalBlockDevice", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.PortOpts", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.RootVolume", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata"}, + "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.TypedLocalObjectReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.AdditionalBlockDevice", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.PortOpts", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.RootVolume", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalProperty", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata"}, } } @@ -23444,12 +23468,34 @@ func schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_OpenStackMachin Ref: ref("k8s.io/api/core/v1.TypedLocalObjectReference"), }, }, + "schedulerHintAdditionalProperties": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-map-keys": []interface{}{ + "name", + }, + "x-kubernetes-list-type": "map", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "SchedulerHintAdditionalProperties are arbitrary key/value pairs that provide additional hints to the OpenStack scheduler. These hints can influence how instances are placed on the infrastructure, such as specifying certain host aggregates or availability zones.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalProperty"), + }, + }, + }, + }, + }, }, Required: []string{"flavor", "image"}, }, }, Dependencies: []string{ - "k8s.io/api/core/v1.TypedLocalObjectReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.AdditionalBlockDevice", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.PortOpts", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.RootVolume", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata"}, + "k8s.io/api/core/v1.TypedLocalObjectReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.AdditionalBlockDevice", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.OpenStackIdentityReference", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.PortOpts", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.RootVolume", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalProperty", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerGroupParam", "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ServerMetadata"}, } } @@ -24492,6 +24538,80 @@ func schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_RouterParam(ref } } +func schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SchedulerHintAdditionalProperty(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "SchedulerHintAdditionalProperty represents a single additional property for a scheduler hint. It includes a Name to identify the property and a Value that can be of various types.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the name of the scheduler hint property. It is a unique identifier for the property.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "value": { + SchemaProps: spec.SchemaProps{ + Description: "Value is the value of the scheduler hint property, which can be of various types (e.g., bool, string, int). The type is indicated by the Value.Type field.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalValue"), + }, + }, + }, + Required: []string{"name", "value"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SchedulerHintAdditionalValue"}, + } +} + +func schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SchedulerHintAdditionalValue(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "SchedulerHintAdditionalValue represents the value of a scheduler hint property. The value can be of various types: Bool, String, or Number. The Type field indicates the type of the value being used.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type represents the type of the value. Valid values are Bool, String, and Number.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "bool": { + SchemaProps: spec.SchemaProps{ + Description: "Bool is the boolean value of the scheduler hint, used when Type is \"Bool\". This field is required if type is 'Bool', and must not be set otherwise.", + Type: []string{"boolean"}, + Format: "", + }, + }, + "number": { + SchemaProps: spec.SchemaProps{ + Description: "Number is the integer value of the scheduler hint, used when Type is \"Number\". This field is required if type is 'Number', and must not be set otherwise.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "string": { + SchemaProps: spec.SchemaProps{ + Description: "String is the string value of the scheduler hint, used when Type is \"String\". This field is required if type is 'String', and must not be set otherwise.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"type"}, + }, + }, + } +} + func schema_sigsk8sio_cluster_api_provider_openstack_api_v1beta1_SecurityGroupFilter(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go index 90284ba926..a47348b0b3 100644 --- a/pkg/cloud/services/compute/instance.go +++ b/pkg/cloud/services/compute/instance.go @@ -107,13 +107,27 @@ func (s *Service) createInstanceImpl(eventObject runtime.Object, instanceSpec *I BlockDevice: blockDevices, } + schedulerAdditionalProperties := make(map[string]interface{}) + + for _, prop := range instanceSpec.SchedulerAdditionalProperties { + switch prop.Value.Type { + case infrav1.SchedulerHintTypeBool: + schedulerAdditionalProperties[prop.Name] = *prop.Value.Bool + case infrav1.SchedulerHintTypeString: + schedulerAdditionalProperties[prop.Name] = *prop.Value.String + case infrav1.SchedulerHintTypeNumber: + schedulerAdditionalProperties[prop.Name] = *prop.Value.Number + } + } + server, err := s.getComputeClient().CreateServer( keypairs.CreateOptsExt{ CreateOptsBuilder: serverCreateOpts, KeyName: instanceSpec.SSHKeyName, }, servers.SchedulerHintOpts{ - Group: instanceSpec.ServerGroupID, + Group: instanceSpec.ServerGroupID, + AdditionalProperties: schedulerAdditionalProperties, }, ) if err != nil { diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go index 53eeb9bae0..88c88a4a48 100644 --- a/pkg/cloud/services/compute/instance_test.go +++ b/pkg/cloud/services/compute/instance_test.go @@ -913,6 +913,90 @@ func TestService_ReconcileInstance(t *testing.T) { }, wantErr: true, }, + { + name: "With custom scheduler hint bool", + getInstanceSpec: func() *InstanceSpec { + s := getDefaultInstanceSpec() + s.SchedulerAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "custom_hint", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeBool, + Bool: ptr.To(true), + }, + }, + } + return s + }, + expect: func(g Gomega, r *recorders) { + expectDefaultFlavor(r.compute) + createOpts := getDefaultServerCreateOpts() + schedulerHintOpts := servers.SchedulerHintOpts{ + Group: serverGroupUUID, + AdditionalProperties: map[string]any{ + "custom_hint": true, + }, + } + expectCreateServer(g, r.compute, withSSHKey(createOpts), schedulerHintOpts, false) + }, + wantErr: false, + }, + { + name: "With custom scheduler hint number", + getInstanceSpec: func() *InstanceSpec { + s := getDefaultInstanceSpec() + s.SchedulerAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "custom_hint", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeNumber, + Number: ptr.To(1), + }, + }, + } + return s + }, + expect: func(g Gomega, r *recorders) { + expectDefaultFlavor(r.compute) + createOpts := getDefaultServerCreateOpts() + schedulerHintOpts := servers.SchedulerHintOpts{ + Group: serverGroupUUID, + AdditionalProperties: map[string]any{ + "custom_hint": 1, + }, + } + expectCreateServer(g, r.compute, withSSHKey(createOpts), schedulerHintOpts, false) + }, + wantErr: false, + }, + { + name: "With custom scheduler hint string", + getInstanceSpec: func() *InstanceSpec { + s := getDefaultInstanceSpec() + s.SchedulerAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "custom_hint", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeString, + String: ptr.To("custom hint"), + }, + }, + } + return s + }, + expect: func(g Gomega, r *recorders) { + expectDefaultFlavor(r.compute) + createOpts := getDefaultServerCreateOpts() + schedulerHintOpts := servers.SchedulerHintOpts{ + Group: serverGroupUUID, + AdditionalProperties: map[string]any{ + "custom_hint": "custom hint", + }, + } + expectCreateServer(g, r.compute, withSSHKey(createOpts), schedulerHintOpts, false) + }, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/cloud/services/compute/instance_types.go b/pkg/cloud/services/compute/instance_types.go index ecf927921e..0322926ed8 100644 --- a/pkg/cloud/services/compute/instance_types.go +++ b/pkg/cloud/services/compute/instance_types.go @@ -30,19 +30,20 @@ import ( // InstanceSpec defines the fields which can be set on a new OpenStack instance. type InstanceSpec struct { - Name string - ImageID string - Flavor string - SSHKeyName string - UserData string - Metadata map[string]string - ConfigDrive bool - FailureDomain string - RootVolume *infrav1.RootVolume - AdditionalBlockDevices []infrav1.AdditionalBlockDevice - ServerGroupID string - Trunk bool - Tags []string + Name string + ImageID string + Flavor string + SSHKeyName string + UserData string + Metadata map[string]string + ConfigDrive bool + FailureDomain string + RootVolume *infrav1.RootVolume + AdditionalBlockDevices []infrav1.AdditionalBlockDevice + ServerGroupID string + Trunk bool + Tags []string + SchedulerAdditionalProperties []infrav1.SchedulerHintAdditionalProperty } // InstanceIdentifier describes an instance which has not necessarily been fetched. diff --git a/pkg/generated/applyconfiguration/api/v1alpha1/openstackserverspec.go b/pkg/generated/applyconfiguration/api/v1alpha1/openstackserverspec.go index d07a3bbdbc..1067d7729b 100644 --- a/pkg/generated/applyconfiguration/api/v1alpha1/openstackserverspec.go +++ b/pkg/generated/applyconfiguration/api/v1alpha1/openstackserverspec.go @@ -26,22 +26,23 @@ import ( // OpenStackServerSpecApplyConfiguration represents an declarative configuration of the OpenStackServerSpec type for use // with apply. type OpenStackServerSpecApplyConfiguration struct { - AdditionalBlockDevices []v1beta1.AdditionalBlockDeviceApplyConfiguration `json:"additionalBlockDevices,omitempty"` - AvailabilityZone *string `json:"availabilityZone,omitempty"` - ConfigDrive *bool `json:"configDrive,omitempty"` - Flavor *string `json:"flavor,omitempty"` - FloatingIPPoolRef *v1.TypedLocalObjectReference `json:"floatingIPPoolRef,omitempty"` - IdentityRef *v1beta1.OpenStackIdentityReferenceApplyConfiguration `json:"identityRef,omitempty"` - Image *v1beta1.ImageParamApplyConfiguration `json:"image,omitempty"` - Ports []v1beta1.PortOptsApplyConfiguration `json:"ports,omitempty"` - RootVolume *v1beta1.RootVolumeApplyConfiguration `json:"rootVolume,omitempty"` - SSHKeyName *string `json:"sshKeyName,omitempty"` - SecurityGroups []v1beta1.SecurityGroupParamApplyConfiguration `json:"securityGroups,omitempty"` - ServerGroup *v1beta1.ServerGroupParamApplyConfiguration `json:"serverGroup,omitempty"` - ServerMetadata []v1beta1.ServerMetadataApplyConfiguration `json:"serverMetadata,omitempty"` - Tags []string `json:"tags,omitempty"` - Trunk *bool `json:"trunk,omitempty"` - UserDataRef *v1.LocalObjectReference `json:"userDataRef,omitempty"` + AdditionalBlockDevices []v1beta1.AdditionalBlockDeviceApplyConfiguration `json:"additionalBlockDevices,omitempty"` + AvailabilityZone *string `json:"availabilityZone,omitempty"` + ConfigDrive *bool `json:"configDrive,omitempty"` + Flavor *string `json:"flavor,omitempty"` + FloatingIPPoolRef *v1.TypedLocalObjectReference `json:"floatingIPPoolRef,omitempty"` + IdentityRef *v1beta1.OpenStackIdentityReferenceApplyConfiguration `json:"identityRef,omitempty"` + Image *v1beta1.ImageParamApplyConfiguration `json:"image,omitempty"` + Ports []v1beta1.PortOptsApplyConfiguration `json:"ports,omitempty"` + RootVolume *v1beta1.RootVolumeApplyConfiguration `json:"rootVolume,omitempty"` + SSHKeyName *string `json:"sshKeyName,omitempty"` + SecurityGroups []v1beta1.SecurityGroupParamApplyConfiguration `json:"securityGroups,omitempty"` + ServerGroup *v1beta1.ServerGroupParamApplyConfiguration `json:"serverGroup,omitempty"` + ServerMetadata []v1beta1.ServerMetadataApplyConfiguration `json:"serverMetadata,omitempty"` + Tags []string `json:"tags,omitempty"` + Trunk *bool `json:"trunk,omitempty"` + UserDataRef *v1.LocalObjectReference `json:"userDataRef,omitempty"` + SchedulerHintAdditionalProperties []v1beta1.SchedulerHintAdditionalPropertyApplyConfiguration `json:"schedulerHintAdditionalProperties,omitempty"` } // OpenStackServerSpecApplyConfiguration constructs an declarative configuration of the OpenStackServerSpec type for use with @@ -199,3 +200,16 @@ func (b *OpenStackServerSpecApplyConfiguration) WithUserDataRef(value v1.LocalOb b.UserDataRef = &value return b } + +// WithSchedulerHintAdditionalProperties adds the given value to the SchedulerHintAdditionalProperties field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the SchedulerHintAdditionalProperties field. +func (b *OpenStackServerSpecApplyConfiguration) WithSchedulerHintAdditionalProperties(values ...*v1beta1.SchedulerHintAdditionalPropertyApplyConfiguration) *OpenStackServerSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithSchedulerHintAdditionalProperties") + } + b.SchedulerHintAdditionalProperties = append(b.SchedulerHintAdditionalProperties, *values[i]) + } + return b +} diff --git a/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinespec.go b/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinespec.go index 6a80ea4093..b495fdf89e 100644 --- a/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinespec.go +++ b/pkg/generated/applyconfiguration/api/v1beta1/openstackmachinespec.go @@ -25,21 +25,22 @@ import ( // OpenStackMachineSpecApplyConfiguration represents an declarative configuration of the OpenStackMachineSpec type for use // with apply. type OpenStackMachineSpecApplyConfiguration struct { - ProviderID *string `json:"providerID,omitempty"` - Flavor *string `json:"flavor,omitempty"` - Image *ImageParamApplyConfiguration `json:"image,omitempty"` - SSHKeyName *string `json:"sshKeyName,omitempty"` - Ports []PortOptsApplyConfiguration `json:"ports,omitempty"` - SecurityGroups []SecurityGroupParamApplyConfiguration `json:"securityGroups,omitempty"` - Trunk *bool `json:"trunk,omitempty"` - Tags []string `json:"tags,omitempty"` - ServerMetadata []ServerMetadataApplyConfiguration `json:"serverMetadata,omitempty"` - ConfigDrive *bool `json:"configDrive,omitempty"` - RootVolume *RootVolumeApplyConfiguration `json:"rootVolume,omitempty"` - AdditionalBlockDevices []AdditionalBlockDeviceApplyConfiguration `json:"additionalBlockDevices,omitempty"` - ServerGroup *ServerGroupParamApplyConfiguration `json:"serverGroup,omitempty"` - IdentityRef *OpenStackIdentityReferenceApplyConfiguration `json:"identityRef,omitempty"` - FloatingIPPoolRef *v1.TypedLocalObjectReference `json:"floatingIPPoolRef,omitempty"` + ProviderID *string `json:"providerID,omitempty"` + Flavor *string `json:"flavor,omitempty"` + Image *ImageParamApplyConfiguration `json:"image,omitempty"` + SSHKeyName *string `json:"sshKeyName,omitempty"` + Ports []PortOptsApplyConfiguration `json:"ports,omitempty"` + SecurityGroups []SecurityGroupParamApplyConfiguration `json:"securityGroups,omitempty"` + Trunk *bool `json:"trunk,omitempty"` + Tags []string `json:"tags,omitempty"` + ServerMetadata []ServerMetadataApplyConfiguration `json:"serverMetadata,omitempty"` + ConfigDrive *bool `json:"configDrive,omitempty"` + RootVolume *RootVolumeApplyConfiguration `json:"rootVolume,omitempty"` + AdditionalBlockDevices []AdditionalBlockDeviceApplyConfiguration `json:"additionalBlockDevices,omitempty"` + ServerGroup *ServerGroupParamApplyConfiguration `json:"serverGroup,omitempty"` + IdentityRef *OpenStackIdentityReferenceApplyConfiguration `json:"identityRef,omitempty"` + FloatingIPPoolRef *v1.TypedLocalObjectReference `json:"floatingIPPoolRef,omitempty"` + SchedulerHintAdditionalProperties []SchedulerHintAdditionalPropertyApplyConfiguration `json:"schedulerHintAdditionalProperties,omitempty"` } // OpenStackMachineSpecApplyConfiguration constructs an declarative configuration of the OpenStackMachineSpec type for use with @@ -189,3 +190,16 @@ func (b *OpenStackMachineSpecApplyConfiguration) WithFloatingIPPoolRef(value v1. b.FloatingIPPoolRef = &value return b } + +// WithSchedulerHintAdditionalProperties adds the given value to the SchedulerHintAdditionalProperties field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the SchedulerHintAdditionalProperties field. +func (b *OpenStackMachineSpecApplyConfiguration) WithSchedulerHintAdditionalProperties(values ...*SchedulerHintAdditionalPropertyApplyConfiguration) *OpenStackMachineSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithSchedulerHintAdditionalProperties") + } + b.SchedulerHintAdditionalProperties = append(b.SchedulerHintAdditionalProperties, *values[i]) + } + return b +} diff --git a/pkg/generated/applyconfiguration/api/v1beta1/schedulerhintadditionalproperty.go b/pkg/generated/applyconfiguration/api/v1beta1/schedulerhintadditionalproperty.go new file mode 100644 index 0000000000..56b5173a51 --- /dev/null +++ b/pkg/generated/applyconfiguration/api/v1beta1/schedulerhintadditionalproperty.go @@ -0,0 +1,48 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1beta1 + +// SchedulerHintAdditionalPropertyApplyConfiguration represents an declarative configuration of the SchedulerHintAdditionalProperty type for use +// with apply. +type SchedulerHintAdditionalPropertyApplyConfiguration struct { + Name *string `json:"name,omitempty"` + Value *SchedulerHintAdditionalValueApplyConfiguration `json:"value,omitempty"` +} + +// SchedulerHintAdditionalPropertyApplyConfiguration constructs an declarative configuration of the SchedulerHintAdditionalProperty type for use with +// apply. +func SchedulerHintAdditionalProperty() *SchedulerHintAdditionalPropertyApplyConfiguration { + return &SchedulerHintAdditionalPropertyApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *SchedulerHintAdditionalPropertyApplyConfiguration) WithName(value string) *SchedulerHintAdditionalPropertyApplyConfiguration { + b.Name = &value + return b +} + +// WithValue sets the Value field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Value field is set to the value of the last call. +func (b *SchedulerHintAdditionalPropertyApplyConfiguration) WithValue(value *SchedulerHintAdditionalValueApplyConfiguration) *SchedulerHintAdditionalPropertyApplyConfiguration { + b.Value = value + return b +} diff --git a/pkg/generated/applyconfiguration/api/v1beta1/schedulerhintadditionalvalue.go b/pkg/generated/applyconfiguration/api/v1beta1/schedulerhintadditionalvalue.go new file mode 100644 index 0000000000..abde2eca0c --- /dev/null +++ b/pkg/generated/applyconfiguration/api/v1beta1/schedulerhintadditionalvalue.go @@ -0,0 +1,70 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1beta1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" +) + +// SchedulerHintAdditionalValueApplyConfiguration represents an declarative configuration of the SchedulerHintAdditionalValue type for use +// with apply. +type SchedulerHintAdditionalValueApplyConfiguration struct { + Type *v1beta1.SchedulerHintValueType `json:"type,omitempty"` + Bool *bool `json:"bool,omitempty"` + Number *int `json:"number,omitempty"` + String *string `json:"string,omitempty"` +} + +// SchedulerHintAdditionalValueApplyConfiguration constructs an declarative configuration of the SchedulerHintAdditionalValue type for use with +// apply. +func SchedulerHintAdditionalValue() *SchedulerHintAdditionalValueApplyConfiguration { + return &SchedulerHintAdditionalValueApplyConfiguration{} +} + +// WithType sets the Type field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Type field is set to the value of the last call. +func (b *SchedulerHintAdditionalValueApplyConfiguration) WithType(value v1beta1.SchedulerHintValueType) *SchedulerHintAdditionalValueApplyConfiguration { + b.Type = &value + return b +} + +// WithBool sets the Bool field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Bool field is set to the value of the last call. +func (b *SchedulerHintAdditionalValueApplyConfiguration) WithBool(value bool) *SchedulerHintAdditionalValueApplyConfiguration { + b.Bool = &value + return b +} + +// WithNumber sets the Number field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Number field is set to the value of the last call. +func (b *SchedulerHintAdditionalValueApplyConfiguration) WithNumber(value int) *SchedulerHintAdditionalValueApplyConfiguration { + b.Number = &value + return b +} + +// WithString sets the String field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the String field is set to the value of the last call. +func (b *SchedulerHintAdditionalValueApplyConfiguration) WithString(value string) *SchedulerHintAdditionalValueApplyConfiguration { + b.String = &value + return b +} diff --git a/pkg/generated/applyconfiguration/internal/internal.go b/pkg/generated/applyconfiguration/internal/internal.go index 2350bc7f1a..f9fd93ba0d 100644 --- a/pkg/generated/applyconfiguration/internal/internal.go +++ b/pkg/generated/applyconfiguration/internal/internal.go @@ -262,6 +262,14 @@ var schemaYAML = typed.YAMLObject(`types: - name: rootVolume type: namedType: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.RootVolume + - name: schedulerHintAdditionalProperties + type: + list: + elementType: + namedType: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.SchedulerHintAdditionalProperty + elementRelationship: associative + keys: + - name - name: securityGroups type: list: @@ -2710,6 +2718,14 @@ var schemaYAML = typed.YAMLObject(`types: - name: rootVolume type: namedType: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.RootVolume + - name: schedulerHintAdditionalProperties + type: + list: + elementType: + namedType: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.SchedulerHintAdditionalProperty + elementRelationship: associative + keys: + - name - name: securityGroups type: list: @@ -3065,6 +3081,33 @@ var schemaYAML = typed.YAMLObject(`types: - name: id type: scalar: string +- name: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.SchedulerHintAdditionalProperty + map: + fields: + - name: name + type: + scalar: string + default: "" + - name: value + type: + namedType: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.SchedulerHintAdditionalValue + default: {} +- name: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.SchedulerHintAdditionalValue + map: + fields: + - name: bool + type: + scalar: boolean + - name: number + type: + scalar: numeric + - name: string + type: + scalar: string + - name: type + type: + scalar: string + default: "" - name: io.k8s.sigs.cluster-api-provider-openstack.api.v1beta1.SecurityGroupFilter map: fields: diff --git a/pkg/generated/applyconfiguration/utils.go b/pkg/generated/applyconfiguration/utils.go index 4fa234c0fc..ab07b20a40 100644 --- a/pkg/generated/applyconfiguration/utils.go +++ b/pkg/generated/applyconfiguration/utils.go @@ -283,6 +283,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apiv1beta1.RouterFilterApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("RouterParam"): return &apiv1beta1.RouterParamApplyConfiguration{} + case v1beta1.SchemeGroupVersion.WithKind("SchedulerHintAdditionalProperty"): + return &apiv1beta1.SchedulerHintAdditionalPropertyApplyConfiguration{} + case v1beta1.SchemeGroupVersion.WithKind("SchedulerHintAdditionalValue"): + return &apiv1beta1.SchedulerHintAdditionalValueApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("SecurityGroupFilter"): return &apiv1beta1.SecurityGroupFilterApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("SecurityGroupParam"): diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go index 4faad1d789..83eaf23d48 100644 --- a/test/e2e/suites/apivalidations/openstackmachine_test.go +++ b/test/e2e/suites/apivalidations/openstackmachine_test.go @@ -354,6 +354,158 @@ var _ = Describe("OpenStackMachine API validations", func() { }) }) + Context("schedulerHints", func() { + It("should allow empty schedulerHints", func() { + machine := defaultMachine() + machine.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{} + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "Creating a machine with an empty SchedulerHintAdditionalProperties should succeed.") + }) + + It("should not allow item with empty name", func() { + machine := defaultMachine() + machine.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeBool, + Bool: ptr.To(false), + }, + }, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with SchedulerHintAdditionalProperties including an item with empty name should fail.") + }) + + It("should not allow item with empty value", func() { + machine := defaultMachine() + machine.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + }, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "Creating a machine with SchedulerHintAdditionalProperties including an item with empty value should fail.") + }) + + It("should allow correct SchedulerHintAdditionalProperties", func() { + machineB := defaultMachine() + machineB.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeBool, + Bool: ptr.To(true), + }, + }, + } + By("Creating SchedulerHint with bool type") + Expect(k8sClient.Create(ctx, machineB)).To(Succeed(), "Creating a machine with bool type scheduler hint property should succeed.") + machineN := defaultMachine() + machineN.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeNumber, + Number: ptr.To(1), + }, + }, + } + By("Creating SchedulerHint with number type") + Expect(k8sClient.Create(ctx, machineN)).To(Succeed(), "Creating a machine with number type scheduler hint property should succeed.") + machineS := defaultMachine() + machineS.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeString, + String: ptr.To("test-hint"), + }, + }, + } + By("Creating SchedulerHint with string type") + Expect(k8sClient.Create(ctx, machineS)).To(Succeed(), "Creating a machine with string type scheduler hint property should succeed.") + }) + + It("should not allow incorrect SchedulerHintAdditionalProperties with bool type", func() { + machineBN := defaultMachine() + machineBN.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeBool, + Number: ptr.To(1), + }, + }, + } + By("Creating SchedulerHint with bool type and number value") + Expect(k8sClient.Create(ctx, machineBN)).NotTo(Succeed(), "Creating a machine with bool type but number value scheduler hint property should fail.") + machineBS := defaultMachine() + machineBS.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeBool, + String: ptr.To("test-hint"), + }, + }, + } + By("Creating SchedulerHint with bool type and string value") + Expect(k8sClient.Create(ctx, machineBS)).NotTo(Succeed(), "Creating a machine with bool type but string value scheduler hint property should fail.") + }) + + It("should not allow incorrect SchedulerHintAdditionalProperties with number type", func() { + machineNB := defaultMachine() + machineNB.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeNumber, + Bool: ptr.To(true), + }, + }, + } + By("Creating SchedulerHint with number type and bool value") + Expect(k8sClient.Create(ctx, machineNB)).NotTo(Succeed(), "Creating a machine with number type but bool value scheduler hint property should fail.") + machineNS := defaultMachine() + machineNS.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeNumber, + String: ptr.To("test-hint"), + }, + }, + } + By("Creating SchedulerHint with number type and string value") + Expect(k8sClient.Create(ctx, machineNS)).NotTo(Succeed(), "Creating a machine with number type but string value scheduler hint property should fail.") + }) + + It("should not allow incorrect SchedulerHintAdditionalProperties with string type", func() { + machineSB := defaultMachine() + machineSB.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeString, + Bool: ptr.To(true), + }, + }, + } + By("Creating SchedulerHint with string type and bool value") + Expect(k8sClient.Create(ctx, machineSB)).NotTo(Succeed(), "Creating a machine with string type but bool value scheduler hint property should fail.") + machineSN := defaultMachine() + machineSN.Spec.SchedulerHintAdditionalProperties = []infrav1.SchedulerHintAdditionalProperty{ + { + Name: "test-hints", + Value: infrav1.SchedulerHintAdditionalValue{ + Type: infrav1.SchedulerHintTypeString, + Number: ptr.To(1), + }, + }, + } + By("Creating SchedulerHint with string type and number value") + Expect(k8sClient.Create(ctx, machineSN)).NotTo(Succeed(), "Creating a machine with string type but number value scheduler hint property should fail.") + }) + }) + Context("v1alpha7", func() { It("should downgrade cleanly from infrav1", func() { infrav1Machine := &infrav1.OpenStackMachine{}