Skip to content

Commit a7d8138

Browse files
authored
Merge pull request #2338 from simonostendorf/feat/reconcile-pre-existing-router
✨ feat: reconcile pre-existing router
2 parents aec70ed + 86f864b commit a7d8138

File tree

3 files changed

+164
-4
lines changed

3 files changed

+164
-4
lines changed

Diff for: controllers/openstackcluster_controller.go

+26-2
Original file line numberDiff line numberDiff line change
@@ -695,10 +695,10 @@ func reconcileNetworkComponents(scope *scope.WithLogger, cluster *clusterv1.Clus
695695
}
696696

697697
// reconcilePreExistingNetworkComponents reconciles the cluster network status when the cluster is
698-
// using pre-existing networks and subnets which are not provisioned by the
698+
// using pre-existing networks, subnets and router which are not provisioned by the
699699
// cluster controller.
700700
func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster) error {
701-
scope.Logger().V(4).Info("No need to reconcile network, searching network and subnet instead")
701+
scope.Logger().V(4).Info("No need to reconcile network, searching network, subnet and router instead")
702702

703703
if openStackCluster.Status.Network == nil {
704704
openStackCluster.Status.Network = &infrav1.NetworkStatusWithSubnets{}
@@ -745,9 +745,33 @@ func reconcilePreExistingNetworkComponents(scope *scope.WithLogger, networkingSe
745745
setClusterNetwork(openStackCluster, network)
746746
}
747747

748+
if openStackCluster.Spec.Router != nil {
749+
router, err := networkingService.GetRouterByParam(openStackCluster.Spec.Router)
750+
if err != nil {
751+
handleUpdateOSCError(openStackCluster, fmt.Errorf("failed to find router: %w", err), false)
752+
return fmt.Errorf("error fetching cluster router: %w", err)
753+
}
754+
755+
scope.Logger().V(4).Info("Found pre-existing router", "id", router.ID, "name", router.Name)
756+
757+
routerIPs := []string{}
758+
for _, ip := range router.GatewayInfo.ExternalFixedIPs {
759+
routerIPs = append(routerIPs, ip.IPAddress)
760+
}
761+
762+
openStackCluster.Status.Router = &infrav1.Router{
763+
Name: router.Name,
764+
ID: router.ID,
765+
Tags: router.Tags,
766+
IPs: routerIPs,
767+
}
768+
}
769+
748770
return nil
749771
}
750772

773+
// reconcileProvisionedNetworkComponents reconciles the cluster network status when the cluster is
774+
// using networks, subnets and router provisioned by the cluster controller.
751775
func reconcileProvisionedNetworkComponents(networkingService *networking.Service, openStackCluster *infrav1.OpenStackCluster, clusterResourceName string) error {
752776
err := networkingService.ReconcileNetwork(openStackCluster, clusterResourceName)
753777
if err != nil {

Diff for: controllers/openstackcluster_controller_test.go

+136
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"reflect"
2323
"testing"
2424

25+
"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/layer3/routers"
2526
"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks"
2627
"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets"
2728
. "github.com/onsi/ginkgo/v2" //nolint:revive
@@ -38,6 +39,7 @@ import (
3839
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3940

4041
infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
42+
"sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/services/networking"
4143
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
4244
)
4345

@@ -431,6 +433,140 @@ var _ = Describe("OpenStackCluster controller", func() {
431433
Expect(err).To(BeNil())
432434
Expect(testCluster.Status.Network.ID).To(Equal(clusterNetworkID))
433435
})
436+
437+
It("reconcile pre-existing network components by id", func() {
438+
const clusterNetworkID = "6c90b532-7ba0-418a-a276-5ae55060b5b0"
439+
const clusterSubnetID = "cad5a91a-36de-4388-823b-b0cc82cadfdc"
440+
const clusterRouterID = "e2407c18-c4e7-4d3d-befa-8eec5d8756f2"
441+
442+
testCluster.SetName("pre-existing-network-components-by-id")
443+
testCluster.Spec = infrav1.OpenStackClusterSpec{
444+
Network: &infrav1.NetworkParam{
445+
ID: ptr.To(clusterNetworkID),
446+
},
447+
Subnets: []infrav1.SubnetParam{
448+
{
449+
ID: ptr.To(clusterSubnetID),
450+
},
451+
},
452+
ManagedSubnets: []infrav1.SubnetSpec{},
453+
Router: &infrav1.RouterParam{
454+
ID: ptr.To(clusterRouterID),
455+
},
456+
}
457+
err := k8sClient.Create(ctx, testCluster)
458+
Expect(err).To(BeNil())
459+
err = k8sClient.Create(ctx, capiCluster)
460+
Expect(err).To(BeNil())
461+
462+
log := GinkgoLogr
463+
clientScope, err := mockScopeFactory.NewClientScopeFromObject(ctx, k8sClient, nil, log, testCluster)
464+
Expect(err).To(BeNil())
465+
scope := scope.NewWithLogger(clientScope, log)
466+
467+
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
468+
469+
networkClientRecorder.GetSubnet(clusterSubnetID).Return(&subnets.Subnet{
470+
ID: clusterSubnetID,
471+
CIDR: "192.168.0.0/24",
472+
NetworkID: clusterNetworkID,
473+
}, nil)
474+
475+
networkClientRecorder.GetNetwork(clusterNetworkID).Return(&networks.Network{
476+
ID: clusterNetworkID,
477+
}, nil)
478+
479+
networkClientRecorder.GetRouter(clusterRouterID).Return(&routers.Router{
480+
ID: clusterRouterID,
481+
}, nil)
482+
483+
networkingService, err := networking.NewService(scope)
484+
Expect(err).To(BeNil())
485+
486+
err = reconcilePreExistingNetworkComponents(scope, networkingService, testCluster)
487+
Expect(err).To(BeNil())
488+
Expect(testCluster.Status.Network.ID).To(Equal(clusterNetworkID))
489+
Expect(testCluster.Status.Network.Subnets[0].ID).To(Equal(clusterSubnetID))
490+
Expect(testCluster.Status.Router.ID).To(Equal(clusterRouterID))
491+
})
492+
493+
It("reconcile pre-existing network components by name", func() {
494+
const clusterNetworkID = "6c90b532-7ba0-418a-a276-5ae55060b5b0"
495+
const clusterNetworkName = "capo"
496+
const clusterSubnetID = "cad5a91a-36de-4388-823b-b0cc82cadfdc"
497+
const clusterSubnetName = "capo"
498+
const clusterRouterID = "e2407c18-c4e7-4d3d-befa-8eec5d8756f2"
499+
const clusterRouterName = "capo"
500+
501+
testCluster.SetName("pre-existing-network-components-by-id")
502+
testCluster.Spec = infrav1.OpenStackClusterSpec{
503+
Network: &infrav1.NetworkParam{
504+
Filter: &infrav1.NetworkFilter{
505+
Name: clusterNetworkName,
506+
},
507+
},
508+
Subnets: []infrav1.SubnetParam{
509+
{
510+
Filter: &infrav1.SubnetFilter{
511+
Name: clusterSubnetName,
512+
},
513+
},
514+
},
515+
ManagedSubnets: []infrav1.SubnetSpec{},
516+
Router: &infrav1.RouterParam{
517+
Filter: &infrav1.RouterFilter{
518+
Name: clusterRouterName,
519+
},
520+
},
521+
}
522+
err := k8sClient.Create(ctx, testCluster)
523+
Expect(err).To(BeNil())
524+
err = k8sClient.Create(ctx, capiCluster)
525+
Expect(err).To(BeNil())
526+
527+
log := GinkgoLogr
528+
clientScope, err := mockScopeFactory.NewClientScopeFromObject(ctx, k8sClient, nil, log, testCluster)
529+
Expect(err).To(BeNil())
530+
scope := scope.NewWithLogger(clientScope, log)
531+
532+
networkClientRecorder := mockScopeFactory.NetworkClient.EXPECT()
533+
534+
networkClientRecorder.ListNetwork(networks.ListOpts{
535+
Name: clusterNetworkName,
536+
}).Return([]networks.Network{
537+
{
538+
ID: clusterNetworkID,
539+
},
540+
}, nil)
541+
542+
networkClientRecorder.ListSubnet(subnets.ListOpts{
543+
Name: clusterSubnetName,
544+
NetworkID: clusterNetworkID,
545+
}).Return([]subnets.Subnet{
546+
{
547+
ID: clusterSubnetID,
548+
CIDR: "192.168.0.0/24",
549+
NetworkID: clusterNetworkID,
550+
},
551+
}, nil)
552+
553+
networkClientRecorder.ListRouter(routers.ListOpts{
554+
Name: clusterRouterName,
555+
}).Return([]routers.Router{
556+
{
557+
ID: clusterRouterID,
558+
},
559+
}, nil)
560+
561+
networkingService, err := networking.NewService(scope)
562+
Expect(err).To(BeNil())
563+
564+
err = reconcilePreExistingNetworkComponents(scope, networkingService, testCluster)
565+
Expect(err).To(BeNil())
566+
Expect(testCluster.Status.Network.ID).To(Equal(clusterNetworkID))
567+
Expect(testCluster.Status.Network.Subnets[0].ID).To(Equal(clusterSubnetID))
568+
Expect(testCluster.Status.Router.ID).To(Equal(clusterRouterID))
569+
})
434570
})
435571

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

Diff for: pkg/cloud/services/networking/router.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ func (s *Service) getExternallyManagedRouter(openStackCluster *infrav1.OpenStack
157157
if openStackCluster.Status.Router != nil {
158158
return s.client.GetRouter(openStackCluster.Status.Router.ID)
159159
}
160-
return s.getRouterByParam(openStackCluster.Spec.Router)
160+
return s.GetRouterByParam(openStackCluster.Spec.Router)
161161
}
162162

163-
func (s *Service) getRouterByParam(routerParam *infrav1.RouterParam) (*routers.Router, error) {
163+
func (s *Service) GetRouterByParam(routerParam *infrav1.RouterParam) (*routers.Router, error) {
164164
if routerParam.ID != nil {
165165
return s.client.GetRouter(*routerParam.ID)
166166
}

0 commit comments

Comments
 (0)