diff --git a/Makefile b/Makefile index d23c75d8ba..8b905651da 100644 --- a/Makefile +++ b/Makefile @@ -248,7 +248,7 @@ modules: ## Runs go mod to ensure proper vendoring. cd $(TOOLS_DIR); go mod tidy .PHONY: generate -generate: generate-controller-gen generate-conversion-gen generate-go generate-manifests generate-api-docs ## Generate all generated code +generate: templates generate-controller-gen generate-conversion-gen generate-go generate-manifests generate-api-docs ## Generate all generated code .PHONY: generate-go generate-go: $(MOCKGEN) diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go index b5d0cf0ff3..b9439a54eb 100644 --- a/api/v1alpha5/conversion.go +++ b/api/v1alpha5/conversion.go @@ -325,13 +325,8 @@ func Convert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *infrav1.PortOpts, out *Po if len(in.SecurityGroups) > 0 { out.SecurityGroupFilters = make([]SecurityGroupParam, len(in.SecurityGroups)) for i := range in.SecurityGroups { - securityGroupParam := &out.SecurityGroupFilters[i] - if in.SecurityGroups[i].ID != "" { - securityGroupParam.UUID = in.SecurityGroups[i].ID - } else { - if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil { - return err - } + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { + return err } } } @@ -361,13 +356,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} @@ -395,46 +390,48 @@ func Convert_v1alpha5_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po } if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 { - out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) + out.SecurityGroups = make([]infrav1.SecurityGroupParam, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) for i := range in.SecurityGroupFilters { sgParam := &in.SecurityGroupFilters[i] switch { case sgParam.UUID != "": - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: sgParam.UUID}) + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &sgParam.UUID}) case sgParam.Name != "": - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name}) + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{Filter: &infrav1.SecurityGroupFilter{Name: sgParam.Name}}) case sgParam.Filter != (SecurityGroupFilter{}): - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{}) + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{}) outSG := &out.SecurityGroups[len(out.SecurityGroups)-1] - if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil { + outSG.Filter = &infrav1.SecurityGroupFilter{} + if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG.Filter, s); err != nil { return err } } } - for _, id := range in.SecurityGroups { - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id}) + for i := range in.SecurityGroups { + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]}) } } if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 { - out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) + out.SecurityGroups = make([]infrav1.SecurityGroupParam, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) for i := range in.SecurityGroupFilters { sgParam := &in.SecurityGroupFilters[i] switch { case sgParam.UUID != "": - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: sgParam.UUID}) + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &sgParam.UUID}) case sgParam.Name != "": - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name}) + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{Filter: &infrav1.SecurityGroupFilter{Name: sgParam.Name}}) case sgParam.Filter != (SecurityGroupFilter{}): - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{}) + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{}) outSG := &out.SecurityGroups[len(out.SecurityGroups)-1] - if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil { + outSG.Filter = &infrav1.SecurityGroupFilter{} + if err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG.Filter, s); err != nil { return err } } } - for _, id := range in.SecurityGroups { - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id}) + for i := range in.SecurityGroups { + out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]}) } } @@ -521,34 +518,40 @@ func Convert_v1beta1_NetworkStatus_To_v1alpha5_Network(in *infrav1.NetworkStatus return nil } -func Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s conversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1 - err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s) - if err != nil { - return err - } - +func Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *infrav1.SecurityGroupParam, s conversion.Scope) error { if in.UUID != "" { - out.ID = in.UUID + out.ID = &in.UUID + return nil } + + outFilter := &infrav1.SecurityGroupFilter{} if in.Name != "" { - out.Name = in.Name + outFilter.Name = in.Name + } else { + // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1 + err := Convert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, outFilter, s) + if err != nil { + return err + } + } + + if !outFilter.IsZero() { + out.Filter = outFilter } return nil } -func Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s conversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1 - err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in, &out.Filter, s) - if err != nil { - return err +func Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(in *infrav1.SecurityGroupParam, out *SecurityGroupParam, s conversion.Scope) error { + if in.ID != nil { + out.UUID = *in.ID + return nil } - if in.ID != "" { - out.UUID = in.ID - } - if in.Name != "" { - out.Name = in.Name + if in.Filter != nil { + err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in.Filter, &out.Filter, s) + if err != nil { + return err + } } return nil } @@ -683,12 +686,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 8d24ce309a..2c5a688927 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -302,8 +302,8 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupParam), scope) }); err != nil { return err } @@ -407,8 +407,8 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(a.(*v1beta1.SecurityGroupParam), b.(*SecurityGroupParam), scope) }); err != nil { return err } @@ -1142,7 +1142,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 @@ -1161,9 +1161,9 @@ func autoConvert_v1alpha5_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]v1beta1.SecurityGroupFilter, len(*in)) + *out = make([]v1beta1.SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1192,7 +1192,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 @@ -1209,7 +1209,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(i in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1453,7 +1453,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha5_PortOpts(in *v1beta1.PortOpts, out in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]string, len(*in)) for i := range *in { - if err := v1alpha6.Convert_v1beta1_SecurityGroupFilter_To_string(&(*in)[i], &(*out)[i], s); err != nil { + if err := v1alpha6.Convert_v1beta1_SecurityGroupParam_To_string(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1517,7 +1517,7 @@ func Convert_v1beta1_Router_To_v1alpha5_Router(in *v1beta1.Router, out *Router, } func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID + // WARNING: in.ID requires manual conversion: does not exist in peer-type out.Name = in.Name out.Description = in.Description // WARNING: in.TenantID requires manual conversion: does not exist in peer-type @@ -1534,7 +1534,6 @@ func autoConvert_v1alpha5_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in } func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1542,6 +1541,19 @@ func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha5_SecurityGroupFilter(in return nil } +func autoConvert_v1alpha5_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *v1beta1.SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.Name requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.SecurityGroupFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter) + return nil +} + +func autoConvert_v1beta1_SecurityGroupParam_To_v1alpha5_SecurityGroupParam(in *v1beta1.SecurityGroupParam, out *SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha5.SecurityGroupFilter) + return nil +} + func autoConvert_v1alpha5_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID diff --git a/api/v1alpha6/conversion_test.go b/api/v1alpha6/conversion_test.go index 1456680359..4680ed9c15 100644 --- a/api/v1alpha6/conversion_test.go +++ b/api/v1alpha6/conversion_test.go @@ -455,19 +455,19 @@ func TestPortOptsConvertTo(t *testing.T) { // Variables used in the tests uuids := []string{"abc123", "123abc"} - securityGroupsUuids := []infrav1.SecurityGroupFilter{ - {ID: uuids[0]}, - {ID: uuids[1]}, + securityGroupsUuids := []infrav1.SecurityGroupParam{ + {ID: &uuids[0]}, + {ID: &uuids[1]}, } securityGroupFilter := []SecurityGroupParam{ {Name: "one"}, {UUID: "654cba"}, } - securityGroupFilterMerged := []infrav1.SecurityGroupFilter{ - {Name: "one"}, - {ID: "654cba"}, - {ID: uuids[0]}, - {ID: uuids[1]}, + securityGroupFilterMerged := []infrav1.SecurityGroupParam{ + {Filter: &infrav1.SecurityGroupFilter{Name: "one"}}, + {ID: pointer.String("654cba")}, + {ID: &uuids[0]}, + {ID: &uuids[1]}, } legacyPortProfile := map[string]string{ "capabilities": "[\"switchdev\"]", diff --git a/api/v1alpha6/openstackmachine_conversion.go b/api/v1alpha6/openstackmachine_conversion.go index d13eb5c124..2b5864d818 100644 --- a/api/v1alpha6/openstackmachine_conversion.go +++ b/api/v1alpha6/openstackmachine_conversion.go @@ -170,6 +170,12 @@ func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infr dst.ServerGroup = previous.ServerGroup dst.Image = previous.Image dst.FloatingIPPoolRef = previous.FloatingIPPoolRef + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for i := range dst.SecurityGroups { + restorev1beta1SecurityGroupParam(&previous.SecurityGroups[i], &dst.SecurityGroups[i]) + } + } } func convertNetworksToPorts(networks []NetworkParam, s apiconversion.Scope) ([]infrav1.PortOpts, error) { @@ -266,13 +272,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 +320,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/types_conversion.go b/api/v1alpha6/types_conversion.go index 1b2a642f34..7b99803d3f 100644 --- a/api/v1alpha6/types_conversion.go +++ b/api/v1alpha6/types_conversion.go @@ -41,55 +41,71 @@ func restorev1alpha6SecurityGroupFilter(previous *SecurityGroupFilter, dst *Secu dst.NotTagsAny = previous.NotTagsAny } -func Convert_v1beta1_SecurityGroupFilter_To_string(in *infrav1.SecurityGroupFilter, out *string, _ apiconversion.Scope) error { - if in.ID != "" { - *out = in.ID +func restorev1beta1SecurityGroupParam(previous *infrav1.SecurityGroupParam, dst *infrav1.SecurityGroupParam) { + if previous == nil || dst == nil { + return + } + + if dst.Filter != nil && previous.Filter != nil { + dst.Filter.Tags = previous.Filter.Tags + dst.Filter.TagsAny = previous.Filter.TagsAny + dst.Filter.NotTags = previous.Filter.NotTags + dst.Filter.NotTagsAny = previous.Filter.NotTagsAny } - return nil } -func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(in *SecurityGroupParam, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1 - err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, out, s) - if err != nil { - return err +func Convert_v1beta1_SecurityGroupParam_To_string(in *infrav1.SecurityGroupParam, out *string, _ apiconversion.Scope) error { + if in.ID != nil { + *out = *in.ID } + return nil +} +func Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *infrav1.SecurityGroupParam, s apiconversion.Scope) error { if in.UUID != "" { - out.ID = in.UUID + out.ID = &in.UUID + return nil } + + outFilter := &infrav1.SecurityGroupFilter{} + if in.Name != "" { - out.Name = in.Name + outFilter.Name = in.Name + } else { + err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.Filter, outFilter, s) + if err != nil { + return err + } + } + + if !outFilter.IsZero() { + out.Filter = outFilter } return nil } -func Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupFilter, out *SecurityGroupParam, s apiconversion.Scope) error { - // SecurityGroupParam is replaced by its contained SecurityGroupFilter in v1beta1 - err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in, &out.Filter, s) - if err != nil { - return err +func Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(in *infrav1.SecurityGroupParam, out *SecurityGroupParam, s apiconversion.Scope) error { + if in.ID != nil { + out.UUID = *in.ID + return nil } - if in.ID != "" { - out.UUID = in.ID - } - if in.Name != "" { - out.Name = in.Name + if in.Filter != nil { + err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in.Filter, &out.Filter, s) + if err != nil { + return err + } } + return nil } func Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error { - if err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil { + err := autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s) + if err != nil { return err } infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags) - - // TenantID has been removed in v1beta1. Write it to ProjectID if ProjectID is not already set. - if out.ProjectID == "" { - out.ProjectID = in.TenantID - } return nil } @@ -319,24 +335,14 @@ func Convert_v1alpha6_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po } if len(in.SecurityGroups) > 0 || len(in.SecurityGroupFilters) > 0 { - out.SecurityGroups = make([]infrav1.SecurityGroupFilter, 0, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) + out.SecurityGroups = make([]infrav1.SecurityGroupParam, len(in.SecurityGroups)+len(in.SecurityGroupFilters)) for i := range in.SecurityGroupFilters { - sgParam := &in.SecurityGroupFilters[i] - switch { - case sgParam.UUID != "": - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: sgParam.UUID}) - case sgParam.Name != "": - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{Name: sgParam.Name}) - case sgParam.Filter != (SecurityGroupFilter{}): - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{}) - outSG := &out.SecurityGroups[len(out.SecurityGroups)-1] - if err := Convert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&sgParam.Filter, outSG, s); err != nil { - return err - } + if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil { + return err } } - for _, id := range in.SecurityGroups { - out.SecurityGroups = append(out.SecurityGroups, infrav1.SecurityGroupFilter{ID: id}) + for i := range in.SecurityGroups { + out.SecurityGroups[i+len(in.SecurityGroupFilters)] = infrav1.SecurityGroupParam{ID: &in.SecurityGroups[i]} } } @@ -373,13 +379,8 @@ func Convert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *infrav1.PortOpts, out *Po if len(in.SecurityGroups) > 0 { out.SecurityGroupFilters = make([]SecurityGroupParam, len(in.SecurityGroups)) for i := range in.SecurityGroups { - securityGroupParam := &out.SecurityGroupFilters[i] - if in.SecurityGroups[i].ID != "" { - securityGroupParam.UUID = in.SecurityGroups[i].ID - } else { - if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(&in.SecurityGroups[i], &securityGroupParam.Filter, s); err != nil { - return err - } + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { + return err } } } diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index 9862d40792..8e33e36df6 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -321,8 +321,8 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*SecurityGroupParam)(nil), (*v1beta1.SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(a.(*SecurityGroupParam), b.(*v1beta1.SecurityGroupParam), scope) }); err != nil { return err } @@ -411,18 +411,18 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*string)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_SecurityGroupFilter_To_string(a.(*v1beta1.SecurityGroupFilter), b.(*string), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupFilter), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*string)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_string(a.(*v1beta1.SecurityGroupParam), b.(*string), scope) }); err != nil { return err } - if err := s.AddConversionFunc((*v1beta1.SecurityGroupFilter)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupFilter), b.(*SecurityGroupParam), scope) + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(a.(*v1beta1.SecurityGroupParam), b.(*SecurityGroupParam), scope) }); err != nil { return err } @@ -1177,7 +1177,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 @@ -1196,9 +1196,9 @@ func autoConvert_v1alpha6_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]v1beta1.SecurityGroupFilter, len(*in)) + *out = make([]v1beta1.SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1227,7 +1227,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 @@ -1244,7 +1244,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(i in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1489,7 +1489,7 @@ func autoConvert_v1beta1_PortOpts_To_v1alpha6_PortOpts(in *v1beta1.PortOpts, out in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]string, len(*in)) for i := range *in { - if err := Convert_v1beta1_SecurityGroupFilter_To_string(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_string(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1553,7 +1553,7 @@ func Convert_v1beta1_Router_To_v1alpha6_Router(in *v1beta1.Router, out *Router, } func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID + // WARNING: in.ID requires manual conversion: does not exist in peer-type out.Name = in.Name out.Description = in.Description // WARNING: in.TenantID requires manual conversion: does not exist in peer-type @@ -1570,7 +1570,6 @@ func autoConvert_v1alpha6_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in } func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1578,6 +1577,19 @@ func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha6_SecurityGroupFilter(in return nil } +func autoConvert_v1alpha6_SecurityGroupParam_To_v1beta1_SecurityGroupParam(in *SecurityGroupParam, out *v1beta1.SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.UUID requires manual conversion: does not exist in peer-type + // WARNING: in.Name requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.SecurityGroupFilter vs *sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter) + return nil +} + +func autoConvert_v1beta1_SecurityGroupParam_To_v1alpha6_SecurityGroupParam(in *v1beta1.SecurityGroupParam, out *SecurityGroupParam, s conversion.Scope) error { + // WARNING: in.ID requires manual conversion: does not exist in peer-type + // WARNING: in.Filter requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1.SecurityGroupFilter vs sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6.SecurityGroupFilter) + return nil +} + func autoConvert_v1alpha6_Subnet_To_v1beta1_Subnet(in *Subnet, out *v1beta1.Subnet, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID diff --git a/api/v1alpha7/openstackmachine_conversion.go b/api/v1alpha7/openstackmachine_conversion.go index fa0655288c..4731f7445c 100644 --- a/api/v1alpha7/openstackmachine_conversion.go +++ b/api/v1alpha7/openstackmachine_conversion.go @@ -137,9 +137,19 @@ func restorev1alpha7MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa } func restorev1beta1MachineSpec(previous *infrav1.OpenStackMachineSpec, dst *infrav1.OpenStackMachineSpec) { + if previous == nil || dst == nil { + return + } + dst.ServerGroup = previous.ServerGroup dst.Image = previous.Image + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for i := range dst.SecurityGroups { + restorev1beta1SecurityGroupParam(&previous.SecurityGroups[i], &dst.SecurityGroups[i]) + } + } + if len(dst.Ports) == len(previous.Ports) { for i := range dst.Ports { restorev1beta1Port(&previous.Ports[i], &dst.Ports[i]) @@ -160,13 +170,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 +215,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/types_conversion.go b/api/v1alpha7/types_conversion.go index a63cd212ed..f98207a409 100644 --- a/api/v1alpha7/types_conversion.go +++ b/api/v1alpha7/types_conversion.go @@ -34,6 +34,13 @@ func restorev1alpha7SecurityGroupFilter(previous *SecurityGroupFilter, dst *Secu dst.TagsAny = previous.TagsAny dst.NotTags = previous.NotTags dst.NotTagsAny = previous.NotTagsAny + + // If ID was set we lost all other filter params + if dst.ID != "" { + dst.Name = previous.Name + dst.Description = previous.Description + dst.ProjectID = previous.ProjectID + } } func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) { @@ -44,19 +51,48 @@ func restorev1alpha7SecurityGroup(previous *SecurityGroup, dst *SecurityGroup) { dst.Rules = previous.Rules } -func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *infrav1.SecurityGroupFilter, s apiconversion.Scope) error { - if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, out, s); err != nil { +func restorev1beta1SecurityGroupParam(previous *infrav1.SecurityGroupParam, dst *infrav1.SecurityGroupParam) { + if previous == nil || dst == nil { + return + } + + if dst.Filter != nil && previous.Filter != nil { + dst.Filter.Tags = previous.Filter.Tags + dst.Filter.TagsAny = previous.Filter.TagsAny + dst.Filter.NotTags = previous.Filter.NotTags + dst.Filter.NotTagsAny = previous.Filter.NotTagsAny + } +} + +func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(in *SecurityGroupFilter, out *infrav1.SecurityGroupParam, s apiconversion.Scope) error { + if in.ID != "" { + out.ID = &in.ID + return nil + } + + filter := &infrav1.SecurityGroupFilter{} + if err := autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in, filter, s); err != nil { return err } - infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &out.FilterByNeutronTags) + infrav1.ConvertAllTagsTo(in.Tags, in.TagsAny, in.NotTags, in.NotTagsAny, &filter.FilterByNeutronTags) + if !filter.IsZero() { + out.Filter = filter + } return nil } -func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupFilter, out *SecurityGroupFilter, s apiconversion.Scope) error { - if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in, out, s); err != nil { - return err +func Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(in *infrav1.SecurityGroupParam, out *SecurityGroupFilter, s apiconversion.Scope) error { + if in.ID != nil { + out.ID = *in.ID + return nil + } + + if in.Filter != nil { + if err := autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in.Filter, out, s); err != nil { + return err + } + infrav1.ConvertAllTagsFrom(&in.Filter.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) } - infrav1.ConvertAllTagsFrom(&in.FilterByNeutronTags, &out.Tags, &out.TagsAny, &out.NotTags, &out.NotTagsAny) return nil } @@ -294,6 +330,12 @@ func restorev1beta1Port(previous *infrav1.PortOpts, dst *infrav1.PortOpts) { dstProfile.TrustedVF = prevProfile.TrustedVF } } + + if len(dst.SecurityGroups) == len(previous.SecurityGroups) { + for j := range dst.SecurityGroups { + restorev1beta1SecurityGroupParam(&previous.SecurityGroups[j], &dst.SecurityGroups[j]) + } + } } func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error { @@ -334,9 +376,9 @@ func Convert_v1alpha7_PortOpts_To_v1beta1_PortOpts(in *PortOpts, out *infrav1.Po } if len(in.SecurityGroupFilters) > 0 { - out.SecurityGroups = make([]infrav1.SecurityGroupFilter, len(in.SecurityGroupFilters)) + out.SecurityGroups = make([]infrav1.SecurityGroupParam, len(in.SecurityGroupFilters)) for i := range in.SecurityGroupFilters { - if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil { + if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(&in.SecurityGroupFilters[i], &out.SecurityGroups[i], s); err != nil { return err } } @@ -393,7 +435,7 @@ func Convert_v1beta1_PortOpts_To_v1alpha7_PortOpts(in *infrav1.PortOpts, out *Po if len(in.SecurityGroups) > 0 { out.SecurityGroupFilters = make([]SecurityGroupFilter, len(in.SecurityGroups)) for i := range in.SecurityGroups { - if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&in.SecurityGroups[i], &out.SecurityGroupFilters[i], s); err != nil { return err } } @@ -454,3 +496,11 @@ func Convert_v1alpha7_NetworkFilter_To_v1beta1_NetworkFilter(_ *NetworkFilter, _ func Convert_v1beta1_NetworkFilter_To_v1alpha7_NetworkFilter(_ *infrav1.NetworkFilter, _ *NetworkFilter, _ apiconversion.Scope) error { return errors.New("Convert_v1beta1_NetworkFilter_To_v1alpha6_NetworkFilter should not be called") } + +func Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(_ *SecurityGroupFilter, _ *infrav1.SecurityGroupFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter should not be called") +} + +func Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(_ *infrav1.SecurityGroupFilter, _ *SecurityGroupFilter, _ apiconversion.Scope) error { + return errors.New("Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter should not be called") +} diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go index e2ae6041c7..87bb5dc328 100644 --- a/api/v1alpha7/zz_generated.conversion.go +++ b/api/v1alpha7/zz_generated.conversion.go @@ -371,6 +371,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*SecurityGroupFilter)(nil), (*v1beta1.SecurityGroupParam)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(a.(*SecurityGroupFilter), b.(*v1beta1.SecurityGroupParam), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*SecurityGroup)(nil), (*v1beta1.SecurityGroupStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha7_SecurityGroup_To_v1beta1_SecurityGroupStatus(a.(*SecurityGroup), b.(*v1beta1.SecurityGroupStatus), scope) }); err != nil { @@ -446,6 +451,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta1.SecurityGroupParam)(nil), (*SecurityGroupFilter)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(a.(*v1beta1.SecurityGroupParam), b.(*SecurityGroupFilter), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta1.SecurityGroupStatus)(nil), (*SecurityGroup)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_SecurityGroupStatus_To_v1alpha7_SecurityGroup(a.(*v1beta1.SecurityGroupStatus), b.(*SecurityGroup), scope) }); err != nil { @@ -1354,7 +1364,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 { @@ -1371,9 +1381,9 @@ func autoConvert_v1alpha7_OpenStackMachineSpec_To_v1beta1_OpenStackMachineSpec(i // WARNING: in.FloatingIP requires manual conversion: does not exist in peer-type if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]v1beta1.SecurityGroupFilter, len(*in)) + *out = make([]v1beta1.SecurityGroupParam, len(*in)) for i := range *in { - if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupParam(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1403,7 +1413,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 @@ -1420,7 +1430,7 @@ func autoConvert_v1beta1_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(i in, out := &in.SecurityGroups, &out.SecurityGroups *out = make([]SecurityGroupFilter, len(*in)) for i := range *in { - if err := Convert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { + if err := Convert_v1beta1_SecurityGroupParam_To_v1alpha7_SecurityGroupFilter(&(*in)[i], &(*out)[i], s); err != nil { return err } } @@ -1738,7 +1748,7 @@ func autoConvert_v1beta1_RouterFilter_To_v1alpha7_RouterFilter(in *v1beta1.Route } func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in *SecurityGroupFilter, out *v1beta1.SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID + // WARNING: in.ID requires manual conversion: does not exist in peer-type out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID @@ -1750,7 +1760,6 @@ func autoConvert_v1alpha7_SecurityGroupFilter_To_v1beta1_SecurityGroupFilter(in } func autoConvert_v1beta1_SecurityGroupFilter_To_v1alpha7_SecurityGroupFilter(in *v1beta1.SecurityGroupFilter, out *SecurityGroupFilter, s conversion.Scope) error { - out.ID = in.ID out.Name = in.Name out.Description = in.Description out.ProjectID = in.ProjectID diff --git a/api/v1beta1/openstackmachine_types.go b/api/v1beta1/openstackmachine_types.go index f222f71761..3f20a559ff 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"` @@ -55,7 +55,7 @@ type OpenStackMachineSpec struct { Ports []PortOpts `json:"ports,omitempty"` // The names of the security groups to assign to the instance - SecurityGroups []SecurityGroupFilter `json:"securityGroups,omitempty"` + SecurityGroups []SecurityGroupParam `json:"securityGroups,omitempty"` // Whether the server instance is created on a trunk port or not. Trunk bool `json:"trunk,omitempty"` diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index 0fe2f4a1f7..e9b9bbb2f6 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -28,22 +28,42 @@ 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 Tags []string `json:"tags,omitempty"` } +func (f *ImageFilter) IsZero() bool { + if f == nil { + return true + } + return f.Name == nil && len(f.Tags) == 0 +} + type ExternalRouterIPParam struct { // The FixedIP in the corresponding subnet FixedIP string `json:"fixedIP,omitempty"` @@ -88,8 +108,23 @@ func (f *FilterByNeutronTags) IsZero() bool { return f == nil || (len(f.Tags) == 0 && len(f.TagsAny) == 0 && len(f.NotTags) == 0 && len(f.NotTagsAny) == 0) } +// SecurityGroupParam specifies an OpenStack security group. It may be specified by ID or filter, but not both. +// +kubebuilder:validation:MaxProperties:=1 +// +kubebuilder:validation:MinProperties:=1 +type SecurityGroupParam struct { + // ID is the ID of the security group to use. If ID is provided, the other filters cannot be provided. Must be in UUID format. + // +kubebuilder:validation:Format:=uuid + // +optional + ID optional.String `json:"id,omitempty"` + + // Filter specifies a query to select an OpenStack security group. If provided, cannot be empty. + // +optional + Filter *SecurityGroupFilter `json:"filter,omitempty"` +} + +// SecurityGroupFilter specifies a query to select an OpenStack security group. At least one property must be set. +// +kubebuilder:validation:MinProperties:=1 type SecurityGroupFilter struct { - ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` ProjectID string `json:"projectID,omitempty"` @@ -97,6 +132,16 @@ type SecurityGroupFilter struct { FilterByNeutronTags `json:",inline"` } +func (f *SecurityGroupFilter) IsZero() bool { + if f == nil { + return true + } + return f.Name == "" && + f.Description == "" && + f.ProjectID == "" && + f.FilterByNeutronTags.IsZero() +} + // NetworkParam specifies an OpenStack network. It may be specified by either ID or Filter, but not both. // +kubebuilder:validation:MaxProperties:=1 // +kubebuilder:validation:MinProperties:=1 @@ -232,7 +277,7 @@ type PortOpts struct { // SecurityGroups is a list of the names, uuids, filters or any combination these of the security groups to assign to the instance. // +optional // +listType=atomic - SecurityGroups []SecurityGroupFilter `json:"securityGroups,omitempty"` + SecurityGroups []SecurityGroupParam `json:"securityGroups,omitempty"` // Tags applied to the port (and corresponding trunk, if a trunk is configured.) // These tags are applied in addition to the instance's tags, which will also be applied to the port. diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 6255ef3438..9c8f75f97f 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -307,11 +307,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) @@ -334,6 +329,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 @@ -925,7 +945,7 @@ func (in *OpenStackMachineSpec) DeepCopyInto(out *OpenStackMachineSpec) { } if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]SecurityGroupFilter, len(*in)) + *out = make([]SecurityGroupParam, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -1153,7 +1173,7 @@ func (in *PortOpts) DeepCopyInto(out *PortOpts) { } if in.SecurityGroups != nil { in, out := &in.SecurityGroups, &out.SecurityGroups - *out = make([]SecurityGroupFilter, len(*in)) + *out = make([]SecurityGroupParam, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -1415,6 +1435,31 @@ func (in *SecurityGroupFilter) DeepCopy() *SecurityGroupFilter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityGroupParam) DeepCopyInto(out *SecurityGroupParam) { + *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(SecurityGroupFilter) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityGroupParam. +func (in *SecurityGroupParam) DeepCopy() *SecurityGroupParam { + if in == nil { + return nil + } + out := new(SecurityGroupParam) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityGroupRuleSpec) DeepCopyInto(out *SecurityGroupRuleSpec) { *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 2a0546bb8c..1490e10a21 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. @@ -5349,68 +5355,84 @@ spec: uuids, filters or any combination these of the security groups to assign to the instance. items: + description: SecurityGroupParam specifies an OpenStack + security group. It may be specified by ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select + an OpenStack security group. If provided, cannot + be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array x-kubernetes-list-type: atomic @@ -5489,68 +5511,82 @@ spec: description: The names of the security groups to assign to the instance items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group to use. + If ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array serverGroup: 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 1eaba9daf1..c0a334ec4c 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. @@ -2782,68 +2787,85 @@ spec: names, uuids, filters or any combination these of the security groups to assign to the instance. items: + description: SecurityGroupParam specifies + an OpenStack security group. It may be specified + by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query + to select an OpenStack security group. + If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security + group to use. If ID is provided, the + other filters cannot be provided. Must + be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array x-kubernetes-list-type: atomic @@ -2923,68 +2945,84 @@ spec: description: The names of the security groups to assign to the instance items: + description: SecurityGroupParam specifies an OpenStack + security group. It may be specified by ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select + an OpenStack security group. If provided, + cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array serverGroup: 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 c0463608c0..1ea294dcb1 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 @@ -2125,68 +2132,82 @@ spec: or any combination these of the security groups to assign to the instance. items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group to use. + If ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array x-kubernetes-list-type: atomic @@ -2263,68 +2284,82 @@ spec: securityGroups: description: The names of the security groups to assign to the instance items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group to use. If ID + is provided, the other filters cannot be provided. Must be + in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array serverGroup: 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 2407fa4a06..4c1b1abb98 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. @@ -1803,68 +1809,84 @@ spec: uuids, filters or any combination these of the security groups to assign to the instance. items: + description: SecurityGroupParam specifies an OpenStack + security group. It may be specified by ID or filter, + but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select + an OpenStack security group. If provided, cannot + be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group + to use. If ID is provided, the other filters + cannot be provided. Must be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array x-kubernetes-list-type: atomic @@ -1943,68 +1965,82 @@ spec: description: The names of the security groups to assign to the instance items: + description: SecurityGroupParam specifies an OpenStack security + group. It may be specified by ID or filter, but not both. + maxProperties: 1 + minProperties: 1 properties: - description: - type: string + filter: + description: Filter specifies a query to select an OpenStack + security group. If provided, cannot be empty. + minProperties: 1 + properties: + description: + type: string + name: + type: string + notTags: + description: |- + NotTags is a list of tags to filter by. If specified, resources which + contain all of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + notTagsAny: + description: |- + NotTagsAny is a list of tags to filter by. If specified, resources + which contain any of the given tags will be excluded from the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + projectID: + type: string + tags: + description: |- + Tags is a list of tags to filter by. If specified, the resource must + have all of the tags specified to be included in the result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + tagsAny: + description: |- + TagsAny is a list of tags to filter by. If specified, the resource + must have at least one of the tags specified to be included in the + result. + items: + description: |- + NeutronTag represents a tag on a Neutron resource. + It may not be empty and may not contain commas. + minLength: 1 + pattern: ^[^,]+$ + type: string + type: array + x-kubernetes-list-type: set + type: object id: + description: ID is the ID of the security group to use. + If ID is provided, the other filters cannot be provided. + Must be in UUID format. + format: uuid type: string - name: - type: string - notTags: - description: |- - NotTags is a list of tags to filter by. If specified, resources which - contain all of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - notTagsAny: - description: |- - NotTagsAny is a list of tags to filter by. If specified, resources - which contain any of the given tags will be excluded from the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - projectID: - type: string - tags: - description: |- - Tags is a list of tags to filter by. If specified, the resource must - have all of the tags specified to be included in the result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set - tagsAny: - description: |- - TagsAny is a list of tags to filter by. If specified, the resource - must have at least one of the tags specified to be included in the - result. - items: - description: |- - NeutronTag represents a tag on a Neutron resource. - It may not be empty and may not contain commas. - minLength: 1 - pattern: ^[^,]+$ - type: string - type: array - x-kubernetes-list-type: set type: object type: array serverGroup: diff --git a/controllers/openstackcluster_controller_test.go b/controllers/openstackcluster_controller_test.go index 0b6fe63784..c2a602ec31 100644 --- a/controllers/openstackcluster_controller_test.go +++ b/controllers/openstackcluster_controller_test.go @@ -62,8 +62,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 c941f11d04..53c504e05c 100644 --- a/controllers/openstackmachine_controller_test.go +++ b/controllers/openstackmachine_controller_test.go @@ -84,14 +84,14 @@ 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{ {Key: "test-metadata", Value: "test-value"}, }, ConfigDrive: pointer.Bool(true), - SecurityGroups: []infrav1.SecurityGroupFilter{}, + SecurityGroups: []infrav1.SecurityGroupParam{}, ServerGroup: &infrav1.ServerGroupFilter{ID: serverGroupUUID}, }, Status: infrav1.OpenStackMachineStatus{ diff --git a/docs/book/src/api/v1beta1/api.md b/docs/book/src/api/v1beta1/api.md index 24c303f15e..581f7326ef 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 @@ -626,8 +626,8 @@ If not specified a default port will be added for the default cluster network. securityGroups
- -[]SecurityGroupFilter + +[]SecurityGroupParam @@ -1580,10 +1580,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.

