Skip to content

Commit b511a57

Browse files
authored
Merge pull request #1572 from shiftstack/issue1570
🐛 Always filter cluster subnets by cluster network ID
2 parents 295b75b + bbe2472 commit b511a57

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

controllers/openstackcluster_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ func reconcileNetworkComponents(scope scope.Scope, cluster *clusterv1.Cluster, o
445445
openStackCluster.Status.Network.Name = networkList[0].Name
446446
openStackCluster.Status.Network.Tags = networkList[0].Tags
447447

448-
subnet, err := networkingService.GetSubnetByFilter(&openStackCluster.Spec.Subnet)
448+
subnet, err := networkingService.GetNetworkSubnetByFilter(openStackCluster.Status.Network.ID, &openStackCluster.Spec.Subnet)
449449
if err != nil {
450450
err = fmt.Errorf("failed to find subnet: %w", err)
451451

controllers/openstackcluster_controller_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"github.com/golang/mock/gomock"
2525
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
2626
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
27+
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
28+
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
2729
. "github.com/onsi/ginkgo/v2"
2830
. "github.com/onsi/gomega"
2931
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -207,6 +209,63 @@ var _ = Describe("OpenStackCluster controller", func() {
207209
err = deleteBastion(scope, capiCluster, testCluster)
208210
Expect(err).To(BeNil())
209211
})
212+
It("should implicitly filter cluster subnets by cluster network", func() {
213+
const externalNetworkID = "a42211a2-4d2c-426f-9413-830e4b4abbbc"
214+
const clusterNetworkID = "6c90b532-7ba0-418a-a276-5ae55060b5b0"
215+
const clusterSubnetID = "cad5a91a-36de-4388-823b-b0cc82cadfdc"
216+
217+
testCluster.SetName("subnet-filtering")
218+
testCluster.Spec = infrav1.OpenStackClusterSpec{
219+
DisableAPIServerFloatingIP: true,
220+
APIServerFixedIP: "10.0.0.1",
221+
ExternalNetworkID: externalNetworkID,
222+
Network: infrav1.NetworkFilter{
223+
ID: clusterNetworkID,
224+
},
225+
}
226+
err := k8sClient.Create(ctx, testCluster)
227+
Expect(err).To(BeNil())
228+
err = k8sClient.Create(ctx, capiCluster)
229+
Expect(err).To(BeNil())
230+
scope, err := mockScopeFactory.NewClientScopeFromCluster(ctx, k8sClient, testCluster, nil, logr.Discard())
231+
Expect(err).To(BeNil())
232+
233+
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
234+
235+
// Fetch external network
236+
networkClientRecorder.ListNetwork(networks.ListOpts{
237+
ID: externalNetworkID,
238+
}).Return([]networks.Network{
239+
{
240+
ID: externalNetworkID,
241+
Name: "external-network",
242+
},
243+
}, nil)
244+
245+
// Fetch cluster network
246+
networkClientRecorder.ListNetwork(&networks.ListOpts{
247+
ID: clusterNetworkID,
248+
}).Return([]networks.Network{
249+
{
250+
ID: clusterNetworkID,
251+
Name: "cluster-network",
252+
},
253+
}, nil)
254+
255+
// Fetching cluster subnets should be filtered by cluster network id
256+
networkClientRecorder.ListSubnet(subnets.ListOpts{
257+
NetworkID: clusterNetworkID,
258+
}).Return([]subnets.Subnet{
259+
{
260+
ID: clusterSubnetID,
261+
Name: "cluster-subnet",
262+
CIDR: "192.168.0.0/24",
263+
},
264+
}, nil)
265+
266+
err = reconcileNetworkComponents(scope, capiCluster, testCluster)
267+
Expect(err).To(BeNil())
268+
})
210269
})
211270

212271
func createRequestFromOSCluster(openStackCluster *infrav1.OpenStackCluster) reconcile.Request {

pkg/cloud/services/networking/network.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,16 +351,31 @@ func (s *Service) GetSubnetsByFilter(opts subnets.ListOptsBuilder) ([]subnets.Su
351351
// GetSubnetByFilter gets a single subnet specified by the given SubnetFilter.
352352
// It returns an ErrFilterMatch if no or multiple subnets are found.
353353
func (s *Service) GetSubnetByFilter(filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
354+
return s.getSubnetByFilter(filter.ToListOpt())
355+
}
356+
357+
// GetNetworkSubnetByFilter gets a single subnet of the given network, specified by the given SubnetFilter.
358+
// It returns an ErrFilterMatch if no or multiple subnets are found.
359+
func (s *Service) GetNetworkSubnetByFilter(networkID string, filter *infrav1.SubnetFilter) (*subnets.Subnet, error) {
360+
listOpt := filter.ToListOpt()
361+
listOpt.NetworkID = networkID
362+
363+
return s.getSubnetByFilter(listOpt)
364+
}
365+
366+
// getSubnetByFilter gets a single subnet specified by the given gophercloud ListOpts.
367+
// It returns an ErrFilterMatch if no or multiple subnets are found.
368+
func (s *Service) getSubnetByFilter(listOpts subnets.ListOpts) (*subnets.Subnet, error) {
354369
// 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)
370+
if listOpts.ID != "" {
371+
subnet, err := s.client.GetSubnet(listOpts.ID)
357372
if capoerrors.IsNotFound(err) {
358373
return nil, ErrNoMatches
359374
}
360375
return subnet, err
361376
}
362377

363-
subnets, err := s.GetSubnetsByFilter(filter.ToListOpt())
378+
subnets, err := s.GetSubnetsByFilter(listOpts)
364379
if err != nil {
365380
return nil, err
366381
}

0 commit comments

Comments
 (0)