Skip to content

Commit 994a8f4

Browse files
Feat outposts (#964)
* initial commit for subnets * Added custom route targets * fixed vpx cfn route logic * fixed merge conflict * Fixed config naming * fixed AZ references and ts errors * fixed az reference * small changes * Added logging for subnets * tweak en.ts descriptions * prettier Co-authored-by: hickeydh-aws <hickeydh@amazon.com> Co-authored-by: Brian969 <56414362+Brian969@users.noreply.github.com>
1 parent 9e34d5c commit 994a8f4

File tree

6 files changed

+98
-16
lines changed

6 files changed

+98
-16
lines changed

src/core/runtime/src/get-baseline-step.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,15 @@ async function assignDynamicCidrs(input: AssignCidrInput) {
241241
}
242242

243243
if (existingSubnet['account-ou-key'] === `organizational-unit/${ouKey}`) {
244+
const az = subnetDef.az;
244245
await updateSubnetCidr(subnetCidrPoolAssignedTable, uuidv4(), {
245246
accountOuKey: `account/${accountKey}`,
246247
cidr: existingSubnet.cidr,
247248
pool: existingSubnet['sub-pool'],
248249
region: vpcConfig.region,
249250
vpc: vpcConfig.name,
250251
subnet: subnetConfig.name,
251-
az: subnetDef.az,
252+
az,
252253
accountKey,
253254
});
254255
}
@@ -351,14 +352,15 @@ async function assignDynamicCidrs(input: AssignCidrInput) {
351352
);
352353
}
353354
console.log(`Dynamic CIDR for "${subnetConfig.name}.${subnetDef.az}" is "${subnetCidr}"`);
355+
const az = subnetDef.az;
354356
await updateSubnetCidr(subnetCidrPoolAssignedTable, uuidv4(), {
355357
accountOuKey: `account/${accountKey}`,
356358
cidr: subnetCidr,
357359
pool: subnetDef.cidr.pool,
358360
region: vpcConfig.region,
359361
vpc: vpcConfig.name,
360362
subnet: subnetConfig.name,
361-
az: subnetDef.az,
363+
az,
362364
accountKey,
363365
});
364366
} else {

src/deployments/cdk/src/common/vpc.ts

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ export class Vpc extends cdk.Construct implements constructs.Vpc {
254254
: ec2.DefaultInstanceTenancy.DEFAULT,
255255
});
256256
this.vpcId = vpcObj.ref;
257+
const lgw = props.vpcProps.vpcConfig['lgw-route-table-id'];
258+
if (lgw) {
259+
new ec2.CfnLocalGatewayRouteTableVPCAssociation(this, `${vpcName}-${lgw}`, {
260+
localGatewayRouteTableId: lgw,
261+
vpcId: this.vpcId,
262+
});
263+
}
257264