@@ -1595,38 +1595,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.

+

+ + + + + + + + + + @@ -3101,8 +3136,8 @@ string @@ -3140,8 +3175,8 @@ If not specified a default port will be added for the default cluster network.securityGroups
- -[]SecurityGroupFilter + +[]SecurityGroupParam @@ -3473,8 +3508,8 @@ string @@ -3512,8 +3547,8 @@ If not specified a default port will be added for the default cluster network.securityGroups
- -[]SecurityGroupFilter + +[]SecurityGroupParam @@ -3750,8 +3785,8 @@ string @@ -4396,10 +4431,10 @@ FilterByNeutronTags

(Appears on: -OpenStackMachineSpec, -PortOpts) +SecurityGroupParam)

+

SecurityGroupFilter specifies a query to select an OpenStack security group. At least one property must be set.

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
securityGroups
- -[]SecurityGroupFilter + +[]SecurityGroupParam
@@ -4411,16 +4446,6 @@ FilterByNeutronTags - - - -
-id
- -string - -
-
name
string @@ -4466,6 +4491,52 @@ FilterByNeutronTags
+

SecurityGroupParam +

+

+(Appears on: +OpenStackMachineSpec, +PortOpts) +

+

+

SecurityGroupParam specifies an OpenStack security group. It may be specified by ID or filter, but not both.

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+id
+ +string + +
+(Optional) +

