From 477e1801f558078373ec59522ae9547e3dcf0692 Mon Sep 17 00:00:00 2001 From: Maysa Macedo Date: Tue, 12 Dec 2023 10:35:52 -0300 Subject: [PATCH] Support BYO dual-stack Network This commit adds support to specify more than one existent subnet on the `OpenStackCluster`. The existent `OpenStackClusterSpec.Subnet` is removed in favor of `OpenStackClusterSpec.Subnets`. --- api/v1alpha5/conversion.go | 26 +++++- api/v1alpha5/conversion_test.go | 4 +- api/v1alpha5/zz_generated.conversion.go | 13 +-- api/v1alpha6/conversion.go | 25 +++++- api/v1alpha6/zz_generated.conversion.go | 13 +-- api/v1alpha7/conversion.go | 28 ++++++ api/v1alpha7/zz_generated.conversion.go | 86 ++++++++++++------- api/v1alpha8/openstackcluster_types.go | 4 +- api/v1alpha8/zz_generated.deepcopy.go | 6 +- ...re.cluster.x-k8s.io_openstackclusters.yaml | 62 ++++++------- ...er.x-k8s.io_openstackclustertemplates.yaml | 62 ++++++------- controllers/openstackcluster_controller.go | 34 ++++---- 12 files changed, 226 insertions(+), 137 deletions(-) diff --git a/api/v1alpha5/conversion.go b/api/v1alpha5/conversion.go index 77e39fa2eb..65b2591c9d 100644 --- a/api/v1alpha5/conversion.go +++ b/api/v1alpha5/conversion.go @@ -187,8 +187,16 @@ func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) er } func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { - // Our new flag has no equivalent in v1alpha5 - return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s) + err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Subnets != nil && len(in.Subnets) == 1 { + out.Subnet = SubnetFilter(in.Subnets[0]) + } + + return nil } func Convert_v1alpha8_LoadBalancer_To_v1alpha5_LoadBalancer(in *infrav1.LoadBalancer, out *LoadBalancer, s conversion.Scope) error { @@ -437,3 +445,17 @@ func Convert_v1alpha5_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus( func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s conversion.Scope) error { return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha5_OpenStackMachineSpec(in, out, s) } + +func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s conversion.Scope) error { + err := autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + emptySubnet := SubnetFilter{} + if in.Subnet != emptySubnet { + out.Subnets = []infrav1.SubnetFilter{infrav1.SubnetFilter(in.Subnet)} + } + + return nil +} diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go index 95f83052dd..259ccff1ed 100644 --- a/api/v1alpha5/conversion_test.go +++ b/api/v1alpha5/conversion_test.go @@ -49,7 +49,7 @@ func TestConvertFrom(t *testing.T) { Spec: OpenStackClusterSpec{}, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}},\"status\":{\"ready\":false}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"managedSecurityGroups\":false,\"network\":{}},\"status\":{\"ready\":false}}", }, }, }, @@ -64,7 +64,7 @@ func TestConvertFrom(t *testing.T) { Spec: OpenStackClusterTemplateSpec{}, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"managedSecurityGroups\":false,\"network\":{},\"subnet\":{}}}}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"allowAllInClusterTraffic\":false,\"apiServerLoadBalancer\":{},\"cloudName\":\"\",\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"managedSecurityGroups\":false,\"network\":{}}}}}", }, }, }, diff --git a/api/v1alpha5/zz_generated.conversion.go b/api/v1alpha5/zz_generated.conversion.go index 5ef62e512e..2fba24d093 100644 --- a/api/v1alpha5/zz_generated.conversion.go +++ b/api/v1alpha5/zz_generated.conversion.go @@ -668,9 +668,7 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec( if err := Convert_v1alpha5_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil { return err } - if err := Convert_v1alpha5_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Subnet requires manual conversion: does not exist in peer-type out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs @@ -710,11 +708,6 @@ func autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec( return nil } -// Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function. -func Convert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error { - return autoConvert_v1alpha5_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s) -} - func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { out.CloudName = in.CloudName out.NodeCIDR = in.NodeCIDR @@ -722,9 +715,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha5_OpenStackClusterSpec( if err := Convert_v1alpha8_NetworkFilter_To_v1alpha5_NetworkFilter(&in.Network, &out.Network, s); err != nil { return err } - if err := Convert_v1alpha8_SubnetFilter_To_v1alpha5_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type // WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { diff --git a/api/v1alpha6/conversion.go b/api/v1alpha6/conversion.go index 66f77e3076..e228115cac 100644 --- a/api/v1alpha6/conversion.go +++ b/api/v1alpha6/conversion.go @@ -432,7 +432,16 @@ func convertNetworksToPorts(networks []NetworkParam) []infrav1.PortOpts { } func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error { - return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in, out, s) + err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Subnets != nil && len(in.Subnets) == 1 { + out.Subnet = SubnetFilter(in.Subnets[0]) + } + + return nil } func Convert_v1alpha6_PortOpts_To_v1alpha8_PortOpts(in *PortOpts, out *infrav1.PortOpts, s apiconversion.Scope) error { @@ -659,3 +668,17 @@ func Convert_v1alpha6_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus( func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *infrav1.OpenStackMachineSpec, out *OpenStackMachineSpec, s apiconversion.Scope) error { return autoConvert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in, out, s) } + +func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + emptySubnet := SubnetFilter{} + if in.Subnet != emptySubnet { + out.Subnets = []infrav1.SubnetFilter{infrav1.SubnetFilter(in.Subnet)} + } + + return nil +} diff --git a/api/v1alpha6/zz_generated.conversion.go b/api/v1alpha6/zz_generated.conversion.go index ec1a8020f7..3e5cefc52b 100644 --- a/api/v1alpha6/zz_generated.conversion.go +++ b/api/v1alpha6/zz_generated.conversion.go @@ -690,9 +690,7 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec( if err := Convert_v1alpha6_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil { return err } - if err := Convert_v1alpha6_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Subnet requires manual conversion: does not exist in peer-type out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { in, out := &in.ExternalRouterIPs, &out.ExternalRouterIPs @@ -733,11 +731,6 @@ func autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec( return nil } -// Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function. -func Convert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error { - return autoConvert_v1alpha6_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s) -} - func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { out.CloudName = in.CloudName out.NodeCIDR = in.NodeCIDR @@ -745,9 +738,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha6_OpenStackClusterSpec( if err := Convert_v1alpha8_NetworkFilter_To_v1alpha6_NetworkFilter(&in.Network, &out.Network, s); err != nil { return err } - if err := Convert_v1alpha8_SubnetFilter_To_v1alpha6_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type // WARNING: in.NetworkMTU requires manual conversion: does not exist in peer-type out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) if in.ExternalRouterIPs != nil { diff --git a/api/v1alpha7/conversion.go b/api/v1alpha7/conversion.go index 6b17160fdf..c06fcf38e7 100644 --- a/api/v1alpha7/conversion.go +++ b/api/v1alpha7/conversion.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha7 import ( + apiconversion "k8s.io/apimachinery/pkg/conversion" ctrlconversion "sigs.k8s.io/controller-runtime/pkg/conversion" infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha8" @@ -232,3 +233,30 @@ func (r *OpenStackMachineTemplateList) ConvertFrom(srcRaw ctrlconversion.Hub) er src := srcRaw.(*infrav1.OpenStackMachineTemplateList) return Convert_v1alpha8_OpenStackMachineTemplateList_To_v1alpha7_OpenStackMachineTemplateList(src, r, nil) } + +func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *infrav1.OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + emptySubnet := SubnetFilter{} + if in.Subnet != emptySubnet { + out.Subnets = []infrav1.SubnetFilter{infrav1.SubnetFilter(in.Subnet)} + } + + return nil +} + +func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *infrav1.OpenStackClusterSpec, out *OpenStackClusterSpec, s apiconversion.Scope) error { + err := autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s) + if err != nil { + return err + } + + if in.Subnets != nil && len(in.Subnets) == 1 { + out.Subnet = SubnetFilter(in.Subnets[0]) + } + + return nil +} diff --git a/api/v1alpha7/zz_generated.conversion.go b/api/v1alpha7/zz_generated.conversion.go index 2d4a574a69..12358199d2 100644 --- a/api/v1alpha7/zz_generated.conversion.go +++ b/api/v1alpha7/zz_generated.conversion.go @@ -199,16 +199,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*OpenStackClusterStatus)(nil), (*v1alpha8.OpenStackClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(a.(*OpenStackClusterStatus), b.(*v1alpha8.OpenStackClusterStatus), scope) }); err != nil { @@ -449,6 +439,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*OpenStackClusterSpec)(nil), (*v1alpha8.OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(a.(*OpenStackClusterSpec), b.(*v1alpha8.OpenStackClusterSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha8.OpenStackClusterSpec)(nil), (*OpenStackClusterSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(a.(*v1alpha8.OpenStackClusterSpec), b.(*OpenStackClusterSpec), scope) + }); err != nil { + return err + } return nil } @@ -848,7 +848,17 @@ func Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(in *v1alpha8 func autoConvert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in *OpenStackClusterList, out *v1alpha8.OpenStackClusterList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]v1alpha8.OpenStackCluster)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha8.OpenStackCluster, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_OpenStackCluster_To_v1alpha8_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -859,7 +869,17 @@ func Convert_v1alpha7_OpenStackClusterList_To_v1alpha8_OpenStackClusterList(in * func autoConvert_v1alpha8_OpenStackClusterList_To_v1alpha7_OpenStackClusterList(in *v1alpha8.OpenStackClusterList, out *OpenStackClusterList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]OpenStackCluster)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackCluster, len(*in)) + for i := range *in { + if err := Convert_v1alpha8_OpenStackCluster_To_v1alpha7_OpenStackCluster(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -875,9 +895,7 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec( if err := Convert_v1alpha7_NetworkFilter_To_v1alpha8_NetworkFilter(&in.Network, &out.Network, s); err != nil { return err } - if err := Convert_v1alpha7_SubnetFilter_To_v1alpha8_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Subnet requires manual conversion: does not exist in peer-type out.NetworkMTU = in.NetworkMTU out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) out.ExternalRouterIPs = *(*[]v1alpha8.ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs)) @@ -901,11 +919,6 @@ func autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec( return nil } -// Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec is an autogenerated conversion function. -func Convert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in *OpenStackClusterSpec, out *v1alpha8.OpenStackClusterSpec, s conversion.Scope) error { - return autoConvert_v1alpha7_OpenStackClusterSpec_To_v1alpha8_OpenStackClusterSpec(in, out, s) -} - func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { out.CloudName = in.CloudName out.NodeCIDR = in.NodeCIDR @@ -913,9 +926,7 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec( if err := Convert_v1alpha8_NetworkFilter_To_v1alpha7_NetworkFilter(&in.Network, &out.Network, s); err != nil { return err } - if err := Convert_v1alpha8_SubnetFilter_To_v1alpha7_SubnetFilter(&in.Subnet, &out.Subnet, s); err != nil { - return err - } + // WARNING: in.Subnets requires manual conversion: does not exist in peer-type out.NetworkMTU = in.NetworkMTU out.DNSNameservers = *(*[]string)(unsafe.Pointer(&in.DNSNameservers)) out.ExternalRouterIPs = *(*[]ExternalRouterIPParam)(unsafe.Pointer(&in.ExternalRouterIPs)) @@ -939,11 +950,6 @@ func autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec( return nil } -// Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec is an autogenerated conversion function. -func Convert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in *v1alpha8.OpenStackClusterSpec, out *OpenStackClusterSpec, s conversion.Scope) error { - return autoConvert_v1alpha8_OpenStackClusterSpec_To_v1alpha7_OpenStackClusterSpec(in, out, s) -} - func autoConvert_v1alpha7_OpenStackClusterStatus_To_v1alpha8_OpenStackClusterStatus(in *OpenStackClusterStatus, out *v1alpha8.OpenStackClusterStatus, s conversion.Scope) error { out.Ready = in.Ready out.Network = (*v1alpha8.NetworkStatusWithSubnets)(unsafe.Pointer(in.Network)) @@ -1014,7 +1020,17 @@ func Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTempl func autoConvert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterTemplateList(in *OpenStackClusterTemplateList, out *v1alpha8.OpenStackClusterTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]v1alpha8.OpenStackClusterTemplate)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha8.OpenStackClusterTemplate, len(*in)) + for i := range *in { + if err := Convert_v1alpha7_OpenStackClusterTemplate_To_v1alpha8_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -1025,7 +1041,17 @@ func Convert_v1alpha7_OpenStackClusterTemplateList_To_v1alpha8_OpenStackClusterT func autoConvert_v1alpha8_OpenStackClusterTemplateList_To_v1alpha7_OpenStackClusterTemplateList(in *v1alpha8.OpenStackClusterTemplateList, out *OpenStackClusterTemplateList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]OpenStackClusterTemplate)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OpenStackClusterTemplate, len(*in)) + for i := range *in { + if err := Convert_v1alpha8_OpenStackClusterTemplate_To_v1alpha7_OpenStackClusterTemplate(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } diff --git a/api/v1alpha8/openstackcluster_types.go b/api/v1alpha8/openstackcluster_types.go index 902e9c7c03..a0fb8a1ef1 100644 --- a/api/v1alpha8/openstackcluster_types.go +++ b/api/v1alpha8/openstackcluster_types.go @@ -47,8 +47,8 @@ type OpenStackClusterSpec struct { // If NodeCIDR cannot be set this can be used to detect an existing network. Network NetworkFilter `json:"network,omitempty"` - // If NodeCIDR cannot be set this can be used to detect an existing subnet. - Subnet SubnetFilter `json:"subnet,omitempty"` + // If NodeCIDR cannot be set this can be used to detect existing IPv4 and/or IPv6 subnets. + Subnets []SubnetFilter `json:"subnets,omitempty"` // NetworkMTU sets the maximum transmission unit (MTU) value to address fragmentation for the private network ID. // This value will be used only if the Cluster actuator creates the network. diff --git a/api/v1alpha8/zz_generated.deepcopy.go b/api/v1alpha8/zz_generated.deepcopy.go index 3ded212691..cbf388ab78 100644 --- a/api/v1alpha8/zz_generated.deepcopy.go +++ b/api/v1alpha8/zz_generated.deepcopy.go @@ -351,7 +351,11 @@ func (in *OpenStackClusterSpec) DeepCopyInto(out *OpenStackClusterSpec) { **out = **in } out.Network = in.Network - out.Subnet = in.Subnet + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]SubnetFilter, len(*in)) + copy(*out, *in) + } if in.DNSNameservers != nil { in, out := &in.DNSNameservers, &out.DNSNameservers *out = make([]string, len(*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 532490a5ea..9656a4cfd4 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -5370,37 +5370,39 @@ spec: tagsAny: type: string type: object - subnet: + subnets: description: If NodeCIDR cannot be set this can be used to detect - an existing subnet. - properties: - cidr: - type: string - description: - type: string - gateway_ip: - type: string - id: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RaMode: - type: string - name: - type: string - notTags: - type: string - notTagsAny: - type: string - projectId: - type: string - tags: - type: string - tagsAny: - type: string - type: object + existing IPv4 and/or IPv6 subnets. + items: + properties: + cidr: + type: string + description: + type: string + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + tags: + type: string + tagsAny: + type: string + type: object + type: array tags: description: Tags for all resources in cluster items: 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 73f10af04d..00798b5acd 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_openstackclustertemplates.yaml @@ -2923,37 +2923,39 @@ spec: tagsAny: type: string type: object - subnet: + subnets: description: If NodeCIDR cannot be set this can be used to - detect an existing subnet. - properties: - cidr: - type: string - description: - type: string - gateway_ip: - type: string - id: - type: string - ipVersion: - type: integer - ipv6AddressMode: - type: string - ipv6RaMode: - type: string - name: - type: string - notTags: - type: string - notTagsAny: - type: string - projectId: - type: string - tags: - type: string - tagsAny: - type: string - type: object + detect existing IPv4 and/or IPv6 subnets. + items: + properties: + cidr: + type: string + description: + type: string + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + tags: + type: string + tagsAny: + type: string + type: object + type: array tags: description: Tags for all resources in cluster items: diff --git a/controllers/openstackcluster_controller.go b/controllers/openstackcluster_controller.go index f83b8b75a9..77214cb6aa 100644 --- a/controllers/openstackcluster_controller.go +++ b/controllers/openstackcluster_controller.go @@ -461,26 +461,26 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o openStackCluster.Status.Network.Name = networkList[0].Name openStackCluster.Status.Network.Tags = networkList[0].Tags - subnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &openStackCluster.Spec.Subnet) - if err != nil { - err = fmt.Errorf("failed to find subnet: %w", err) + var filteredSubnets []infrav1.Subnet + for _, subnet := range openStackCluster.Spec.Subnets { + filteredSubnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &subnet) + if err != nil { + err = fmt.Errorf("failed to find subnet: %w", err) + // Set the cluster to failed if subnet filter is invalid + if errors.Is(err, networking.ErrFilterMatch) { + handleUpdateOSCError(openStackCluster, err) + } - // Set the cluster to failed if subnet filter is invalid - if errors.Is(err, networking.ErrFilterMatch) { - handleUpdateOSCError(openStackCluster, err) + return err } - - return err - } - - openStackCluster.Status.Network.Subnets = []infrav1.Subnet{ - { - ID: subnet.ID, - Name: subnet.Name, - CIDR: subnet.CIDR, - Tags: subnet.Tags, - }, + filteredSubnets = append(filteredSubnets, infrav1.Subnet{ + ID: filteredSubnet.ID, + Name: filteredSubnet.Name, + CIDR: filteredSubnet.CIDR, + Tags: filteredSubnet.Tags, + }) } + openStackCluster.Status.Network.Subnets = filteredSubnets } else { err := networkingService.ReconcileNetwork(openStackCluster, clusterName) if err != nil {