Skip to content

Commit

Permalink
feat(aws-ec2): Control over VPC AZs
Browse files Browse the repository at this point in the history
With this change, the `Vpc` construct gains a new constructor prop,
`availabilityZones`, which gives more control over AZs than the existing
`maxAzs` prop.

closes aws#5847
  • Loading branch information
philipmw committed Jun 1, 2022
1 parent 96d54df commit 12b5e9d
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
24 changes: 21 additions & 3 deletions packages/@aws-cdk/aws-ec2/lib/vpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,10 +841,21 @@ export interface VpcProps {
* only 2 AZs, so to use more than 2 AZs, be sure to specify the account and
* region on your stack.
*
* Specify this option only if you do not specify `availabilityZones`.
*
* @default 3
*/
readonly maxAzs?: number;

/**
* Availability zones this VPC spans.
*
* This option overrides `maxAzs`.
*
* @default (a subset of) AZs of the stack
*/
readonly availabilityZones?: string[];

/**
* The number of NAT Gateways/Instances to create.
*
Expand Down Expand Up @@ -1289,6 +1300,10 @@ export class Vpc extends VpcBase {
throw new Error('To use DNS Hostnames, DNS Support must be enabled, however, it was explicitly disabled.');
}

if (props.availabilityZones && props.maxAzs) {
throw new Error('Vpc supports either specific \'availabilityZones\' or \'maxAzs\' number, but not both.');
}

const cidrBlock = ifUndefined(props.cidr, Vpc.DEFAULT_CIDR_RANGE);
if (Token.isUnresolved(cidrBlock)) {
throw new Error('\'cidr\' property must be a concrete CIDR string, got a Token (we need to parse it for automatic subdivision)');
Expand Down Expand Up @@ -1317,10 +1332,13 @@ export class Vpc extends VpcBase {

Tags.of(this).add(NAME_TAG, props.vpcName || this.node.path);

this.availabilityZones = stack.availabilityZones;
if (props.availabilityZones) {
this.availabilityZones = props.availabilityZones;
} else {
const maxAZs = props.maxAzs ?? 3;
this.availabilityZones = stack.availabilityZones.slice(0, maxAZs);
}

const maxAZs = props.maxAzs ?? 3;
this.availabilityZones = this.availabilityZones.slice(0, maxAZs);

this.vpcId = this.resource.ref;
this.vpcArn = Arn.format({
Expand Down
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-ec2/test/vpc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,30 @@ describe('vpc', () => {
});

});

test('with availabilityZones and maxAzs set, throws error', () => {
const stack = getTestStack();
expect(() => {
new Vpc(stack, 'VPC', {
availabilityZones: stack.availabilityZones,
maxAzs: 1,
});
}).toThrow(/Vpc supports either specific 'availabilityZones' or 'maxAzs'/);
});

test('with availabilityZones set', () => {
const stack = getTestStack();
new Vpc(stack, 'VPC', {
availabilityZones: [`${stack.region}b`],
});
Template.fromStack(stack).resourceCountIs('AWS::EC2::Subnet', 2);
for (let i = 1; i < 2; i++) {
Template.fromStack(stack).hasResourceProperties('AWS::EC2::Subnet', {
AvailabilityZone: `${stack.region}b`,
});
}
});

test('with natGateway set to 1', () => {
const stack = getTestStack();
new Vpc(stack, 'VPC', {
Expand Down

0 comments on commit 12b5e9d

Please sign in to comment.