ID is the ID of the security group to use. If ID is provided, the other filters cannot be provided. Must be in UUID format.

+
+filter
+ + +SecurityGroupFilter + + +
+(Optional) +

Filter specifies a query to select an OpenStack security group. If provided, cannot be empty.

+

SecurityGroupRuleSpec

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/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml index 0c60d2e460..6c143c853c 100644 --- a/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml +++ b/kustomize/v1beta1/flatcar-sysext/patch-flatcar.yaml @@ -170,7 +170,8 @@ spec: template: spec: image: - name: ${FLATCAR_IMAGE_NAME} + filter: + name: ${FLATCAR_IMAGE_NAME} --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: OpenStackMachineTemplate @@ -180,4 +181,5 @@ spec: template: spec: image: - name: ${FLATCAR_IMAGE_NAME} + filter: + name: ${FLATCAR_IMAGE_NAME} diff --git a/kustomize/v1beta1/flatcar/patch-flatcar.yaml b/kustomize/v1beta1/flatcar/patch-flatcar.yaml index d95991efc9..a702429646 100644 --- a/kustomize/v1beta1/flatcar/patch-flatcar.yaml +++ b/kustomize/v1beta1/flatcar/patch-flatcar.yaml @@ -94,7 +94,8 @@ spec: template: spec: image: - name: ${OPENSTACK_FLATCAR_IMAGE_NAME} + filter: + name: ${OPENSTACK_FLATCAR_IMAGE_NAME} --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: OpenStackMachineTemplate @@ -104,4 +105,5 @@ spec: template: spec: image: - name: ${OPENSTACK_FLATCAR_IMAGE_NAME} + filter: + name: ${OPENSTACK_FLATCAR_IMAGE_NAME} 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 035bdaf824..b4419b691d 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_ResolveMachineSpec(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_ResolveMachineSpec(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_ResolveMachineSpec(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_ResolveMachineSpec(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_ResolveMachineSpec(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_ResolveMachineSpec(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.NetworkParam{ diff --git a/pkg/cloud/services/networking/port_test.go b/pkg/cloud/services/networking/port_test.go index ea0b6f3816..501f5f39cc 100644 --- a/pkg/cloud/services/networking/port_test.go +++ b/pkg/cloud/services/networking/port_test.go @@ -685,8 +685,8 @@ func TestService_ConstructPorts(t *testing.T) { { name: "machine spec security groups added to defaults", spec: infrav1.OpenStackMachineSpec{ - SecurityGroups: []infrav1.SecurityGroupFilter{ - {Name: "test-security-group"}, + SecurityGroups: []infrav1.SecurityGroupParam{ + {Filter: &infrav1.SecurityGroupFilter{Name: "test-security-group"}}, }, }, expectNetwork: func(m *mock.MockNetworkClientMockRecorder) { @@ -710,11 +710,11 @@ func TestService_ConstructPorts(t *testing.T) { { name: "port security groups override machine spec security groups", spec: infrav1.OpenStackMachineSpec{ - SecurityGroups: []infrav1.SecurityGroupFilter{ - {Name: "machine-security-group"}, + SecurityGroups: []infrav1.SecurityGroupParam{ + {Filter: &infrav1.SecurityGroupFilter{Name: "machine-security-group"}}, }, Ports: []infrav1.PortOpts{ - {SecurityGroups: []infrav1.SecurityGroupFilter{{Name: "port-security-group"}}}, + {SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: "port-security-group"}}}}, }, }, expectNetwork: func(m *mock.MockNetworkClientMockRecorder) { @@ -758,7 +758,7 @@ func TestService_ConstructPorts(t *testing.T) { { name: "managed security group and machine security groups added to port", spec: infrav1.OpenStackMachineSpec{ - SecurityGroups: []infrav1.SecurityGroupFilter{{Name: "machine-security-group"}}, + SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: "machine-security-group"}}}, }, managedSecurityGroup: pointer.String(securityGroupID1), expectNetwork: func(m *mock.MockNetworkClientMockRecorder) { diff --git a/pkg/cloud/services/networking/securitygroups.go b/pkg/cloud/services/networking/securitygroups.go index ecde85fe84..5d159f52a5 100644 --- a/pkg/cloud/services/networking/securitygroups.go +++ b/pkg/cloud/services/networking/securitygroups.go @@ -17,6 +17,7 @@ limitations under the License. package networking import ( + "errors" "fmt" "slices" @@ -308,21 +309,26 @@ func validateRemoteManagedGroups(remoteManagedGroups map[string]string, ruleRemo return nil } -func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupFilter) ([]string, error) { +func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupParam) ([]string, error) { var sgIDs []string for i := range securityGroupParams { sg := &securityGroupParams[i] // Don't validate an explicit UUID if we were given one - if sg.ID != "" { - if isDuplicate(sgIDs, sg.ID) { + if sg.ID != nil { + if isDuplicate(sgIDs, *sg.ID) { continue } - sgIDs = append(sgIDs, sg.ID) + sgIDs = append(sgIDs, *sg.ID) continue } - listOpts := filterconvert.SecurityGroupFilterToListOpts(sg) + if sg.Filter == nil { + // Should have been caught by validation + return nil, errors.New("security group param must have id or filter") + } + + listOpts := filterconvert.SecurityGroupFilterToListOpts(sg.Filter) if listOpts.ProjectID == "" { listOpts.ProjectID = s.scope.ProjectID() } @@ -332,7 +338,7 @@ func (s *Service) GetSecurityGroups(securityGroupParams []infrav1.SecurityGroupF } if len(SGList) == 0 { - return nil, fmt.Errorf("security group %s not found", sg.Name) + return nil, fmt.Errorf("security group %d not found", i) } for _, group := range SGList { diff --git a/pkg/utils/filterconvert/convert.go b/pkg/utils/filterconvert/convert.go index c1194b7880..8ece362ab6 100644 --- a/pkg/utils/filterconvert/convert.go +++ b/pkg/utils/filterconvert/convert.go @@ -31,7 +31,6 @@ func SecurityGroupFilterToListOpts(securityGroupFilter *infrav1.SecurityGroupFil return securitygroups.ListOpts{} } return securitygroups.ListOpts{ - ID: securityGroupFilter.ID, Name: securityGroupFilter.Name, Description: securityGroupFilter.Description, ProjectID: securityGroupFilter.ProjectID, 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/templates/cluster-template-flatcar-sysext.yaml b/templates/cluster-template-flatcar-sysext.yaml index 9cbef933cc..ec33bdeff2 100644 --- a/templates/cluster-template-flatcar-sysext.yaml +++ b/templates/cluster-template-flatcar-sysext.yaml @@ -268,7 +268,8 @@ spec: spec: flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} image: - name: ${FLATCAR_IMAGE_NAME} + filter: + name: ${FLATCAR_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 @@ -280,5 +281,6 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${FLATCAR_IMAGE_NAME} + filter: + name: ${FLATCAR_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} diff --git a/templates/cluster-template-flatcar.yaml b/templates/cluster-template-flatcar.yaml index 3d3f92ba23..4282265943 100644 --- a/templates/cluster-template-flatcar.yaml +++ b/templates/cluster-template-flatcar.yaml @@ -192,7 +192,8 @@ spec: spec: flavor: ${OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_FLATCAR_IMAGE_NAME} + filter: + name: ${OPENSTACK_FLATCAR_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} --- apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 @@ -204,5 +205,6 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_FLATCAR_IMAGE_NAME} + filter: + name: ${OPENSTACK_FLATCAR_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} diff --git a/templates/cluster-template-without-lb.yaml b/templates/cluster-template-without-lb.yaml index 35acfdbdf1..6dbf7a72d1 100644 --- a/templates/cluster-template-without-lb.yaml +++ b/templates/cluster-template-without-lb.yaml @@ -144,7 +144,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: infrastructure.cluster.x-k8s.io/v1beta1 @@ -156,5 +157,6 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME} + filter: + name: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} diff --git a/templates/cluster-template.yaml b/templates/cluster-template.yaml index bc8c8aab8c..3508d37e26 100644 --- a/templates/cluster-template.yaml +++ b/templates/cluster-template.yaml @@ -146,7 +146,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: infrastructure.cluster.x-k8s.io/v1beta1 @@ -158,5 +159,6 @@ spec: spec: flavor: ${OPENSTACK_NODE_MACHINE_FLAVOR} image: - name: ${OPENSTACK_IMAGE_NAME} + filter: + name: ${OPENSTACK_IMAGE_NAME} sshKeyName: ${OPENSTACK_SSH_KEY_NAME} diff --git a/templates/clusterclass-dev-test.yaml b/templates/clusterclass-dev-test.yaml index 2cd3a38531..5743a6367d 100644 --- a/templates/clusterclass-dev-test.yaml +++ b/templates/clusterclass-dev-test.yaml @@ -43,7 +43,7 @@ spec: controlPlane: true jsonPatches: - op: add - path: /spec/template/spec/image/name + path: /spec/template/spec/image/filter/name valueFrom: template: | ubuntu-2204-kube-{{ .builtin.controlPlane.version }} @@ -59,7 +59,7 @@ spec: - default-worker jsonPatches: - op: add - path: /spec/template/spec/image/name + path: /spec/template/spec/image/filter/name valueFrom: template: | ubuntu-2204-kube-{{ .builtin.machineDeployment.version }} diff --git a/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml b/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml new file mode 100644 index 0000000000..7136e9600d --- /dev/null +++ b/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/kustomization.yaml @@ -0,0 +1,10 @@ +# Modifications to release templates common to all e2e test scenarios +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: +- target: + kind: OpenStackCluster + name: \${CLUSTER_NAME} + path: patch-cluster.yaml diff --git a/test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml b/test/e2e/data/kustomize/common-patches/cluster-prev1beta1/patch-cluster.yaml similarity index 100% rename from test/e2e/data/kustomize/common-patches/cni/patch-cluster.yaml rename to test/e2e/data/kustomize/common-patches/cluster-prev1beta1/patch-cluster.yaml diff --git a/test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml b/test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml new file mode 100644 index 0000000000..7136e9600d --- /dev/null +++ b/test/e2e/data/kustomize/common-patches/cluster/kustomization.yaml @@ -0,0 +1,10 @@ +# Modifications to release templates common to all e2e test scenarios +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: +- target: + kind: OpenStackCluster + name: \${CLUSTER_NAME} + path: patch-cluster.yaml diff --git a/test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml b/test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml new file mode 100644 index 0000000000..b6d9564506 --- /dev/null +++ b/test/e2e/data/kustomize/common-patches/cluster/patch-cluster.yaml @@ -0,0 +1,15 @@ +--- +- op: add + path: /spec/bastion + value: + enabled: true + spec: + flavor: ${OPENSTACK_BASTION_MACHINE_FLAVOR} + image: + filter: + name: ${OPENSTACK_BASTION_IMAGE_NAME} + sshKeyName: ${OPENSTACK_SSH_KEY_NAME} +- op: add + path: /spec/controlPlaneAvailabilityZones + value: + - ${OPENSTACK_FAILURE_DOMAIN} diff --git a/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml b/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml index 60fe867342..0f10084b63 100644 --- a/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml +++ b/test/e2e/data/kustomize/common-patches/cni/kustomization.yaml @@ -7,8 +7,4 @@ resources: - cni.yaml patches: -- target: - kind: OpenStackCluster - name: \${CLUSTER_NAME} - path: patch-cluster.yaml - path: patch-cni.yaml diff --git a/test/e2e/data/kustomize/default/kustomization.yaml b/test/e2e/data/kustomize/default/kustomization.yaml index 30f2c9d85d..e85e60a623 100644 --- a/test/e2e/data/kustomize/default/kustomization.yaml +++ b/test/e2e/data/kustomize/default/kustomization.yaml @@ -3,6 +3,7 @@ kind: Kustomization resources: - ../../../../../kustomize/v1beta1/default components: +- ../common-patches/cluster - ../common-patches/cni - ../upgrade-patches - ../common-patches/ccm diff --git a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml index 6738cde3a8..63c5035c15 100644 --- a/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml +++ b/test/e2e/data/kustomize/flatcar-sysext/kustomization.yaml @@ -3,6 +3,7 @@ resources: - ../../../../../kustomize/v1beta1/flatcar-sysext components: +- ../common-patches/cluster - ../common-patches/cni - ../common-patches/ccm - ../common-patches/externalNetworkByName diff --git a/test/e2e/data/kustomize/flatcar/kustomization.yaml b/test/e2e/data/kustomize/flatcar/kustomization.yaml index 2de905e98e..ca872d20cb 100644 --- a/test/e2e/data/kustomize/flatcar/kustomization.yaml +++ b/test/e2e/data/kustomize/flatcar/kustomization.yaml @@ -4,6 +4,7 @@ resources: - ../../../../../kustomize/v1beta1/flatcar components: +- ../common-patches/cluster - ../common-patches/cni - ../common-patches/ccm - ../common-patches/externalNetworkByName 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/data/kustomize/v1alpha6/kustomization.yaml b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml index 9f7ac4445d..f2035ba071 100644 --- a/test/e2e/data/kustomize/v1alpha6/kustomization.yaml +++ b/test/e2e/data/kustomize/v1alpha6/kustomization.yaml @@ -4,6 +4,7 @@ resources: - ../../../../../kustomize/v1alpha6/external-cloud-provider components: +- ../common-patches/cluster-prev1beta1 - ../common-patches/cni - ../common-patches/ccm diff --git a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml index ed5685505c..9bcee09929 100644 --- a/test/e2e/data/kustomize/v1alpha7/kustomization.yaml +++ b/test/e2e/data/kustomize/v1alpha7/kustomization.yaml @@ -4,6 +4,7 @@ resources: - ../../../../../kustomize/v1alpha6/external-cloud-provider components: +- ../common-patches/cluster-prev1beta1 - ../common-patches/cni - ../common-patches/ccm diff --git a/test/e2e/data/kustomize/without-lb/kustomization.yaml b/test/e2e/data/kustomize/without-lb/kustomization.yaml index 7f3842e60c..2d88085bde 100644 --- a/test/e2e/data/kustomize/without-lb/kustomization.yaml +++ b/test/e2e/data/kustomize/without-lb/kustomization.yaml @@ -4,6 +4,7 @@ resources: - ../../../../../kustomize/v1beta1/without-lb components: +- ../common-patches/cluster - ../common-patches/cni - ../common-patches/ccm - ../common-patches/externalNetworkByName diff --git a/test/e2e/suites/apivalidations/filters_test.go b/test/e2e/suites/apivalidations/filters_test.go index ce0b38637b..e2bad140a5 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-" @@ -51,9 +55,9 @@ var _ = Describe("Filter API validations", func() { // possible to specify them in, then create the // resulting object. It should be valid. - securityGroups := make([]infrav1.SecurityGroupFilter, len(tags)) + securityGroups := make([]infrav1.SecurityGroupParam, len(tags)) for i := range tags { - securityGroups[i].FilterByNeutronTags = tags[i] + securityGroups[i].Filter = &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]} } machine.Spec.SecurityGroups = securityGroups @@ -64,7 +68,7 @@ var _ = Describe("Filter API validations", func() { port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetParam{ Filter: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}, }}} - port.SecurityGroups = []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}} + port.SecurityGroups = []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]}}} } Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") @@ -97,9 +101,9 @@ var _ = Describe("Filter API validations", func() { DescribeTable("Disallow invalid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) { { machine := machine.DeepCopy() - securityGroups := make([]infrav1.SecurityGroupFilter, len(tags)) + securityGroups := make([]infrav1.SecurityGroupParam, len(tags)) for i := range tags { - securityGroups[i].FilterByNeutronTags = tags[i] + securityGroups[i].Filter = &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]} } machine.Spec.SecurityGroups = securityGroups Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid security group neutron tags") @@ -125,7 +129,7 @@ var _ = Describe("Filter API validations", func() { { machine := machine.DeepCopy() machine.Spec.Ports = []infrav1.PortOpts{ - {SecurityGroups: []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}}, + {SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{FilterByNeutronTags: tags[i]}}}}, } Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port security group neutron tags") } @@ -179,49 +183,59 @@ var _ = Describe("Filter API validations", func() { }), ) - const imageUUID = "5a78f794-cdc3-48d2-8d9f-0fd472fdd743" + Context("ImageParam", func() { + const imageUUID = "5a78f794-cdc3-48d2-8d9f-0fd472fdd743" - It("should not allow both ID and Name of ImageFilter to be set", func() { - By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ - ID: pointer.String(imageUUID), - Name: pointer.String("bar"), - } - Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") - }) + It("should not allow both ID and Filter to be set", func() { + 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"}, - } - 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() { + 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{ - ID: pointer.String(imageUUID), - } - Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") - }) + It("should allow UUID ID of ImageFilter to be set", func() { + machine.Spec.Image = infrav1.ImageParam{ + ID: pointer.String(imageUUID), + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + }) - It("should not allow non-UUID ID of ImageFilter to be set", func() { - By("Creating a machine") - machine.Spec.Image = infrav1.ImageFilter{ - ID: pointer.String("foo"), - } - Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") - }) + It("should not allow non-UUID ID of ImageFilter to be set", func() { + machine.Spec.Image = infrav1.ImageParam{ + ID: pointer.String("foo"), + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") + }) - 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"}, - } - Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + It("should allow Name and Tags of ImageFilter to be set", func() { + 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() { + machine.Spec.Image = infrav1.ImageParam{ + Filter: &infrav1.ImageFilter{}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") + }) }) Context("NetworkParam", func() { @@ -307,4 +321,46 @@ var _ = Describe("Filter API validations", func() { Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail") }) }) + + Context("SecurityGroupParam", func() { + It("should allow setting ID", func() { + machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{ + {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c")}, + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + }) + + It("should allow setting non-empty Filter", func() { + machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{ + {Filter: &infrav1.SecurityGroupFilter{Name: "foo"}}, + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + }) + + It("should not allow setting empty param", func() { + machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{{}} + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") + }) + + It("should not allow setting invalid id", func() { + machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{ + {ID: pointer.String("foo")}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") + }) + + It("should not allow setting empty Filter", func() { + machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{ + {Filter: &infrav1.SecurityGroupFilter{}}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail") + }) + + It("should not allow setting both ID and Filter", func() { + machine.Spec.SecurityGroups = []infrav1.SecurityGroupParam{ + {ID: pointer.String("06c32c52-f207-4f6a-a769-bbcbe5a43f5c"), Filter: &infrav1.SecurityGroupFilter{Name: "foo"}}, + } + 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..37422eb33f 100644 --- a/test/e2e/suites/e2e/e2e_test.go +++ b/test/e2e/suites/e2e/e2e_test.go @@ -379,7 +379,7 @@ var _ = Describe("e2e tests [PR-Blocking]", func() { Trunk: pointer.Bool(true), }, { - SecurityGroups: []infrav1.SecurityGroupFilter{{Name: testSecurityGroupName}}, + SecurityGroups: []infrav1.SecurityGroupParam{{Filter: &infrav1.SecurityGroupFilter{Name: testSecurityGroupName}}}, }, } @@ -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{ diff --git a/test/helpers/fuzzerfuncs.go b/test/helpers/fuzzerfuncs.go index 35720fcdd1..36ee8baa85 100644 --- a/test/helpers/fuzzerfuncs.go +++ b/test/helpers/fuzzerfuncs.go @@ -137,5 +137,13 @@ func InfraV1FuzzerFuncs() []interface{} { func(param *infrav1.SubnetParam, c fuzz.Continue) { fuzzFilterParam(¶m.ID, ¶m.Filter, c) }, + + func(param *infrav1.SecurityGroupParam, c fuzz.Continue) { + fuzzFilterParam(¶m.ID, ¶m.Filter, c) + }, + + func(param *infrav1.ImageParam, c fuzz.Continue) { + fuzzFilterParam(¶m.ID, ¶m.Filter, c) + }, } }