@@ -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 &&
@@ -280,7 +260,7 @@ func (s *Service) describeVpcRouteTables() ([]*ec2.RouteTable, error) {
280260 return out .RouteTables , nil
281261}
282262
283- func (s * Service ) createRouteTableWithRoutes (routes []* ec2.Route , isPublic bool , zone string ) (* infrav1.RouteTable , error ) {
263+ func (s * Service ) createRouteTableWithRoutes (routes []* ec2.CreateRouteInput , isPublic bool , zone string ) (* infrav1.RouteTable , error ) {
284264 out , err := s .EC2Client .CreateRouteTableWithContext (context .TODO (), & ec2.CreateRouteTableInput {
285265 VpcId : aws .String (s .scope .VPC ().ID ),
286266 TagSpecifications : []* ec2.TagSpecification {
@@ -296,17 +276,8 @@ func (s *Service) createRouteTableWithRoutes(routes []*ec2.Route, isPublic bool,
296276 for i := range routes {
297277 route := routes [i ]
298278 if err := wait .WaitForWithRetryable (wait .NewBackoff (), func () (bool , error ) {
299- if _ , err := s .EC2Client .CreateRouteWithContext (context .TODO (), & ec2.CreateRouteInput {
300- RouteTableId : out .RouteTable .RouteTableId ,
301- DestinationCidrBlock : route .DestinationCidrBlock ,
302- DestinationIpv6CidrBlock : route .DestinationIpv6CidrBlock ,
303- EgressOnlyInternetGatewayId : route .EgressOnlyInternetGatewayId ,
304- GatewayId : route .GatewayId ,
305- InstanceId : route .InstanceId ,
306- NatGatewayId : route .NatGatewayId ,
307- NetworkInterfaceId : route .NetworkInterfaceId ,
308- VpcPeeringConnectionId : route .VpcPeeringConnectionId ,
309- }); err != nil {
279+ route .RouteTableId = out .RouteTable .RouteTableId
280+ if _ , err := s .EC2Client .CreateRouteWithContext (context .TODO (), route ); err != nil {
310281 return false , err
311282 }
312283 return true , nil
@@ -341,29 +312,29 @@ func (s *Service) associateRouteTable(rt *infrav1.RouteTable, subnetID string) e
341312 return nil
342313}
343314
344- func (s * Service ) getNatGatewayPrivateRoute (natGatewayID string ) * ec2.Route {
345- return & ec2.Route {
315+ func (s * Service ) getNatGatewayPrivateRoute (natGatewayID string ) * ec2.CreateRouteInput {
316+ return & ec2.CreateRouteInput {
346317 NatGatewayId : aws .String (natGatewayID ),
347318 DestinationCidrBlock : aws .String (services .AnyIPv4CidrBlock ),
348319 }
349320}
350321
351- func (s * Service ) getEgressOnlyInternetGateway () * ec2.Route {
352- return & ec2.Route {
322+ func (s * Service ) getEgressOnlyInternetGateway () * ec2.CreateRouteInput {
323+ return & ec2.CreateRouteInput {
353324 DestinationIpv6CidrBlock : aws .String (services .AnyIPv6CidrBlock ),
354325 EgressOnlyInternetGatewayId : s .scope .VPC ().IPv6 .EgressOnlyInternetGatewayID ,
355326 }
356327}
357328
358- func (s * Service ) getGatewayPublicRoute () * ec2.Route {
359- return & ec2.Route {
329+ func (s * Service ) getGatewayPublicRoute () * ec2.CreateRouteInput {
330+ return & ec2.CreateRouteInput {
360331 DestinationCidrBlock : aws .String (services .AnyIPv4CidrBlock ),
361332 GatewayId : aws .String (* s .scope .VPC ().InternetGatewayID ),
362333 }
363334}
364335
365- func (s * Service ) getGatewayPublicIPv6Route () * ec2.Route {
366- return & ec2.Route {
336+ func (s * Service ) getGatewayPublicIPv6Route () * ec2.CreateRouteInput {
337+ return & ec2.CreateRouteInput {
367338 DestinationIpv6CidrBlock : aws .String (services .AnyIPv6CidrBlock ),
368339 GatewayId : aws .String (* s .scope .VPC ().InternetGatewayID ),
369340 }
@@ -394,3 +365,45 @@ func (s *Service) getRouteTableTagParams(id string, public bool, zone string) in
394365 Additional : additionalTags ,
395366 }
396367}
368+
369+ func (s * Service ) getRoutesToPublicSubnet (sn * infrav1.SubnetSpec ) ([]* ec2.CreateRouteInput , error ) {
370+ var routes []* ec2.CreateRouteInput
371+
372+ if s .scope .VPC ().InternetGatewayID == nil {
373+ return routes , errors .Errorf ("failed to create routing tables: internet gateway for %q is nil" , s .scope .VPC ().ID )
374+ }
375+
376+ routes = append (routes , s .getGatewayPublicRoute ())
377+ if sn .IsIPv6 {
378+ routes = append (routes , s .getGatewayPublicIPv6Route ())
379+ }
380+
381+ return routes , nil
382+ }
383+
384+ func (s * Service ) getRoutesToPrivateSubnet (sn * infrav1.SubnetSpec ) (routes []* ec2.CreateRouteInput , err error ) {
385+ natGatewayID , err := s .getNatGatewayForSubnet (sn )
386+ if err != nil {
387+ return routes , err
388+ }
389+
390+ routes = append (routes , s .getNatGatewayPrivateRoute (natGatewayID ))
391+ if sn .IsIPv6 {
392+ if ! s .scope .VPC ().IsIPv6Enabled () {
393+ // Safety net because EgressOnlyInternetGateway needs the ID from the ipv6 block.
394+ // if, for whatever reason by this point that is not available, we don't want to
395+ // panic because of a nil pointer access. This should never occur. Famous last words though.
396+ return routes , errors .Errorf ("ipv6 block missing for ipv6 enabled subnet, can't create route for egress only internet gateway" )
397+ }
398+ routes = append (routes , s .getEgressOnlyInternetGateway ())
399+ }
400+
401+ return routes , nil
402+ }
403+
404+ func (s * Service ) getRoutesForSubnet (sn * infrav1.SubnetSpec ) ([]* ec2.CreateRouteInput , error ) {
405+ if sn .IsPublic {
406+ return s .getRoutesToPublicSubnet (sn )
407+ }
408+ return s .getRoutesToPrivateSubnet (sn )
409+ }
0 commit comments