258265
const extendVpc: ec2.CfnVPCCidrBlock[] = [];
259266
this.cidr2Block.forEach((additionalCidr, index) => {
@@ -325,6 +332,7 @@ export class Vpc extends cdk.Construct implements constructs.Vpc {
325332
const subnetsConfig = props.vpcProps.vpcConfig.subnets || [];
326333
for (const subnetConfig of subnetsConfig) {
327334
const subnetName = subnetConfig.name;
335+
console.log(`Deploying Subnet ${subnetName}`);
328336
for (const subnetDefinition of subnetConfig.definitions.values()) {
329337
if (subnetDefinition.disabled) {
330338
continue;
@@ -345,26 +353,35 @@ export class Vpc extends cdk.Construct implements constructs.Vpc {
345353
subnetCidr = subnetDefinition.cidr?.value?.toCidrString()!;
346354
}
347355
if (!subnetCidr) {
348-
console.warn(`Subnet with name "${subnetName}" and AZ "${subnetDefinition.az}" does not have a CIDR block`);
356+
console.log(`Subnet with name "${subnetName}" and AZ "${subnetDefinition.az}" does not have a CIDR block`);
349357
continue;
350358
}
351-
359+
let availabilityZone = subnetDefinition.az;
360+
if (availabilityZone.length === 1) {
361+
availabilityZone = `${this.region}${subnetDefinition.az}`;
362+
}
352363
const subnetId = `${subnetName}_${vpcName}_az${subnetDefinition.az}`;
364+
console.log(`Creating subnet ${subnetId}`);
353365
const subnet = new ec2.CfnSubnet(this, subnetId, {
354366
cidrBlock: subnetCidr,
355367
vpcId: vpcObj.ref,
356-
availabilityZone: `${this.region}${subnetDefinition.az}`,
368+
availabilityZone,
369+
outpostArn: subnetDefinition['outpost-arn'],
357370
});
371+
if (availabilityZone.length > 1) {
372+
console.log(subnet);
373+
}
358374
for (const extensions of extendVpc) {
359375
subnet.addDependsOn(extensions);
360376
}
377+
361378
this.azSubnets.push({
362379
subnet,
363380
subnetName,
364381
id: subnet.ref,
365382
name: subnetName,
366-
az: subnetDefinition.az,
367383
cidrBlock: subnetCidr,
384+
az: subnetDefinition.az,
368385
});
369386

370387
// Attach Subnet to Route-Table
@@ -686,11 +703,25 @@ export class Vpc extends cdk.Construct implements constructs.Vpc {
686703
};
687704
new ec2.CfnRoute(this, constructName, routeParams);
688705
continue;
706+
} else if (route.target === 'customer') {
707+
if (!route.type || !route['target-id']) {
708+
console.warn(
709+
`type and target-id are required when using customer as target for route for the route ${route.name}`,
710+
);
711+
continue;
712+
}
713+
const constructName = `${routeTableName}_${route.type}_${route['target-id']}`;
714+
const routeParams: ec2.CfnRouteProps = {
715+
routeTableId: routeTableObj,
716+
[route.type]: route['target-id'],
717+
destinationCidrBlock: route.destination as string,
718+
};
719+
new ec2.CfnRoute(this, constructName, routeParams);
720+
continue;
689721
} else {
690722
// Need to add for different Routes
691723
continue;
692724
}
693-
694725
const params: ec2.CfnRouteProps = {
695726
routeTableId: routeTableObj,
696727
destinationCidrBlock: route.destination as string,

src/lib/common-outputs/src/elb.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const LoadBalancerEndpointOutputFinder = createStructuredOutputFinder(Loa
7979
accountKey: string;
8080
region: string;
8181
vpcName: string;
82-
az: string;
82+
az: string | undefined;
8383
elbAccountKey?: string;
8484
}) =>
8585
finder.tryFindOne({

src/lib/config-i18n/src/en.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ translate(c.SubnetDefinitionConfig, {
460460
fields: {
461461
az: {
462462
title: 'Availability Zone',
463-
description: 'Availability Zone to create the subnet in',
463+
description: 'Availability Zone to create the subnet.',
464464
},
465465
cidr: {
466466
title: 'Subnet CIDR Definition',
@@ -475,6 +475,10 @@ translate(c.SubnetDefinitionConfig, {
475475
description:
476476
'Define the subnet in the Accelerator to reserve the address space, but do not create it at this time. Used to define a 3 AZ config, but deploy a 2 AZ config.',
477477
},
478+
'outpost-arn': {
479+
title: 'Outpost ARN',
480+
description: 'The ARN of the Outpost to create the subnet.',
481+
},
478482
},
479483
});
480484

@@ -588,27 +592,38 @@ translate(c.PcxRouteConfigType, {
588592

589593
translate(c.RouteConfig, {
590594
title: 'Route Config',
591-
description: 'The configuration routes that are added to the route tables',
595+
description: 'The configuration for routes to be added to a route table',
592596
fields: {
593597
destination: {
594598
title: '',
595-
description: 'Destination IP subnet or VPC Gateway endpoint',
599+
description: 'Destination CIDR or either "s3", "DynamoDB" for a VPC Gateway endpoint.',
596600
},
597601
target: {
598602
title: '',
599-
description: 'Next-hop address for the route',
603+
description:
604+
'The target type for the next-hop, includes TGW, IGW, VGW, pcx, NATGW_subnet_azX, NFW_subnet_azX, s3, DynamoDB, and customer. If target is set to customer, the target-id and type are required.',
600605
},
601606
name: {
602607
title: '',
603-
description: 'Name of the route',
608+
description: 'Route table name.',
604609
},
605610
az: {
606611
title: '',
607-
description: 'Availability Zone',
612+
description: 'Availability Zone (only used when targeting EC2 based firewall appliances)',
608613
},
609614
port: {
610615
title: '',
611-
description: 'When routing traffic to ports of 3rd party virtual appliances',
616+
description:
617+
'Subnet name containing the targeted virtual appliance port (only used when targeting EC2 based firewall appliances)',
618+
},
619+
'target-id': {
620+
title: 'Target ID',
621+
description: 'The ID of the specified target, i.e. igw-12345678901234567.',
622+
},
623+
type: {
624+
title: 'Target Type',
625+
description:
626+
'The target type for the next hop, when created external to the ASEA. Valid values: "egressOnlyInternetGatewayId", "gatewayId", "instanceId", "localGatewayId","natGatewayId", "networkInterfaceId", "transitGatewayId", "vpcEndpointId", "vpcPeeringConnectionId".',
612627
},
613628
},
614629
});
@@ -1032,6 +1047,10 @@ translate(c.VpcConfigType, {
10321047
title: '',
10331048
description: 'Use central endpoints for this VPC',
10341049
},
1050+
'lgw-route-table-id': {
1051+
title: 'Local Gateway Route Table ID',
1052+
description: 'The route table ID to associate a VPC to a local zone.',
1053+
},
10351054
},
10361055
});
10371056

src/lib/config-i18n/src/fr.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ translate(c.SubnetDefinitionConfig, {
388388
title: '',
389389
description: '',
390390
},
391+
'outpost-arn': {
392+
title: '',
393+
},
391394
},
392395
});
393396

@@ -520,6 +523,12 @@ translate(c.RouteConfig, {
520523
title: '',
521524
description: '',
522525
},
526+
'target-id': {
527+
title: '',
528+
},
529+
type: {
530+
title: '',
531+
},
523532
},
524533
});
525534

@@ -935,6 +944,9 @@ translate(c.VpcConfigType, {
935944
title: '',
936945
description: '',
937946
},
947+
'lgw-route-table-id': {
948+
title: '',
949+
},
938950
},
939951
});
940952

src/lib/config/src/config.v2.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ export const CidrConfigType = t.interface({
9999
export type CidrConfig = t.TypeOf<typeof CidrConfigType>;
100100

101101
export const SubnetDefinitionConfig = t.interface({
102-
az: t.availabilityZone,
102+
az: t.union([t.availabilityZone, t.nonEmptyString]),
103+
'outpost-arn': t.optional(t.nonEmptyString),
103104
cidr: t.optional(CidrConfigType),
104105
'route-table': t.nonEmptyString,
105106
disabled: t.defaulted(t.boolean, false),
@@ -152,12 +153,28 @@ export const AccountVpcConfigType = t.interface({
152153

153154
export type AccountVpcConfigType = t.TypeOf<typeof AccountVpcConfigType>;
154155

156+
export const RouteTargetType = t.enums('RouteTargetType', [
157+
'egressOnlyInternetGatewayId',
158+
'gatewayId',
159+
'instanceId',
160+
'localGatewayId',
161+
'natGatewayId',
162+
'networkInterfaceId',
163+
'transitGatewayId',
164+
'vpcEndpointId',
165+
'vpcPeeringConnectionId',
166+
]);
167+
168+
export type RouteTargetType = t.TypeOf<typeof RouteTargetType>;
169+
155170
export const RouteConfig = t.interface({
156171
destination: t.union([t.nonEmptyString, PcxRouteConfigType]), // TODO Can be string or destination in another account
157172
target: t.nonEmptyString,
158173
name: t.optional(t.nonEmptyString),
159174
az: t.optional(t.nonEmptyString),
160175
port: t.optional(t.nonEmptyString),
176+
type: t.optional(RouteTargetType),
177+
'target-id': t.optional(t.nonEmptyString),
161178
});
162179

163180
export const RouteTableConfigType = t.interface({
@@ -308,6 +325,7 @@ export const VpcConfigType = t.interface({
308325
'security-groups': t.optional(t.array(SecurityGroupConfigType)),
309326
zones: t.optional(ZoneNamesConfigType),
310327
'central-endpoint': t.defaulted(t.boolean, false),
328+
'lgw-route-table-id': t.optional(t.nonEmptyString),
311329
});
312330

313331
export type VpcConfig = t.TypeOf<typeof VpcConfigType>;

0 commit comments

Comments
 (0)