import { Composite, mergeDefaults } from "@intentius/chant"; import { Vpc, Subnet, InternetGateway, VPCGatewayAttachment, RouteTable, EC2Route, SubnetRouteTableAssociation, EIP, NatGateway, } from "../generated"; import { Select, GetAZs } from "../intrinsics"; export interface VpcDefaultProps { cidr?: string; /** Number of availability zones (2 or 3, default: 2). */ azCount?: 2 | 3; publicSubnet1Cidr?: string; publicSubnet2Cidr?: string; privateSubnet1Cidr?: string; privateSubnet2Cidr?: string; /** Public subnet 3 CIDR (default: "10.0.32.0/20"). Used when azCount is 3. */ publicSubnet3Cidr?: string; /** Private subnet 3 CIDR (default: "10.0.160.0/20"). Used when azCount is 3. */ privateSubnet3Cidr?: string; defaults?: { vpc?: Partial[0]>; publicSubnet1?: Partial[0]>; publicSubnet2?: Partial[0]>; privateSubnet1?: Partial[0]>; privateSubnet2?: Partial[0]>; publicSubnet3?: Partial[0]>; privateSubnet3?: Partial[0]>; natGateway?: Partial[0]>; }; } export type VpcDefaultResult = { vpc: InstanceType; igw: InstanceType; igwAttachment: InstanceType; publicSubnet1: InstanceType; publicSubnet2: InstanceType; privateSubnet1: InstanceType; privateSubnet2: InstanceType; publicRouteTable: InstanceType; publicRoute: InstanceType; publicRta1: InstanceType; publicRta2: InstanceType; privateRouteTable: InstanceType; privateRoute: InstanceType; privateRta1: InstanceType; privateRta2: InstanceType; natEip: InstanceType; natGateway: InstanceType; publicSubnet3?: InstanceType; privateSubnet3?: InstanceType; publicRta3?: InstanceType; privateRta3?: InstanceType; }; export const VpcDefault = Composite((props) => { const { defaults: defs } = props; const cidr = props.cidr ?? "10.0.0.0/16"; const azCount = props.azCount ?? 2; const publicSubnet1Cidr = props.publicSubnet1Cidr ?? "10.0.0.0/20"; const publicSubnet2Cidr = props.publicSubnet2Cidr ?? "10.0.16.0/20"; const privateSubnet1Cidr = props.privateSubnet1Cidr ?? "10.0.128.0/20"; const privateSubnet2Cidr = props.privateSubnet2Cidr ?? "10.0.144.0/20"; const az1 = Select(0, GetAZs("")); const az2 = Select(1, GetAZs("")); const vpc = new Vpc(mergeDefaults({ CidrBlock: cidr, EnableDnsSupport: true, EnableDnsHostnames: true, }, defs?.vpc)); const igw = new InternetGateway({}); const igwAttachment = new VPCGatewayAttachment({ VpcId: vpc.VpcId, InternetGatewayId: igw.InternetGatewayId, }); // Public subnets const publicSubnet1 = new Subnet(mergeDefaults({ VpcId: vpc.VpcId, CidrBlock: publicSubnet1Cidr, AvailabilityZone: az1, MapPublicIpOnLaunch: true, }, defs?.publicSubnet1)); const publicSubnet2 = new Subnet(mergeDefaults({ VpcId: vpc.VpcId, CidrBlock: publicSubnet2Cidr, AvailabilityZone: az2, MapPublicIpOnLaunch: true, }, defs?.publicSubnet2)); // Private subnets const privateSubnet1 = new Subnet(mergeDefaults({ VpcId: vpc.VpcId, CidrBlock: privateSubnet1Cidr, AvailabilityZone: az1, }, defs?.privateSubnet1)); const privateSubnet2 = new Subnet(mergeDefaults({ VpcId: vpc.VpcId, CidrBlock: privateSubnet2Cidr, AvailabilityZone: az2, }, defs?.privateSubnet2)); // Public route table const publicRouteTable = new RouteTable({ VpcId: vpc.VpcId, }); const publicRoute = new EC2Route( { RouteTableId: publicRouteTable.RouteTableId, DestinationCidrBlock: "0.0.0.0/0", GatewayId: igw.InternetGatewayId, }, { DependsOn: [igwAttachment] }, ); const publicRta1 = new SubnetRouteTableAssociation({ SubnetId: publicSubnet1.SubnetId, RouteTableId: publicRouteTable.RouteTableId, }); const publicRta2 = new SubnetRouteTableAssociation({ SubnetId: publicSubnet2.SubnetId, RouteTableId: publicRouteTable.RouteTableId, }); // NAT gateway const natEip = new EIP({ Domain: "vpc", }); const natGateway = new NatGateway(mergeDefaults({ AllocationId: natEip.AllocationId, SubnetId: publicSubnet1.SubnetId, }, defs?.natGateway)); // Private route table const privateRouteTable = new RouteTable({ VpcId: vpc.VpcId, }); const privateRoute = new EC2Route({ RouteTableId: privateRouteTable.RouteTableId, DestinationCidrBlock: "0.0.0.0/0", NatGatewayId: natGateway.NatGatewayId, }); const privateRta1 = new SubnetRouteTableAssociation({ SubnetId: privateSubnet1.SubnetId, RouteTableId: privateRouteTable.RouteTableId, }); const privateRta2 = new SubnetRouteTableAssociation({ SubnetId: privateSubnet2.SubnetId, RouteTableId: privateRouteTable.RouteTableId, }); // ── AZ3 (optional) ────────────────────────────────────────────── // Ternaries keep the `new`s out of the `if` (EVL002); the AZ3 resources fold // into one return via a conditional spread. const publicSubnet3 = azCount >= 3 ? new Subnet(mergeDefaults({ VpcId: vpc.VpcId, CidrBlock: props.publicSubnet3Cidr ?? "10.0.32.0/20", AvailabilityZone: Select(2, GetAZs("")), MapPublicIpOnLaunch: true, }, defs?.publicSubnet3)) : undefined; const privateSubnet3 = azCount >= 3 ? new Subnet(mergeDefaults({ VpcId: vpc.VpcId, CidrBlock: props.privateSubnet3Cidr ?? "10.0.160.0/20", AvailabilityZone: Select(2, GetAZs("")), }, defs?.privateSubnet3)) : undefined; const publicRta3 = publicSubnet3 ? new SubnetRouteTableAssociation({ SubnetId: publicSubnet3.SubnetId, RouteTableId: publicRouteTable.RouteTableId, }) : undefined; const privateRta3 = privateSubnet3 ? new SubnetRouteTableAssociation({ SubnetId: privateSubnet3.SubnetId, RouteTableId: privateRouteTable.RouteTableId, }) : undefined; return { vpc, igw, igwAttachment, publicSubnet1, publicSubnet2, privateSubnet1, privateSubnet2, publicRouteTable, publicRoute, publicRta1, publicRta2, privateRouteTable, privateRoute, privateRta1, privateRta2, natEip, natGateway, ...(publicSubnet3 ? { publicSubnet3, privateSubnet3, publicRta3, privateRta3 } : {}), }; }, "VpcDefault");