@@ -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