Skip to content

Commit c70f341

Browse files
committed
edge: support creating ipv6-enabled subnets in edge zones
IPv6 subnets are not generally supported by AWS Local Zones: only certain zones support Ipv6, see [0]. Wavelength Zones is currently not supporting IPv6 subnets, see [1]. References [0] https://docs.aws.amazon.com/local-zones/latest/ug/how-local-zones-work.html#considerations [1] https://docs.aws.amazon.com/wavelength/latest/developerguide/wavelength-quotas.html#vpc-considerations
1 parent 71ad2cb commit c70f341

File tree

4 files changed

+72
-26
lines changed

4 files changed

+72
-26
lines changed

pkg/cloud/services/network/routetables.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,10 @@ func (s *Service) getRouteTableTagParams(id string, public bool, zone string) in
385385
func (s *Service) getRoutesToPublicSubnet(sn *infrav1.SubnetSpec) ([]*ec2.CreateRouteInput, error) {
386386
var routes []*ec2.CreateRouteInput
387387

388-
if sn.IsEdge() && sn.IsIPv6 {
389-
return nil, errors.Errorf("can't determine routes for unsupported ipv6 subnet in zone type %q", sn.ZoneType)
390-
}
391-
392388
if sn.IsEdgeWavelength() {
389+
if sn.IsIPv6 {
390+
return nil, errors.Errorf("can't determine routes for unsupported ipv6 subnet in zone type %q", sn.ZoneType)
391+
}
393392
if s.scope.VPC().CarrierGatewayID == nil {
394393
return routes, errors.Errorf("failed to create carrier routing table: carrier gateway for VPC %q is not present", s.scope.VPC().ID)
395394
}
@@ -411,7 +410,7 @@ func (s *Service) getRoutesToPublicSubnet(sn *infrav1.SubnetSpec) ([]*ec2.Create
411410
func (s *Service) getRoutesToPrivateSubnet(sn *infrav1.SubnetSpec) (routes []*ec2.CreateRouteInput, err error) {
412411
var natGatewayID string
413412

414-
if sn.IsEdge() && sn.IsIPv6 {
413+
if sn.IsEdgeWavelength() && sn.IsIPv6 {
415414
return nil, errors.Errorf("can't determine routes for unsupported ipv6 subnet in zone type %q", sn.ZoneType)
416415
}
417416

pkg/cloud/services/network/routetables_test.go

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,17 @@ func TestService_getRoutesForSubnet(t *testing.T) {
918918
IsPublic: true,
919919
NatGatewayID: ptr.To("nat-gw-fromZone-us-east-1a"),
920920
},
921+
{
922+
ResourceID: "subnet-az-1f-private",
923+
AvailabilityZone: "us-east-1f",
924+
IsPublic: false,
925+
},
926+
{
927+
ResourceID: "subnet-az-1f-public",
928+
AvailabilityZone: "us-east-1f",
929+
IsPublic: true,
930+
NatGatewayID: ptr.To("nat-gw-fromZone-us-east-1f"),
931+
},
921932
{
922933
ResourceID: "subnet-lz-invalid2z-private",
923934
AvailabilityZone: "us-east-2-inv-1z",
@@ -974,6 +985,20 @@ func TestService_getRoutesForSubnet(t *testing.T) {
974985
ZoneType: ptr.To(infrav1.ZoneType("wavelength-zone")),
975986
ParentZoneName: ptr.To("us-east-1a"),
976987
},
988+
{
989+
ResourceID: "subnet-lz-1f-private",
990+
AvailabilityZone: "us-east-1-atl-2a",
991+
IsPublic: false,
992+
ZoneType: ptr.To(infrav1.ZoneType("local-zone")),
993+
ParentZoneName: ptr.To("us-east-1f"),
994+
},
995+
{
996+
ResourceID: "subnet-lz-1f-public",
997+
AvailabilityZone: "us-east-1-atl-2a",
998+
IsPublic: true,
999+
ZoneType: ptr.To(infrav1.ZoneType("local-zone")),
1000+
ParentZoneName: ptr.To("us-east-1f"),
1001+
},
9771002
}
9781003

9791004
vpcName := "vpc-test-for-routes"
@@ -1126,19 +1151,28 @@ func TestService_getRoutesForSubnet(t *testing.T) {
11261151
},
11271152
wantErrMessage: `failed to create carrier routing table: carrier gateway for VPC "vpc-test-for-routes" is not present`,
11281153
},
1129-
// public subnet ipv6, unsupported
11301154
{
1131-
name: "public ipv6 subnet, local zone, must return error for unsupported ip version",
1155+
name: "public ipv6 subnet, local zone, must have ipv6 default route to igw",
11321156
inputSubnet: &infrav1.SubnetSpec{
11331157
ResourceID: "subnet-lz-1a-public",
1134-
AvailabilityZone: "us-east-1-nyc-1a",
1158+
AvailabilityZone: "us-east-1-atl-2a",
11351159
IsPublic: true,
11361160
IsIPv6: true,
11371161
ZoneType: ptr.To(infrav1.ZoneType("local-zone")),
1138-
ParentZoneName: aws.String("us-east-1a"),
1162+
ParentZoneName: aws.String("us-east-1f"),
1163+
},
1164+
want: []*ec2.CreateRouteInput{
1165+
{
1166+
DestinationCidrBlock: aws.String("0.0.0.0/0"),
1167+
GatewayId: aws.String("vpc-igw"),
1168+
},
1169+
{
1170+
DestinationIpv6CidrBlock: aws.String("::/0"),
1171+
GatewayId: aws.String("vpc-igw"),
1172+
},
11391173
},
1140-
wantErrMessage: `can't determine routes for unsupported ipv6 subnet in zone type "local-zone"`,
11411174
},
1175+
// public subnet ipv6, unsupported
11421176
{
11431177
name: "public ipv6 subnet, wavelength zone, must return error for unsupported ip version",
11441178
inputSubnet: &infrav1.SubnetSpec{
@@ -1199,9 +1233,8 @@ func TestService_getRoutesForSubnet(t *testing.T) {
11991233
},
12001234
},
12011235
},
1202-
// egress-only subnet ipv6
12031236
{
1204-
name: "egress-only ipv6 subnet, availability zone, must have ipv6 default route to egress-only gateway",
1237+
name: "private ipv6 subnet, availability zone, must have ipv6 default route to egress-only gateway",
12051238
inputSubnet: &infrav1.SubnetSpec{
12061239
ResourceID: "subnet-az-1a-private",
12071240
AvailabilityZone: "us-east-1a",
@@ -1238,19 +1271,32 @@ func TestService_getRoutesForSubnet(t *testing.T) {
12381271
},
12391272
wantErrMessage: `ipv6 block missing for ipv6 enabled subnet, can't create route for egress only internet gateway`,
12401273
},
1241-
// private subnet ipv6, unsupported
12421274
{
1243-
name: "private ipv6 subnet, local zone, must return unsupported",
1275+
name: "private ipv6 subnet, local zone, must have ipv6 default route to egress-only gateway",
12441276
inputSubnet: &infrav1.SubnetSpec{
12451277
ResourceID: "subnet-lz-1a-private",
1246-
AvailabilityZone: "us-east-1-nyc-a",
1278+
AvailabilityZone: "us-east-1-atl-2a",
12471279
IsIPv6: true,
12481280
IsPublic: false,
12491281
ZoneType: ptr.To(infrav1.ZoneType("local-zone")),
1250-
ParentZoneName: aws.String("us-east-1a"),
1282+
ParentZoneName: aws.String("us-east-1f"),
1283+
},
1284+
want: []*ec2.CreateRouteInput{
1285+
{
1286+
DestinationCidrBlock: aws.String("0.0.0.0/0"),
1287+
NatGatewayId: aws.String("nat-gw-fromZone-us-east-1f"),
1288+
},
1289+
{
1290+
DestinationIpv6CidrBlock: aws.String("64:ff9b::/96"),
1291+
NatGatewayId: aws.String("nat-gw-fromZone-us-east-1f"),
1292+
},
1293+
{
1294+
DestinationIpv6CidrBlock: aws.String("::/0"),
1295+
EgressOnlyInternetGatewayId: aws.String("vpc-eigw"),
1296+
},
12511297
},
1252-
wantErrMessage: `can't determine routes for unsupported ipv6 subnet in zone type "local-zone"`,
12531298
},
1299+
// private subnet ipv6, unsupported
12541300
{
12551301
name: "private ipv6 subnet, wavelength zone, must return unsupported",
12561302
inputSubnet: &infrav1.SubnetSpec{
@@ -1287,21 +1333,22 @@ func TestService_getRoutesForSubnet(t *testing.T) {
12871333
specOverrideNet: func() *infrav1.NetworkSpec {
12881334
net := defaultNetwork.DeepCopy()
12891335
for i := range net.Subnets {
1290-
if net.Subnets[i].AvailabilityZone == "us-east-1a" && net.Subnets[i].IsPublic {
1291-
net.Subnets[i].NatGatewayID = nil
1336+
if net.Subnets[i].IsPublic {
1337+
sn := &net.Subnets[i]
1338+
sn.NatGatewayID = nil
12921339
}
12931340
}
12941341
return net
12951342
}(),
12961343
inputSubnet: &infrav1.SubnetSpec{
12971344
ResourceID: "subnet-lz-1a-private",
12981345
AvailabilityZone: "us-east-1-nyc-1a",
1299-
IsIPv6: true,
1346+
IsIPv6: false,
13001347
IsPublic: false,
13011348
ZoneType: ptr.To(infrav1.ZoneType("local-zone")),
13021349
ParentZoneName: aws.String("us-east-1a"),
13031350
},
1304-
wantErrMessage: `can't determine routes for unsupported ipv6 subnet in zone type "local-zone"`,
1351+
wantErrMessage: `no nat gateways available in "us-east-1-nyc-1a" for private edge subnet "subnet-lz-1a-private", current state: map[]`,
13051352
},
13061353
{
13071354
name: "private ipv4 subnet, wavelength zone, must return error when invalid gateway",

pkg/cloud/services/network/subnets.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ func (s *Service) createSubnet(sn *infrav1.SubnetSpec) (*infrav1.SubnetSpec, err
543543
// https://docs.aws.amazon.com/local-zones/latest/ug/how-local-zones-work.html#considerations
544544
// Wavelength Zones is currently not supporting IPv6 subnets.
545545
// https://docs.aws.amazon.com/wavelength/latest/developerguide/wavelength-quotas.html#vpc-considerations
546-
if sn.IsIPv6 && sn.IsEdge() {
546+
if sn.IsIPv6 && sn.IsEdgeWavelength() {
547547
err := fmt.Errorf("failed to create subnet: IPv6 is not supported with zone type %q", sn.ZoneType)
548548
record.Warnf(s.scope.InfraCluster(), "FailedCreateSubnet", "Failed creating managed Subnet for edge zones: %v", err)
549549
return nil, err

pkg/cloud/services/network/subnets_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3282,16 +3282,16 @@ func TestReconcileSubnets(t *testing.T) {
32823282
errorMessageExpected: `expected the zone attributes to be populated to subnet: unable to update zone information for subnet 'subnet-private-us-east-1a' and zone 'us-east-1a'`,
32833283
},
32843284
{
3285-
name: "Managed VPC, edge zones, error when IPv6 subnet",
3285+
name: "Managed VPC, edge zones, error when IPv6 Wavelength subnet",
32863286
input: func() *ClusterScopeBuilder {
32873287
net := stubNetworkSpecWithSubnetsEdge.DeepCopy()
32883288
// Only AZ and LZ to simplify the goal
32893289
net.Subnets = infrav1.Subnets{}
32903290
for i := range stubSubnetsAvailabilityZone {
32913291
net.Subnets = append(net.Subnets, *stubSubnetsAvailabilityZone[i].DeepCopy())
32923292
}
3293-
for i := range stubSubnetsLocalZone {
3294-
lz := stubSubnetsLocalZone[i].DeepCopy()
3293+
for i := range stubSubnetsWavelengthZone {
3294+
lz := stubSubnetsWavelengthZone[i].DeepCopy()
32953295
lz.IsIPv6 = true
32963296
net.Subnets = append(net.Subnets, *lz)
32973297
}
@@ -3309,7 +3309,7 @@ func TestReconcileSubnets(t *testing.T) {
33093309
stubMockModifySubnetAttributeWithContext(m, "subnet-public-us-east-1a").After(az1Public)
33103310
},
33113311
errorExpected: true,
3312-
errorMessageExpected: `failed to create subnet: IPv6 is not supported with zone type "local-zone"`,
3312+
errorMessageExpected: `failed to create subnet: IPv6 is not supported with zone type "wavelength-zone"`,
33133313
},
33143314
{
33153315
name: "Unmanaged VPC, edge zones, existing subnets, one AZ, LZ and WL, expect one private and one public subnets from each of default zones, Local Zone, and Wavelength",

0 commit comments

Comments
 (0)