From a1f0ffd357321a96713f641db89925a2a5e7f240 Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Mon, 25 Mar 2024 14:08:10 +0000 Subject: [PATCH] Split ImageFilter into ImageParam This makes validation of the filter much simpler, because either ID or Filter must be specified. --- api/v1alpha5/conversion.go | 16 ++--- api/v1alpha5/zz_generated.conversion.go | 4 +- api/v1alpha6/openstackmachine_conversion.go | 16 ++--- api/v1alpha6/zz_generated.conversion.go | 4 +- api/v1alpha7/openstackmachine_conversion.go | 16 ++--- api/v1alpha7/zz_generated.conversion.go | 4 +- api/v1beta1/openstackmachine_types.go | 2 +- api/v1beta1/types.go | 21 ++++-- api/v1beta1/zz_generated.deepcopy.go | 30 +++++++-- ...re.cluster.x-k8s.io_openstackclusters.yaml | 46 +++++++------ ...er.x-k8s.io_openstackclustertemplates.yaml | 49 +++++++------- ...re.cluster.x-k8s.io_openstackmachines.yaml | 43 +++++++----- ...er.x-k8s.io_openstackmachinetemplates.yaml | 46 +++++++------ .../openstackcluster_controller_test.go | 6 +- .../openstackmachine_controller_test.go | 2 +- docs/book/src/api/v1beta1/api.md | 65 ++++++++++++++----- .../v1beta1/default/cluster-template.yaml | 6 +- pkg/cloud/services/compute/instance.go | 10 ++- pkg/cloud/services/compute/instance_test.go | 38 ++++++++--- .../compute/referenced_resources_test.go | 16 +++-- pkg/webhooks/openstackcluster_webhook_test.go | 24 +++++-- .../openstackmachinetemplate_webhook_test.go | 48 +++++++++++--- .../k8s-upgrade/upgrade-from-template.yaml | 6 +- .../k8s-upgrade/upgrade-to-template.yaml | 6 +- .../e2e/suites/apivalidations/filters_test.go | 44 +++++++++---- .../apivalidations/openstackcluster_test.go | 18 ++++- .../apivalidations/openstackmachine_test.go | 6 +- test/e2e/suites/e2e/e2e_test.go | 12 ++-- 28 files changed, 407 insertions(+), 197 deletions(-) diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go index 5c2516b891..9f8f262d34 100644 --- a/api/v1alpha5/conversion.go +++ b/api/v1alpha5/conversion.go @@ -360,13 +360,13 @@ func Convert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O out.ServerGroup = &infrav1.ServerGroupFilter{} } - imageFilter := infrav1.ImageFilter{} + imageParam := infrav1.ImageParam{} if in.ImageUUID != "" { - imageFilter.ID = &in.ImageUUID + imageParam.ID = &in.ImageUUID } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both. - imageFilter.Name = &in.Image + imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image} } - out.Image = imageFilter + out.Image = imageParam if in.IdentityRef != nil { out.IdentityRef = &infrav1.OpenStackIdentityReference{Name: in.IdentityRef.Name} @@ -645,12 +645,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *i out.ServerGroupID = in.ServerGroup.ID } - if in.Image.Name != nil && *in.Image.Name != "" { - out.Image = *in.Image.Name - } - - if in.Image.ID != nil && *in.Image.ID != "" { + if in.Image.ID != nil { out.ImageUUID = *in.Image.ID + } else if in.Image.Filter != nil && in.Image.Filter.Name != nil { + out.Image = *in.Image.Filter.Name } if in.IdentityRef != nil { diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index f5d208397e..6dad8aaef1 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -1099,7 +1099,7 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) // WARNING: in.CloudName requires manual conversion: does not exist in peer-type out.Flavor = in.Flavor - // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter) + // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam) // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type out.SSHKeyName = in.SSHKeyName // WARNING: in.Networks requires manual conversion: does not exist in peer-type @@ -1149,7 +1149,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) out.Flavor = in.Flavor - // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string) + // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam vs string) out.SSHKeyName = in.SSHKeyName if in.Ports != nil { in, out := &in.Ports, &out.Ports diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go index d0f01cac1b..69ae6a1acb 100644 --- a/api/v1alpha6/openstackmachine_conversion.go +++ b/api/v1alpha6/openstackmachine_conversion.go @@ -266,13 +266,13 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O out.ServerGroup = nil } - imageFilter := infrav1.ImageFilter{} + imageParam := infrav1.ImageParam{} if in.ImageUUID != "" { - imageFilter.ID = &in.ImageUUID + imageParam.ID = &in.ImageUUID } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both. - imageFilter.Name = &in.Image + imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image} } - out.Image = imageFilter + out.Image = imageParam if len(in.ServerMetadata) > 0 { serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata)) @@ -314,12 +314,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *i out.ServerGroupID = in.ServerGroup.ID } - if in.Image.Name != nil && *in.Image.Name != "" { - out.Image = *in.Image.Name - } - - if in.Image.ID != nil && *in.Image.ID != "" { + if in.Image.ID != nil { out.ImageUUID = *in.Image.ID + } else if in.Image.Filter != nil && in.Image.Filter.Name != nil { + out.Image = *in.Image.Filter.Name } if len(in.ServerMetadata) > 0 { diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index b35e716ad4..85cbc09d8c 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -1134,7 +1134,7 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) // WARNING: in.CloudName requires manual conversion: does not exist in peer-type out.Flavor = in.Flavor - // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter) + // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam) // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type out.SSHKeyName = in.SSHKeyName // WARNING: in.Networks requires manual conversion: does not exist in peer-type @@ -1184,7 +1184,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) out.Flavor = in.Flavor - // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string) + // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam vs string) out.SSHKeyName = in.SSHKeyName if in.Ports != nil { in, out := &in.Ports, &out.Ports diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go index 08ef6f94ce..561b409ecb 100644 --- a/api/v1alpha7/openstackmachine_conversion.go +++ b/api/v1alpha7/openstackmachine_conversion.go @@ -160,13 +160,13 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(in *O out.ServerGroup = nil } - imageFilter := infrav1.ImageFilter{} + imageParam := infrav1.ImageParam{} if in.ImageUUID != "" { - imageFilter.ID = &in.ImageUUID + imageParam.ID = &in.ImageUUID } else if in.Image != "" { // Only add name when ID is not set, in v1beta1 it's not possible to set both. - imageFilter.Name = &in.Image + imageParam.Filter = &infrav1.ImageFilter{Name: &in.Image} } - out.Image = imageFilter + out.Image = imageParam if len(in.ServerMetadata) > 0 { serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata)) @@ -205,12 +205,10 @@ func Convert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *i out.ServerGroupID = in.ServerGroup.ID } - if in.Image.Name != nil && *in.Image.Name != "" { - out.Image = *in.Image.Name - } - - if in.Image.ID != nil && *in.Image.ID != "" { + if in.Image.ID != nil { out.ImageUUID = *in.Image.ID + } else if in.Image.Filter != nil && in.Image.Filter.Name != nil { + out.Image = *in.Image.Filter.Name } if len(in.ServerMetadata) > 0 { diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go index 5646dbe6f8..5dc22f157a 100644 --- a/api/v1alpha7/zz_generated.conversion.go +++ b/api/v1alpha7/zz_generated.conversion.go @@ -1335,7 +1335,7 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) // WARNING: in.CloudName requires manual conversion: does not exist in peer-type out.Flavor = in.Flavor - // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter) + // WARNING: in.Image requires manual conversion: inconvertible types (string vs sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam) // WARNING: in.ImageUUID requires manual conversion: does not exist in peer-type out.SSHKeyName = in.SSHKeyName if in.Ports != nil { @@ -1384,7 +1384,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i out.ProviderID = (*string)(unsafe.Pointer(in.ProviderID)) out.InstanceID = (*string)(unsafe.Pointer(in.InstanceID)) out.Flavor = in.Flavor - // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageFilter vs string) + // WARNING: in.Image requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.ImageParam vs string) out.SSHKeyName = in.SSHKeyName if in.Ports != nil { in, out := &in.Ports, &out.Ports diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go index 95e5edfe88..dc53e53de8 100644 --- a/api/v1beta1/openstackmachine_types.go +++ b/api/v1beta1/openstackmachine_types.go @@ -45,7 +45,7 @@ type OpenStackMachineSpec struct { // The image to use for your server instance. // If the rootVolume is specified, this will be used when creating the root volume. // +required - Image ImageFilter `json:"image"` + Image ImageParam `json:"image"` // The ssh key to inject in the instance SSHKeyName string `json:"sshKeyName,omitempty"` diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index a8a9288393..c6d7e5e7e9 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -28,16 +28,29 @@ type OpenStackMachineTemplateResource struct { Spec OpenStackMachineSpec `json:"spec"` } -// ImageFilter describes the data needed to identify which image to use. If ID is provided it is required that all other fields are unset. -// +kubebuilder:validation:XValidation:rule="(has(self.id) && !has(self.name) && !has(self.tags)) || !has(self.id)",message="when ID is set you cannot set other options" -type ImageFilter struct { - // The ID of the desired image. If ID is provided, the other filters cannot be provided. Must be in UUID format. +// ImageParam describes a glance image. It can be specified by ID or filter. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type ImageParam struct { + // ID is the uuid of the image. ID will not be validated before use. // +kubebuilder:validation:Format:=uuid // +optional ID optional.String `json:"id,omitempty"` + + // Filter describes a query for an image. If specified, the combination + // of name and tags must return a single matching image or an error will + // be raised. + // +optional + Filter *ImageFilter `json:"filter,omitempty"` +} + +// ImageFilter describes a query for an image. +// +kubebuilder:validation:MinProperties:=1 +type ImageFilter struct { // The name of the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised. // +optional Name optional.String `json:"name,omitempty"` + // The tags associated with the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised. // +listType=set // +optional diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 892e950daf..bb59986203 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -299,11 +299,6 @@ func (in *FixedIP) DeepCopy() *FixedIP { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageFilter) DeepCopyInto(out *ImageFilter) { *out = *in - if in.ID != nil { - in, out := &in.ID, &out.ID - *out = new(string) - **out = **in - } if in.Name != nil { in, out := &in.Name, &out.Name *out = new(string) @@ -326,6 +321,31 @@ func (in *ImageFilter) DeepCopy() *ImageFilter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageParam) DeepCopyInto(out *ImageParam) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(ImageFilter) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageParam. +func (in *ImageParam) DeepCopy() *ImageParam { + if in == nil { + return nil + } + out := new(ImageParam) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) { *out = *in diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml index abdbf1c5da..948494aacf 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -5050,31 +5050,37 @@ spec: description: |- The image to use for your server instance. If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. If specified, + the combination of name and tags must return a single + matching image or an error will be raised. + type: string + tags: + description: The tags associated with the desired + image. If specified, the combination of name and + tags must return a single matching image or an error + will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object id: - description: The ID of the desired image. If ID is provided, - the other filters cannot be provided. Must be in UUID - format. + description: ID is the uuid of the image. ID will not + be validated before use. format: uuid type: string - name: - description: The name of the desired image. If specified, - the combination of name and tags must return a single - matching image or an error will be raised. - type: string - tags: - description: The tags associated with the desired image. - If specified, the combination of name and tags must - return a single matching image or an error will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set type: object - x-kubernetes-validations: - - message: when ID is set you cannot set other options - rule: (has(self.id) && !has(self.name) && !has(self.tags)) - || !has(self.id) instanceID: description: InstanceID is the OpenStack instance ID for this machine. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml index 66b4e12174..377ca329c4 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml @@ -2477,33 +2477,38 @@ spec: description: |- The image to use for your server instance. If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. + If specified, the combination of name and + tags must return a single matching image + or an error will be raised. + type: string + tags: + description: The tags associated with the + desired image. If specified, the combination + of name and tags must return a single matching + image or an error will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object id: - description: The ID of the desired image. If ID - is provided, the other filters cannot be provided. - Must be in UUID format. + description: ID is the uuid of the image. ID will + not be validated before use. format: uuid type: string - name: - description: The name of the desired image. If - specified, the combination of name and tags - must return a single matching image or an error - will be raised. - type: string - tags: - description: The tags associated with the desired - image. If specified, the combination of name - and tags must return a single matching image - or an error will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set type: object - x-kubernetes-validations: - - message: when ID is set you cannot set other options - rule: (has(self.id) && !has(self.name) && !has(self.tags)) - || !has(self.id) instanceID: description: InstanceID is the OpenStack instance ID for this machine. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml index 3d866edc37..471f55ef00 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml @@ -1831,29 +1831,36 @@ spec: description: |- The image to use for your server instance. If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. If specified, + the combination of name and tags must return a single matching + image or an error will be raised. + type: string + tags: + description: The tags associated with the desired image. If + specified, the combination of name and tags must return + a single matching image or an error will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object id: - description: The ID of the desired image. If ID is provided, the - other filters cannot be provided. Must be in UUID format. + description: ID is the uuid of the image. ID will not be validated + before use. format: uuid type: string - name: - description: The name of the desired image. If specified, the - combination of name and tags must return a single matching image - or an error will be raised. - type: string - tags: - description: The tags associated with the desired image. If specified, - the combination of name and tags must return a single matching - image or an error will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set type: object - x-kubernetes-validations: - - message: when ID is set you cannot set other options - rule: (has(self.id) && !has(self.name) && !has(self.tags)) || !has(self.id) instanceID: description: InstanceID is the OpenStack instance ID for this machine. type: string diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml index 12d3b1ea40..8381d7daaa 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml @@ -1504,31 +1504,37 @@ spec: description: |- The image to use for your server instance. If the rootVolume is specified, this will be used when creating the root volume. + maxProperties: 1 + minProperties: 1 properties: + filter: + description: |- + Filter describes a query for an image. If specified, the combination + of name and tags must return a single matching image or an error will + be raised. + minProperties: 1 + properties: + name: + description: The name of the desired image. If specified, + the combination of name and tags must return a single + matching image or an error will be raised. + type: string + tags: + description: The tags associated with the desired + image. If specified, the combination of name and + tags must return a single matching image or an error + will be raised. + items: + type: string + type: array + x-kubernetes-list-type: set + type: object id: - description: The ID of the desired image. If ID is provided, - the other filters cannot be provided. Must be in UUID - format. + description: ID is the uuid of the image. ID will not + be validated before use. format: uuid type: string - name: - description: The name of the desired image. If specified, - the combination of name and tags must return a single - matching image or an error will be raised. - type: string - tags: - description: The tags associated with the desired image. - If specified, the combination of name and tags must - return a single matching image or an error will be raised. - items: - type: string - type: array - x-kubernetes-list-type: set type: object - x-kubernetes-validations: - - message: when ID is set you cannot set other options - rule: (has(self.id) && !has(self.name) && !has(self.tags)) - || !has(self.id) instanceID: description: InstanceID is the OpenStack instance ID for this machine. diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go index b738cafe47..57f69c4308 100644 --- a/controllers/openstackcluster_controller_test.go +++ b/controllers/openstackcluster_controller_test.go @@ -63,8 +63,10 @@ var _ = Describe("OpenStackCluster controller", func() { testClusterName := "test-cluster" testNum := 0 bastionSpec := infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{ - Name: pointer.String("fake-name"), + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("fake-name"), + }, }, } diff --git a/controllers/openstackmachine_controller_test.go b/controllers/openstackmachine_controller_test.go index bc2b4897f3..a6ac3e1b8d 100644 --- a/controllers/openstackmachine_controller_test.go +++ b/controllers/openstackmachine_controller_test.go @@ -84,7 +84,7 @@ func getDefaultOpenStackMachine() *infrav1.OpenStackMachine { // FloatingIP is only used by the cluster controller for the Bastion // TODO: Test Networks, Ports, Subnet, and Trunk separately Flavor: flavorName, - Image: infrav1.ImageFilter{ID: pointer.String(imageUUID)}, + Image: infrav1.ImageParam{ID: pointer.String(imageUUID)}, SSHKeyName: sshKeyName, Tags: []string{"test-tag"}, ServerMetadata: []infrav1.ServerMetadata{ diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md index fc84797f7a..a7904b0840 100644 --- a/docs/book/src/api/v1beta1/api.md +++ b/docs/book/src/api/v1beta1/api.md @@ -587,8 +587,8 @@ string image
- -ImageFilter + +ImageParam @@ -1575,10 +1575,10 @@ address in any subnet of the port’s network.

(Appears on: -OpenStackMachineSpec) +ImageParam)

