Skip to content

Commit 4634da0

Browse files
committed
🌱 refact/network/routetable: review route discover/creation flow
The flow for route discover and creation is reviewed to provide flexibility of route entry inputs for routes discovered by each subnet. This change is a subset of Wavelength zone (#4874) feature which will introduce requirements when discovering gateways of public and private subnets. The refact should not change the existing flow.
1 parent 6afad25 commit 4634da0

File tree

2 files changed

+301
-45
lines changed

2 files changed

+301
-45
lines changed

pkg/cloud/services/network/routetables.go

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -60,30 +60,10 @@ func (s *Service) reconcileRouteTables() error {
6060
for i := range subnets {
6161
sn := &subnets[i]
6262
// We need to compile the minimum routes for this subnet first, so we can compare it or create them.
63-
var routes []*ec2.Route
64-
if sn.IsPublic {
65-
if s.scope.VPC().InternetGatewayID == nil {
66-
return errors.Errorf("failed to create routing tables: internet gateway for %q is nil", s.scope.VPC().ID)
67-
}
68-
routes = append(routes, s.getGatewayPublicRoute())
69-
if sn.IsIPv6 {
70-
routes = append(routes, s.getGatewayPublicIPv6Route())
71-
}
72-
} else {
73-
natGatewayID, err := s.getNatGatewayForSubnet(sn)
74-
if err != nil {
75-
return err
76-
}
77-
routes = append(routes, s.getNatGatewayPrivateRoute(natGatewayID))
78-
if sn.IsIPv6 {
79-
if !s.scope.VPC().IsIPv6Enabled() {
80-
// Safety net because EgressOnlyInternetGateway needs the ID from the ipv6 block.
81-
// if, for whatever reason by this point that is not available, we don't want to
82-
// panic because of a nil pointer access. This should never occur. Famous last words though.
83-
return errors.Errorf("ipv6 block missing for ipv6 enabled subnet, can't create egress only internet gateway")
84-
}
85-
routes = append(routes, s.getEgressOnlyInternetGateway())
86-
}
63+
routes, err := s.getRoutesForSubnet(sn)
64+
if err != nil {
65+
record.Warnf(s.scope.InfraCluster(), "FailedRouteTableRoutes", "Failed to get routes for managed RouteTable for subnet %s: %v", sn.ID, err)
66+
return errors.Wrapf(err, "failed to discover routes on route table %s", sn.ID)
8767
}
8868

8969
if rt, ok := subnetRouteMap[sn.GetResourceID()]; ok {
@@ -145,7 +125,7 @@ func (s *Service) reconcileRouteTables() error {
145125
return nil
146126
}
147127

148-
func (s *Service) fixMismatchedRouting(specRoute *ec2.Route, currentRoute *ec2.Route, rt *ec2.RouteTable) error {
128+
func (s *Service) fixMismatchedRouting(specRoute *ec2.CreateRouteInput, currentRoute *ec2.Route, rt *ec2.RouteTable) error {
149129
var input *ec2.ReplaceRouteInput
150130
if specRoute.DestinationCidrBlock != nil {
151131
if (currentRoute.DestinationCidrBlock != nil &&
@@ -271,7 +251,7 @@ func (s *Service) describeVpcRouteTables() ([]*ec2.RouteTable, error) {
271251
return out.RouteTables, nil
272252
}
273253

274-
func (s *Service) createRouteTableWithRoutes(routes []*ec2.Route, isPublic bool, zone string) (*infrav1.RouteTable, error) {
254+
func (s *Service) createRouteTableWithRoutes(routes []*ec2.CreateRouteInput, isPublic bool, zone string) (*infrav1.RouteTable, error) {
275255
out, err := s.EC2Client.CreateRouteTableWithContext(context.TODO(), &ec2.CreateRouteTableInput{
276256
VpcId: aws.String(s.scope.VPC().ID),
277257
TagSpecifications: []*ec2.TagSpecification{
@@ -287,17 +267,8 @@ func (s *Service) createRouteTableWithRoutes(routes []*ec2.Route, isPublic bool,
287267
for i := range routes {
288268
route := routes[i]
289269
if err := wait.WaitForWithRetryable(wait.NewBackoff(), func() (bool, error) {
290-
if _, err := s.EC2Client.CreateRouteWithContext(context.TODO(), &ec2.CreateRouteInput{
291-
RouteTableId: out.RouteTable.RouteTableId,
292-
DestinationCidrBlock: route.DestinationCidrBlock,
293-
DestinationIpv6CidrBlock: route.DestinationIpv6CidrBlock,
294-
EgressOnlyInternetGatewayId: route.EgressOnlyInternetGatewayId,
295-
GatewayId: route.GatewayId,
296-
InstanceId: route.InstanceId,
297-
NatGatewayId: route.NatGatewayId,
298-
NetworkInterfaceId: route.NetworkInterfaceId,
299-
VpcPeeringConnectionId: route.VpcPeeringConnectionId,
300-
}); err != nil {
270+
route.RouteTableId = out.RouteTable.RouteTableId
271+
if _, err := s.EC2Client.CreateRouteWithContext(context.TODO(), route); err != nil {
301272
return false, err
302273
}
303274
return true, nil
@@ -329,29 +300,29 @@ func (s *Service) associateRouteTable(rt *infrav1.RouteTable, subnetID string) e
329300
return nil
330301
}
331302

332-
func (s *Service) getNatGatewayPrivateRoute(natGatewayID string) *ec2.Route {
333-
return &ec2.Route{
303+
func (s *Service) getNatGatewayPrivateRoute(natGatewayID string) *ec2.CreateRouteInput {
304+
return &ec2.CreateRouteInput{
334305
NatGatewayId: aws.String(natGatewayID),
335306
DestinationCidrBlock: aws.String(services.AnyIPv4CidrBlock),
336307
}
337308
}
338309

339-
func (s *Service) getEgressOnlyInternetGateway() *ec2.Route {
340-
return &ec2.Route{
310+
func (s *Service) getEgressOnlyInternetGateway() *ec2.CreateRouteInput {
311+
return &ec2.CreateRouteInput{
341312
DestinationIpv6CidrBlock: aws.String(services.AnyIPv6CidrBlock),
342313
EgressOnlyInternetGatewayId: s.scope.VPC().IPv6.EgressOnlyInternetGatewayID,
343314
}
344315
}
345316

346-
func (s *Service) getGatewayPublicRoute() *ec2.Route {
347-
return &ec2.Route{
317+
func (s *Service) getGatewayPublicRoute() *ec2.CreateRouteInput {
318+
return &ec2.CreateRouteInput{
348319
DestinationCidrBlock: aws.String(services.AnyIPv4CidrBlock),
349320
GatewayId: aws.String(*s.scope.VPC().InternetGatewayID),
350321
}
351322
}
352323

353-
func (s *Service) getGatewayPublicIPv6Route() *ec2.Route {
354-
return &ec2.Route{
324+
func (s *Service) getGatewayPublicIPv6Route() *ec2.CreateRouteInput {
325+
return &ec2.CreateRouteInput{
355326
DestinationIpv6CidrBlock: aws.String(services.AnyIPv6CidrBlock),
356327
GatewayId: aws.String(*s.scope.VPC().InternetGatewayID),
357328
}
@@ -382,3 +353,45 @@ func (s *Service) getRouteTableTagParams(id string, public bool, zone string) in
382353
Additional: additionalTags,
383354
}
384355
}
356+
357+
func (s *Service) getRoutesToPublicSubnet(sn *infrav1.SubnetSpec) ([]*ec2.CreateRouteInput, error) {
358+
var routes []*ec2.CreateRouteInput
359+
360+
if s.scope.VPC().InternetGatewayID == nil {
361+
return routes, errors.Errorf("failed to create routing tables: internet gateway for %q is nil", s.scope.VPC().ID)
362+
}
363+
364+
routes = append(routes, s.getGatewayPublicRoute())
365+
if sn.IsIPv6 {
366+
routes = append(routes, s.getGatewayPublicIPv6Route())
367+
}
368+
369+
return routes, nil
370+
}
371+
372+
func (s *Service) getRoutesToPrivateSubnet(sn *infrav1.SubnetSpec) (routes []*ec2.CreateRouteInput, err error) {
373+
natGatewayID, err := s.getNatGatewayForSubnet(sn)
374+
if err != nil {
375+
return routes, err
376+
}
377+
378+
routes = append(routes, s.getNatGatewayPrivateRoute(natGatewayID))
379+
if sn.IsIPv6 {
380+
if !s.scope.VPC().IsIPv6Enabled() {
381+
// Safety net because EgressOnlyInternetGateway needs the ID from the ipv6 block.
382+
// if, for whatever reason by this point that is not available, we don't want to
383+
// panic because of a nil pointer access. This should never occur. Famous last words though.
384+
return routes, errors.Errorf("ipv6 block missing for ipv6 enabled subnet, can't create route for egress only internet gateway")
385+
}
386+
routes = append(routes, s.getEgressOnlyInternetGateway())
387+
}
388+
389+
return routes, nil
390+
}
391+
392+
func (s *Service) getRoutesForSubnet(sn *infrav1.SubnetSpec) ([]*ec2.CreateRouteInput, error) {
393+
if sn.IsPublic {
394+
return s.getRoutesToPublicSubnet(sn)
395+
}
396+
return s.getRoutesToPrivateSubnet(sn)
397+
}

0 commit comments

Comments
 (0)