in packages/@aws-cdk/aws-ec2/lib/vpc.ts [1284:1408]
constructor(scope: Construct, id: string, props: VpcProps = {}) {
super(scope, id);
const stack = Stack.of(this);
// Can't have enabledDnsHostnames without enableDnsSupport
if (props.enableDnsHostnames && !props.enableDnsSupport) {
throw new Error('To use DNS Hostnames, DNS Support must be enabled, however, it was explicitly disabled.');
}
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)');
}
this.networkBuilder = new NetworkBuilder(cidrBlock);
this.dnsHostnamesEnabled = props.enableDnsHostnames == null ? true : props.enableDnsHostnames;
this.dnsSupportEnabled = props.enableDnsSupport == null ? true : props.enableDnsSupport;
const instanceTenancy = props.defaultInstanceTenancy || 'default';
this.internetConnectivityEstablished = this._internetConnectivityEstablished;
// Define a VPC using the provided CIDR range
this.resource = new CfnVPC(this, 'Resource', {
cidrBlock,
enableDnsHostnames: this.dnsHostnamesEnabled,
enableDnsSupport: this.dnsSupportEnabled,
instanceTenancy,
});
this.vpcDefaultNetworkAcl = this.resource.attrDefaultNetworkAcl;
this.vpcCidrBlockAssociations = this.resource.attrCidrBlockAssociations;
this.vpcCidrBlock = this.resource.attrCidrBlock;
this.vpcDefaultSecurityGroup = this.resource.attrDefaultSecurityGroup;
this.vpcIpv6CidrBlocks = this.resource.attrIpv6CidrBlocks;
Tags.of(this).add(NAME_TAG, props.vpcName || this.node.path);
this.availabilityZones = stack.availabilityZones;
const maxAZs = props.maxAzs ?? 3;
this.availabilityZones = this.availabilityZones.slice(0, maxAZs);
this.vpcId = this.resource.ref;
this.vpcArn = Arn.format({
service: 'ec2',
resource: 'vpc',
resourceName: this.vpcId,
}, stack);
const defaultSubnet = props.natGateways === 0 ? Vpc.DEFAULT_SUBNETS_NO_NAT : Vpc.DEFAULT_SUBNETS;
this.subnetConfiguration = ifUndefined(props.subnetConfiguration, defaultSubnet);
const natGatewayPlacement = props.natGatewaySubnets || { subnetType: SubnetType.PUBLIC };
const natGatewayCount = determineNatGatewayCount(props.natGateways, this.subnetConfiguration, this.availabilityZones.length);
// subnetConfiguration must be set before calling createSubnets
this.createSubnets();
const allowOutbound = this.subnetConfiguration.filter(
subnet => (subnet.subnetType !== SubnetType.PRIVATE_ISOLATED)).length > 0;
// Create an Internet Gateway and attach it if necessary
if (allowOutbound) {
const igw = new CfnInternetGateway(this, 'IGW', {
});
this.internetGatewayId = igw.ref;
this._internetConnectivityEstablished.add(igw);
const att = new CfnVPCGatewayAttachment(this, 'VPCGW', {
internetGatewayId: igw.ref,
vpcId: this.resource.ref,
});
(this.publicSubnets as PublicSubnet[]).forEach(publicSubnet => {
publicSubnet.addDefaultInternetRoute(igw.ref, att);
});
// if gateways are needed create them
if (natGatewayCount > 0) {
const provider = props.natGatewayProvider || NatProvider.gateway();
this.createNatGateways(provider, natGatewayCount, natGatewayPlacement);
}
}
if (props.vpnGateway && this.publicSubnets.length === 0 && this.privateSubnets.length === 0 && this.isolatedSubnets.length === 0) {
throw new Error('Can not enable the VPN gateway while the VPC has no subnets at all');
}
if ((props.vpnConnections || props.vpnGatewayAsn) && props.vpnGateway === false) {
throw new Error('Cannot specify `vpnConnections` or `vpnGatewayAsn` when `vpnGateway` is set to false.');
}
if (props.vpnGateway || props.vpnConnections || props.vpnGatewayAsn) {
this.enableVpnGateway({
amazonSideAsn: props.vpnGatewayAsn,
type: VpnConnectionType.IPSEC_1,
vpnRoutePropagation: props.vpnRoutePropagation,
});
const vpnConnections = props.vpnConnections || {};
for (const [connectionId, connection] of Object.entries(vpnConnections)) {
this.addVpnConnection(connectionId, connection);
}
}
// Allow creation of gateway endpoints on VPC instantiation as those can be
// immediately functional without further configuration. This is not the case
// for interface endpoints where the security group must be configured.
if (props.gatewayEndpoints) {
const gatewayEndpoints = props.gatewayEndpoints || {};
for (const [endpointId, endpoint] of Object.entries(gatewayEndpoints)) {
this.addGatewayEndpoint(endpointId, endpoint);
}
}
// Add flow logs to the VPC
if (props.flowLogs) {
const flowLogs = props.flowLogs || {};
for (const [flowLogId, flowLog] of Object.entries(flowLogs)) {
this.addFlowLog(flowLogId, flowLog);
}
}
}