-

ImageFilter describes the data needed to identify which image to use. If ID is provided it is required that all other fields are unset.

+

ImageFilter describes a query for an image.

@@ -1590,38 +1590,73 @@ address in any subnet of the port’s network.

+ + + +
-id
+name
string
(Optional) -

The ID of the desired image. If ID is provided, the other filters cannot be provided. Must be in UUID format.

+

The name of the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised.

-name
+tags
+ +[]string + +
+(Optional) +

The tags associated with the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised.

+
+

ImageParam +

+

+(Appears on: +OpenStackMachineSpec) +

+

+

ImageParam describes a glance image. It can be specified by ID or filter.

+

+ + + + + + + + + + @@ -3060,8 +3095,8 @@ string @@ -3430,8 +3465,8 @@ string diff --git a/kustomize/v1beta1/default/cluster-template.yaml b/kustomize/v1beta1/default/cluster-template.yaml index 52ab6c2f88..ae7db083cf 100644 --- a/kustomize/v1beta1/default/cluster-template.yaml +++ b/kustomize/v1beta1/default/cluster-template.yaml @@ -97,7 +97,8 @@ spec: spec: flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME} + filter: + name: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} --- apiVersion: cluster.x-k8s.io/v1beta1 @@ -133,7 +134,8 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME} + filter: + name: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} --- apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 diff --git a/pkg/cloud/services/compute/instance.go b/pkg/cloud/services/compute/instance.go index eebfd9278d..ac0b377bed 100644 --- a/pkg/cloud/services/compute/instance.go +++ b/pkg/cloud/services/compute/instance.go @@ -18,6 +18,7 @@ package compute import ( "context" + "errors" "fmt" "os" "strconv" @@ -332,12 +333,17 @@ func applyServerGroupID(opts servers.CreateOptsBuilder, serverGroupID string) se } // Helper function for getting image ID from name, ID, or tags. -func (s *Service) GetImageID(image infrav1.ImageFilter) (string, error) { +func (s *Service) GetImageID(image infrav1.ImageParam) (string, error) { if image.ID != nil { return *image.ID, nil } - listOpts := filterconvert.ImageFilterToListOpts(&image) + if image.Filter == nil { + // Should have been caught by validation + return "", errors.New("image id and filter are both nil") + } + + listOpts := filterconvert.ImageFilterToListOpts(image.Filter) allImages, err := s.getImageClient().ListImages(listOpts) if err != nil { return "", err diff --git a/pkg/cloud/services/compute/instance_test.go b/pkg/cloud/services/compute/instance_test.go index af9214e8a7..b571b25021 100644 --- a/pkg/cloud/services/compute/instance_test.go +++ b/pkg/cloud/services/compute/instance_test.go @@ -47,22 +47,26 @@ func TestService_getImageID(t *testing.T) { tests := []struct { testName string - image infrav1.ImageFilter + image infrav1.ImageParam expect func(m *mock.MockImageClientMockRecorder) want string wantErr bool }{ { testName: "Return image ID when ID given", - image: infrav1.ImageFilter{ID: &imageID}, + image: infrav1.ImageParam{ID: &imageID}, want: imageID, expect: func(m *mock.MockImageClientMockRecorder) {}, wantErr: false, }, { testName: "Return image ID when name given", - image: infrav1.ImageFilter{Name: &imageName}, - want: imageID, + image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: &imageName, + }, + }, + want: imageID, expect: func(m *mock.MockImageClientMockRecorder) { m.ListImages(images.ListOpts{Name: imageName}).Return( []images.Image{{ID: imageID, Name: imageName}}, @@ -72,8 +76,12 @@ func TestService_getImageID(t *testing.T) { }, { testName: "Return image ID when tags given", - image: infrav1.ImageFilter{Tags: imageTags}, - want: imageID, + image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Tags: imageTags, + }, + }, + want: imageID, expect: func(m *mock.MockImageClientMockRecorder) { m.ListImages(images.ListOpts{Tags: imageTags}).Return( []images.Image{{ID: imageID, Name: imageName, Tags: imageTags}}, @@ -83,7 +91,11 @@ func TestService_getImageID(t *testing.T) { }, { testName: "Return no results", - image: infrav1.ImageFilter{Name: &imageName}, + image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: &imageName, + }, + }, expect: func(m *mock.MockImageClientMockRecorder) { m.ListImages(images.ListOpts{Name: imageName}).Return( []images.Image{}, @@ -94,7 +106,11 @@ func TestService_getImageID(t *testing.T) { }, { testName: "Return multiple results", - image: infrav1.ImageFilter{Name: &imageName}, + image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: &imageName, + }, + }, expect: func(m *mock.MockImageClientMockRecorder) { m.ListImages(images.ListOpts{Name: "test-image"}).Return( []images.Image{ @@ -107,7 +123,11 @@ func TestService_getImageID(t *testing.T) { }, { testName: "OpenStack returns error", - image: infrav1.ImageFilter{Name: &imageName}, + image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: &imageName, + }, + }, expect: func(m *mock.MockImageClientMockRecorder) { m.ListImages(images.ListOpts{Name: "test-image"}).Return( nil, diff --git a/pkg/cloud/services/compute/referenced_resources_test.go b/pkg/cloud/services/compute/referenced_resources_test.go index 1f13ce5427..64adaf3641 100644 --- a/pkg/cloud/services/compute/referenced_resources_test.go +++ b/pkg/cloud/services/compute/referenced_resources_test.go @@ -68,7 +68,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) { testName: "Resources ID passed", spec: infrav1.OpenStackMachineSpec{ ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupID1}, - Image: infrav1.ImageFilter{ID: pointer.String(imageID1)}, + Image: infrav1.ImageParam{ID: pointer.String(imageID1)}, }, want: &infrav1.ResolvedMachineSpec{ ImageID: imageID1, @@ -79,7 +79,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) { { testName: "Only image ID passed: want image id and default ports", spec: infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{ID: pointer.String(imageID1)}, + Image: infrav1.ImageParam{ID: pointer.String(imageID1)}, }, want: &infrav1.ResolvedMachineSpec{ ImageID: imageID1, @@ -89,7 +89,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) { { testName: "Server group empty", spec: infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{ID: pointer.String(imageID1)}, + Image: infrav1.ImageParam{ID: pointer.String(imageID1)}, ServerGroup: &infrav1.ServerGroupFilter{}, }, want: &infrav1.ResolvedMachineSpec{ @@ -100,7 +100,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) { { testName: "Server group by Name not found", spec: infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{ID: pointer.String(imageID1)}, + Image: infrav1.ImageParam{ID: pointer.String(imageID1)}, ServerGroup: &infrav1.ServerGroupFilter{Name: "test-server-group"}, }, expectComputeMock: func(m *mock.MockComputeClientMockRecorder) { @@ -114,7 +114,11 @@ func Test_ResolveReferencedMachineResources(t *testing.T) { { testName: "Image by Name not found", spec: infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{Name: pointer.String("test-image")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("test-image"), + }, + }, }, expectImageMock: func(m *mock.MockImageClientMockRecorder) { m.ListImages(images.ListOpts{Name: "test-image"}).Return([]images.Image{}, nil) @@ -125,7 +129,7 @@ func Test_ResolveReferencedMachineResources(t *testing.T) { { testName: "Ports set", spec: infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{ID: pointer.String(imageID1)}, + Image: infrav1.ImageParam{ID: pointer.String(imageID1)}, Ports: []infrav1.PortOpts{ { Network: &infrav1.NetworkFilter{ diff --git a/pkg/webhooks/openstackcluster_webhook_test.go b/pkg/webhooks/openstackcluster_webhook_test.go index 3d65376486..09c18dcc70 100644 --- a/pkg/webhooks/openstackcluster_webhook_test.go +++ b/pkg/webhooks/openstackcluster_webhook_test.go @@ -85,7 +85,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { }, Bastion: &infrav1.Bastion{ Spec: &infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{Name: pointer.String("foobar")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("foobar"), + }, + }, Flavor: "minimal", }, Enabled: true, @@ -105,7 +109,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { }, Bastion: &infrav1.Bastion{ Spec: &infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{Name: pointer.String("foobarbaz")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("foobarbaz"), + }, + }, Flavor: "medium", }, Enabled: true, @@ -454,7 +462,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { Enabled: true, Spec: &infrav1.OpenStackMachineSpec{ Flavor: "m1.small", - Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("ubuntu"), + }, + }, }, }, }, @@ -481,7 +493,11 @@ func TestOpenStackCluster_ValidateUpdate(t *testing.T) { Enabled: false, Spec: &infrav1.OpenStackMachineSpec{ Flavor: "m1.small", - Image: infrav1.ImageFilter{Name: pointer.String("ubuntu")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("ubuntu"), + }, + }, }, }, }, diff --git a/pkg/webhooks/openstackmachinetemplate_webhook_test.go b/pkg/webhooks/openstackmachinetemplate_webhook_test.go index 899cf509f1..6b148f3bfa 100644 --- a/pkg/webhooks/openstackmachinetemplate_webhook_test.go +++ b/pkg/webhooks/openstackmachinetemplate_webhook_test.go @@ -47,7 +47,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("bar")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + }, + }, }, }, }, @@ -57,7 +61,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("NewImage")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("NewImage"), + }, + }, }, }, }, @@ -72,7 +80,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("bar")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + }, + }, }, }, }, @@ -85,7 +97,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("bar")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + }, + }, }, }, }, @@ -102,7 +118,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("bar")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + }, + }, }, }, }, @@ -112,7 +132,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("NewImage")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("NewImage"), + }, + }, }, }, }, @@ -127,7 +151,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("bar")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + }, + }, }, }, }, @@ -142,7 +170,11 @@ func TestOpenStackMachineTemplate_ValidateUpdate(t *testing.T) { Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: "foo", - Image: infrav1.ImageFilter{Name: pointer.String("NewImage")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("NewImage"), + }, + }, }, }, }, diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml index 6e9098977b..d49208116d 100644 --- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml +++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-from-template.yaml @@ -8,7 +8,8 @@ spec: spec: flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM} + filter: + name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} tags: - control-plane @@ -22,7 +23,8 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM} + filter: + name: ${OPENSTACK_IMAGE_NAME_UPGRADE_FROM} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} tags: - machine diff --git a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml index 39272254fd..466cb7931b 100644 --- a/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml +++ b/test/e2e/data/kustomize/k8s-upgrade/upgrade-to-template.yaml @@ -15,7 +15,8 @@ spec: spec: flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME} + filter: + name: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} tags: - control-plane @@ -31,7 +32,8 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME} + filter: + name: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} tags: - machine diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go index b4e256cff8..ac576951c5 100644 --- a/test/e2e/suites/apivalidations/filters_test.go +++ b/test/e2e/suites/apivalidations/filters_test.go @@ -36,7 +36,11 @@ var _ = Describe("Filter API validations", func() { namespace = createNamespace() // Initialise a basic machine object in the correct namespace - machine = &infrav1.OpenStackMachine{} + machine = &infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}}, + }, + } machine.Namespace = namespace.Name machine.GenerateName = "machine-" @@ -177,27 +181,31 @@ var _ = Describe("Filter API validations", func() { const imageUUID = "5a78f794-cdc3-48d2-8d9f-0fd472fdd743" - It("should not allow both ID and Name of ImageFilter to be set", func() { + It("should not allow both ID and Filter to be set", func() { By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ - ID: pointer.String(imageUUID), - Name: pointer.String("bar"), + machine.Spec.Image = infrav1.ImageParam{ + ID: pointer.String(imageUUID), + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + }, } Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") }) It("should not allow both ID and Tags of ImageFilter to be set", func() { By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ - ID: pointer.String(imageUUID), - Tags: []string{"bar", "baz"}, + machine.Spec.Image = infrav1.ImageParam{ + ID: pointer.String(imageUUID), + Filter: &infrav1.ImageFilter{ + Tags: []string{"bar", "baz"}, + }, } Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") }) It("should allow UUID ID of ImageFilter to be set", func() { By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ + machine.Spec.Image = infrav1.ImageParam{ ID: pointer.String(imageUUID), } Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") @@ -205,7 +213,7 @@ var _ = Describe("Filter API validations", func() { It("should not allow non-UUID ID of ImageFilter to be set", func() { By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ + machine.Spec.Image = infrav1.ImageParam{ ID: pointer.String("foo"), } Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") @@ -213,10 +221,20 @@ var _ = Describe("Filter API validations", func() { It("should allow Name and Tags of ImageFilter to be set", func() { By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ - Name: pointer.String("bar"), - Tags: []string{"bar", "baz"}, + machine.Spec.Image = infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("bar"), + Tags: []string{"bar", "baz"}, + }, } Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") }) + + It("should not allow a non-nil, empty image filter", func() { + By("Creating a machine") + machine.Spec.Image = infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") + }) }) diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go index f84e1d13d7..947f9b7b84 100644 --- a/test/e2e/suites/apivalidations/openstackcluster_test.go +++ b/test/e2e/suites/apivalidations/openstackcluster_test.go @@ -92,7 +92,11 @@ var _ = Describe("OpenStackCluster API validations", func() { cluster.Spec.Bastion = &infrav1.Bastion{ Enabled: true, Spec: &infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{Name: pointer.String("fake-image")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("fake-image"), + }, + }, }, } Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed") @@ -120,7 +124,11 @@ var _ = Describe("OpenStackCluster API validations", func() { cluster.Spec.Bastion = &infrav1.Bastion{ Enabled: true, Spec: &infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{Name: pointer.String("fake-image")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("fake-image"), + }, + }, }, FloatingIP: pointer.String("10.0.0.0"), } @@ -131,7 +139,11 @@ var _ = Describe("OpenStackCluster API validations", func() { cluster.Spec.Bastion = &infrav1.Bastion{ Enabled: true, Spec: &infrav1.OpenStackMachineSpec{ - Image: infrav1.ImageFilter{Name: pointer.String("fake-image")}, + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String("fake-image"), + }, + }, }, FloatingIP: pointer.String("foobar"), } diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go index c984ab1e61..4e888a3a41 100644 --- a/test/e2e/suites/apivalidations/openstackmachine_test.go +++ b/test/e2e/suites/apivalidations/openstackmachine_test.go @@ -35,7 +35,11 @@ var _ = Describe("OpenStackMachine API validations", func() { namespace = createNamespace() // Initialise a basic machine object in the correct namespace - machine = &infrav1.OpenStackMachine{} + machine = &infrav1.OpenStackMachine{ + Spec: infrav1.OpenStackMachineSpec{ + Image: infrav1.ImageParam{Filter: &infrav1.ImageFilter{Name: pointer.String("test-image")}}, + }, + } machine.Namespace = namespace.Name machine.GenerateName = "machine-" }) diff --git a/test/e2e/suites/e2e/e2e_test.go b/test/e2e/suites/e2e/e2e_test.go index ff0cb9c7ba..c271143483 100644 --- a/test/e2e/suites/e2e/e2e_test.go +++ b/test/e2e/suites/e2e/e2e_test.go @@ -859,8 +859,10 @@ func makeOpenStackMachineTemplate(namespace, clusterName, name string) *infrav1. Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor), - Image: infrav1.ImageFilter{ - Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)), + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)), + }, }, SSHKeyName: shared.DefaultSSHKeyPairName, IdentityRef: &infrav1.OpenStackIdentityReference{ @@ -883,8 +885,10 @@ func makeOpenStackMachineTemplateWithPortOptions(namespace, clusterName, name st Template: infrav1.OpenStackMachineTemplateResource{ Spec: infrav1.OpenStackMachineSpec{ Flavor: e2eCtx.E2EConfig.GetVariable(shared.OpenStackNodeMachineFlavor), - Image: infrav1.ImageFilter{ - Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)), + Image: infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{ + Name: pointer.String(e2eCtx.E2EConfig.GetVariable(shared.OpenStackImageName)), + }, }, SSHKeyName: shared.DefaultSSHKeyPairName, IdentityRef: &infrav1.OpenStackIdentityReference{
FieldDescription
+id
string
(Optional) -

The name of the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised.

+

ID is the uuid of the image. ID will not be validated before use.

-tags
+filter
-[]string + +ImageFilter +
(Optional) -

The tags associated with the desired image. If specified, the combination of name and tags must return a single matching image or an error will be raised.

+

Filter describes a query for an image. If specified, the combination +of name and tags must return a single matching image or an error will +be raised.

image
- -ImageFilter + +ImageParam
image
- -ImageFilter + +ImageParam