Skip to content

Commit 6a6b86a

Browse files
committed
Add GetSubnetByFilter
1 parent 41674c8 commit 6a6b86a

File tree

3 files changed

+72
-22
lines changed

3 files changed

+72
-22
lines changed

controllers/openstackcluster_controller.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -446,22 +446,23 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
446446
openStackCluster.Status.Network.Name = networkList[0].Name
447447
openStackCluster.Status.Network.Tags = networkList[0].Tags
448448

449-
subnetOpts := openStackCluster.Spec.Subnet.ToListOpt()
450-
subnetOpts.NetworkID = networkList[0].ID
451-
subnetList, err := networkingService.GetSubnetsByFilter(&subnetOpts)
452-
if err != nil || len(subnetList) == 0 {
453-
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find subnet: %v", err))
454-
return errors.Errorf("failed to find subnet: %v", err)
455-
}
456-
if len(subnetList) > 1 {
457-
handleUpdateOSCError(openStackCluster, errors.Errorf("failed to find only one subnet (result: %v): %v", subnetList, err))
458-
return errors.Errorf("failed to find only one subnet (result: %v): %v", subnetList, err)
449+
subnet, err := networkingService.GetSubnetByFilter(&openStackCluster.Spec.Subnet)
450+
if err != nil {
451+
err = fmt.Errorf("failed to find subnet: %w", err)
452+
453+
// Set the cluster to failed if subnet filter is invalid
454+
if errors.Is(err, networking.ErrFilterMatch) {
455+
handleUpdateOSCError(openStackCluster, err)
456+
}
457+
458+
return err
459459
}
460+
460461
openStackCluster.Status.Network.Subnet = &infrav1.Subnet{
461-
ID: subnetList[0].ID,
462-
Name: subnetList[0].Name,
463-
CIDR: subnetList[0].CIDR,
464-
Tags: subnetList[0].Tags,
462+
ID: subnet.ID,
463+
Name: subnet.Name,
464+
CIDR: subnet.CIDR,
465+
Tags: subnet.Tags,
465466
}
466467
} else {
467468
err := networkingService.ReconcileNetwork(openStackCluster, clusterName)

pkg/cloud/services/networking/network.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,37 @@ import (
2828
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha7"
2929
"sigs.k8s.io/cluster-api-provider-openstack/pkg/metrics"
3030
"sigs.k8s.io/cluster-api-provider-openstack/pkg/record"
31+
capoerrors "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/errors"
3132
"sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/names"
3233
)
3334

35+
var (
36+
ErrFilterMatch = fmt.Errorf("filter match error")
37+
ErrMultipleMatches = multipleMatchesError{}
38+
ErrNoMatches = noMatchesError{}
39+
)
40+
41+
type (
42+
multipleMatchesError struct{}
43+
noMatchesError struct{}
44+
)
45+
46+
func (e multipleMatchesError) Error() string {
47+
return "filter matched more than one resource"
48+
}
49+
50+
func (e multipleMatchesError) Is(err error) bool {
51+
return err == ErrFilterMatch
52+
}
53+
54+
func (e noMatchesError) Error() string {
55+
return "filter matched no resources"
56+
}
57+
58+
func (e noMatchesError) Is(err error) bool {
59+
return err == ErrFilterMatch
60+
}
61+
3462
type createOpts struct {
3563
AdminStateUp *bool `json:"admin_state_up,omitempty"`
3664
Name string `json:"name,omitempty"`
@@ -315,11 +343,36 @@ func (s *Service) GetSubnetsByFilter(opts subnets.ListOptsBuilder) ([]subnets.Su
315343
return []subnets.Subnet{}, err
316344
}
317345
if len(subnetList) == 0 {
318-
return nil, fmt.Errorf("no subnets could be found with the filters provided")
346+
return nil, ErrNoMatches
319347
}
320348
return subnetList, nil
321349
}
322350

351+
// GetSubnetByFilter gets a single subnet specified by the given SubnetFilter.
352+
// It returns an ErrFilterMatch if no or multiple subnets are found.
353+
func (s *Service) GetSubnetByFilter(filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
354+
// If the ID is set, we can just get the subnet by ID.
355+
if filter.ID != "" {
356+
subnet, err := s.client.GetSubnet(filter.ID)
357+
if capoerrors.IsNotFound(err) {
358+
return nil, ErrNoMatches
359+
}
360+
return subnet, err
361+
}
362+
363+
subnets, err := s.GetSubnetsByFilter(filter.ToListOpt())
364+
if err != nil {
365+
return nil, err
366+
}
367+
if len(subnets) == 0 {
368+
return nil, ErrNoMatches
369+
}
370+
if len(subnets) > 1 {
371+
return nil, ErrMultipleMatches
372+
}
373+
return &subnets[0], nil
374+
}
375+
323376
func getSubnetName(clusterName string) string {
324377
return fmt.Sprintf("%s-cluster-%s", networkPrefix, clusterName)
325378
}

pkg/cloud/services/networking/router.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,11 @@ func (s *Service) setRouterExternalIPs(openStackCluster *infrav1.OpenStackCluste
166166
for _, externalRouterIP := range openStackCluster.Spec.ExternalRouterIPs {
167167
subnetID := externalRouterIP.Subnet.UUID
168168
if subnetID == "" {
169-
listOpts := externalRouterIP.Subnet.Filter.ToListOpt()
170-
subnetsByFilter, err := s.GetSubnetsByFilter(&listOpts)
169+
subnet, err := s.GetSubnetByFilter(&externalRouterIP.Subnet.Filter)
171170
if err != nil {
172-
return err
171+
return fmt.Errorf("failed to get subnet for external router: %w", err)
173172
}
174-
if len(subnetsByFilter) != 1 {
175-
return fmt.Errorf("subnetParam didn't exactly match one subnet")
176-
}
177-
subnetID = subnetsByFilter[0].ID
173+
subnetID = subnet.ID
178174
}
179175
updateOpts.GatewayInfo.ExternalFixedIPs = append(updateOpts.GatewayInfo.ExternalFixedIPs, routers.ExternalFixedIP{
180176
IPAddress: externalRouterIP.FixedIP,

0 commit comments

Comments
 (0)