Skip to content

Commit

Permalink
Add availabilityZoneCidrMask option
Browse files Browse the repository at this point in the history
Allow users to reserve more space for additional AZs to be added later.
  • Loading branch information
danielrbradley committed Nov 17, 2023
1 parent 8a3a92b commit 655eb0d
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 8 deletions.
12 changes: 12 additions & 0 deletions awsx/ec2/subnetDistributorLegacy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ describe("default subnet layout", () => {
});
}
});
it("can override az cidr mask", () => {
const vpcCidr = "10.0.0.0/16";
const result = getSubnetSpecsLegacy(
"vpcName",
vpcCidr,
["us-east-1a"],
[{ type: "Public" }],
21,
);
// Would default to /20 as that's the hard coded max size for a public subnet
expect(result[0].cidrBlock).toBe("10.0.0.0/21");
});
});

function getCidrMask(cidrBlock: string): number {
Expand Down
6 changes: 5 additions & 1 deletion awsx/ec2/subnetDistributorLegacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function getSubnetSpecsLegacy(
vpcCidr: string,
azNames: string[],
subnetInputs?: SubnetSpecInputs[],
azCidrMask?: number,
): SubnetSpec[] {
// Design:
// 1. Split the VPC CIDR block evenly between the AZs.
Expand All @@ -46,7 +47,10 @@ export function getSubnetSpecsLegacy(
// 1. Attempt to use the legacy method (cidrSubnetV4) to get the next block.
// 2. Check if the generated next block overlaps with the previous block.
// 3. If there's overlap, use the new method (nextBlock) to get the next block.
const newBitsPerAZ = Math.log2(nextPow2(azNames.length));
const newBitsPerAZ =
azCidrMask !== undefined
? azCidrMask - new ipAddress.Address4(vpcCidr).subnetMask
: Math.log2(nextPow2(azNames.length));

const azBases: string[] = [];
for (let i = 0; i < azNames.length; i++) {
Expand Down
5 changes: 5 additions & 0 deletions awsx/ec2/subnetDistributorNew.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ describe("default subnet layout", () => {
),
);
});
it("can override az cidr mask", () => {
const vpcCidr = "10.0.0.0/16";
const result = getSubnetSpecs("vpcName", vpcCidr, ["us-east-1a"], [{ type: "Public" }], 19);
expect(result[0].cidrBlock).toBe("10.0.0.0/19"); // Would default to /16 as only a single AZ and single subnet
});
});

function getCidrMask(cidrBlock: string): number {
Expand Down
4 changes: 2 additions & 2 deletions awsx/ec2/subnetDistributorNew.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ export function getSubnetSpecs(
vpcCidr: string,
azNames: string[],
subnetInputs: SubnetSpecInputs[] | undefined,
azCidrMask?: number,
): SubnetSpec[] {
const vpcNetmask = new Netmask(vpcCidr);
const newBitsPerAZ = newBits(azNames.length);
const azBitmask = vpcNetmask.bitmask + newBitsPerAZ;
const azBitmask = azCidrMask ?? vpcNetmask.bitmask + newBits(azNames.length);

const subnetSpecs = subnetInputs ?? defaultSubnetInputs(azBitmask);
if (subnetSpecs.length === 0) {
Expand Down
8 changes: 7 additions & 1 deletion awsx/ec2/vpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,13 @@ export class Vpc extends schema.Vpc<VpcData> {
if (parsedSpecs.isExplicitLayout) {
return getSubnetSpecsExplicit(name, availabilityZones, parsedSpecs.normalizedSpecs);
}
return getSubnetSpecs(name, cidrBlock, availabilityZones, parsedSpecs.normalizedSpecs);
return getSubnetSpecs(
name,
cidrBlock,
availabilityZones,
parsedSpecs.normalizedSpecs,
args.availabilityZoneCidrMask,
);
})();

validateSubnets(subnetSpecs, getOverlappingSubnets);
Expand Down
1 change: 1 addition & 0 deletions awsx/schema-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export abstract class Vpc<TData = any> extends (pulumi.ComponentResource)<TData>
}
export interface VpcArgs {
readonly assignGeneratedIpv6CidrBlock?: pulumi.Input<boolean>;
readonly availabilityZoneCidrMask?: number;
readonly availabilityZoneNames?: string[];
readonly cidrBlock?: string;
readonly enableDnsHostnames?: pulumi.Input<boolean>;
Expand Down
5 changes: 5 additions & 0 deletions awsx/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,11 @@
"type": "boolean",
"description": "Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IP addresses, or the size of the CIDR block. Default is `false`. Conflicts with `ipv6_ipam_pool_id`\n"
},
"availabilityZoneCidrMask": {
"type": "integer",
"plain": true,
"description": "The netmask for each available zone to be aligned to. This is optional, the default value is inferred based on an even distribution of available space from the VPC's CIDR block after being divided evenly by the number of availability zones."
},
"availabilityZoneNames": {
"type": "array",
"items": {
Expand Down
9 changes: 5 additions & 4 deletions schemagen/pkg/gen/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ func vpcResource(awsSpec schema.PackageSpec) schema.ResourceSpec {
},
"numberOfAvailabilityZones": {
Description: fmt.Sprintf("A number of availability zones to which the subnets defined in %v will be deployed. Optional, defaults to the first 3 AZs in the current region.", subnetSpecs),
TypeSpec: schema.TypeSpec{
Type: "integer",
Plain: true,
},
TypeSpec: plainInt(),
},
"availabilityZoneCidrMask": {
Description: "The netmask for each available zone to be aligned to. This is optional, the default value is inferred based on an even distribution of available space from the VPC's CIDR block after being divided evenly by the number of availability zones.",
TypeSpec: plainInt(),
},
"cidrBlock": {
Description: "The CIDR block for the VPC. Optional. Defaults to 10.0.0.0/16.",
Expand Down

0 comments on commit 655eb0d

Please sign in to comment.