@@ -84,6 +84,11 @@ func (s *Service) reconcileRouteTables() error {
84
84
}
85
85
}
86
86
87
+ // Make sure desired routes are created in the route table.
88
+ if err := s .fixMissingRoutes (routes , rt .Routes , rt ); err != nil {
89
+ return err
90
+ }
91
+
87
92
// Make sure tags are up-to-date.
88
93
if err := wait .WaitForWithRetryable (wait .NewBackoff (), func () (bool , error ) {
89
94
buildParams := s .getRouteTableTagParams (aws .ToString (rt .RouteTableId ), sn .IsPublic , sn .AvailabilityZone )
@@ -145,7 +150,8 @@ func (s *Service) fixMismatchedRouting(specRoute *ec2.CreateRouteInput, currentR
145
150
if (currentRoute .DestinationIpv6CidrBlock != nil &&
146
151
aws .ToString (currentRoute .DestinationIpv6CidrBlock ) == aws .ToString (specRoute .DestinationIpv6CidrBlock )) &&
147
152
((currentRoute .GatewayId != nil && aws .ToString (currentRoute .GatewayId ) != aws .ToString (specRoute .GatewayId )) ||
148
- (currentRoute .NatGatewayId != nil && aws .ToString (currentRoute .NatGatewayId ) != aws .ToString (specRoute .NatGatewayId ))) {
153
+ (currentRoute .NatGatewayId != nil && aws .ToString (currentRoute .NatGatewayId ) != aws .ToString (specRoute .NatGatewayId )) ||
154
+ (currentRoute .EgressOnlyInternetGatewayId != nil && aws .ToString (currentRoute .EgressOnlyInternetGatewayId ) != aws .ToString (specRoute .EgressOnlyInternetGatewayId ))) {
149
155
input = & ec2.ReplaceRouteInput {
150
156
RouteTableId : rt .RouteTableId ,
151
157
DestinationIpv6CidrBlock : specRoute .DestinationIpv6CidrBlock ,
@@ -170,6 +176,36 @@ func (s *Service) fixMismatchedRouting(specRoute *ec2.CreateRouteInput, currentR
170
176
return nil
171
177
}
172
178
179
+ func (s * Service ) fixMissingRoutes (specRoutes []* ec2.CreateRouteInput , currentRoutes []types.Route , rt types.RouteTable ) error {
180
+ // Routes destination cidr blocks must be unique within a routing table.
181
+ // Each route can define either an IPv4 or IPv6 CIDR, but not both.
182
+ currRouteMap := make (map [string ]types.Route )
183
+ for _ , route := range currentRoutes {
184
+ if route .DestinationCidrBlock != nil {
185
+ currRouteMap [aws .ToString (route .DestinationCidrBlock )] = route
186
+ }
187
+ if route .DestinationIpv6CidrBlock != nil {
188
+ currRouteMap [aws .ToString (route .DestinationIpv6CidrBlock )] = route
189
+ }
190
+ }
191
+
192
+ routesToAdd := make ([]* ec2.CreateRouteInput , 0 )
193
+ for _ , route := range specRoutes {
194
+ var dest string
195
+ if route .DestinationCidrBlock != nil {
196
+ dest = aws .ToString (route .DestinationCidrBlock )
197
+ }
198
+ if route .DestinationIpv6CidrBlock != nil {
199
+ dest = aws .ToString (route .DestinationIpv6CidrBlock )
200
+ }
201
+ if _ , ok := currRouteMap [dest ]; ! ok {
202
+ routesToAdd = append (routesToAdd , route )
203
+ }
204
+ }
205
+
206
+ return s .createRoutesForRouteTable (routesToAdd , rt .RouteTableId )
207
+ }
208
+
173
209
func (s * Service ) describeVpcRouteTablesBySubnet () (map [string ]types.RouteTable , error ) {
174
210
rts , err := s .describeVpcRouteTables ()
175
211
if err != nil {
@@ -274,28 +310,34 @@ func (s *Service) createRouteTableWithRoutes(routes []*ec2.CreateRouteInput, isP
274
310
record .Eventf (s .scope .InfraCluster (), "SuccessfulCreateRouteTable" , "Created managed RouteTable %q" , aws .ToString (out .RouteTable .RouteTableId ))
275
311
s .scope .Info ("Created route table" , "route-table-id" , * out .RouteTable .RouteTableId )
276
312
313
+ if err := s .createRoutesForRouteTable (routes , out .RouteTable .RouteTableId ); err != nil {
314
+ if cleanupErr := s .deleteRouteTable (* out .RouteTable ); cleanupErr != nil {
315
+ record .Warnf (s .scope .InfraCluster (), "FailedDeleteRouteTable" , "Failed to delete managed RouteTable %q: %v" , aws .ToString (out .RouteTable .RouteTableId ), cleanupErr )
316
+ }
317
+ return nil , err
318
+ }
319
+
320
+ return & infrav1.RouteTable {
321
+ ID : * out .RouteTable .RouteTableId ,
322
+ }, nil
323
+ }
324
+
325
+ func (s * Service ) createRoutesForRouteTable (routes []* ec2.CreateRouteInput , routeTableID * string ) error {
277
326
for i := range routes {
278
327
route := routes [i ]
279
328
if err := wait .WaitForWithRetryable (wait .NewBackoff (), func () (bool , error ) {
280
- route .RouteTableId = out . RouteTable . RouteTableId
329
+ route .RouteTableId = routeTableID
281
330
if _ , err := s .EC2Client .CreateRoute (context .TODO (), route ); err != nil {
282
331
return false , err
283
332
}
284
333
return true , nil
285
334
}, awserrors .RouteTableNotFound , awserrors .NATGatewayNotFound , awserrors .GatewayNotFound ); err != nil {
286
- record .Warnf (s .scope .InfraCluster (), "FailedCreateRoute" , "Failed to create route %s for RouteTable %q: %v" , route , aws .ToString (out .RouteTable .RouteTableId ), err )
287
- errDel := s .deleteRouteTable (* out .RouteTable )
288
- if errDel != nil {
289
- record .Warnf (s .scope .InfraCluster (), "FailedDeleteRouteTable" , "Failed to delete managed RouteTable %q: %v" , aws .ToString (out .RouteTable .RouteTableId ), errDel )
290
- }
291
- return nil , errors .Wrapf (err , "failed to create route in route table %q: %v" , aws .ToString (out .RouteTable .RouteTableId ), route )
335
+ record .Warnf (s .scope .InfraCluster (), "FailedCreateRoute" , "Failed to create route %s for RouteTable %q: %v" , route , aws .ToString (routeTableID ), err )
336
+ return errors .Wrapf (err , "failed to create route in route table %q: %v" , aws .ToString (routeTableID ), route )
292
337
}
293
- record .Eventf (s .scope .InfraCluster (), "SuccessfulCreateRoute" , "Created route %s for RouteTable %q" , route , aws .ToString (out . RouteTable . RouteTableId ))
338
+ record .Eventf (s .scope .InfraCluster (), "SuccessfulCreateRoute" , "Created route %s for RouteTable %q" , route , aws .ToString (routeTableID ))
294
339
}
295
-
296
- return & infrav1.RouteTable {
297
- ID : * out .RouteTable .RouteTableId ,
298
- }, nil
340
+ return nil
299
341
}
300
342
301
343
func (s * Service ) associateRouteTable (rt * infrav1.RouteTable , subnetID string ) error {
0 commit comments