private async readVpcProps()

in packages/@aws-cdk/toolkit-lib/lib/context-providers/vpcs.ts [40:186]


  private async readVpcProps(ec2: IEC2Client, vpc: Vpc, args: VpcContextQuery): Promise<VpcContextResponse> {
    const vpcId = vpc.VpcId!;

    await this.io.debug(`Describing VPC ${vpcId}`);

    const filters = { Filters: [{ Name: 'vpc-id', Values: [vpcId] }] };

    const subnetsResponse = await ec2.describeSubnets(filters);
    const listedSubnets = subnetsResponse.Subnets || [];

    const routeTablesResponse = await ec2.describeRouteTables(filters);
    const routeTables = new RouteTables(routeTablesResponse.RouteTables || []);

    // Now comes our job to separate these subnets out into AZs and subnet groups (Public, Private, Isolated)
    // We have the following attributes to go on:
    // - Type tag, we tag subnets with their type. In absence of this tag, we
    //   determine the subnet must be Public if either:
    //   a) it has the property MapPublicIpOnLaunch
    //   b) it has a route to an Internet Gateway
    //   If both of the above is false but the subnet has a route to a NAT Gateway
    //   and the destination CIDR block is "0.0.0.0/0", we assume it to be a Private subnet.
    //   Anything else is considered Isolated.
    // - Name tag, we tag subnets with their subnet group name. In absence of this tag,
    //   we use the type as the name.

    const azs = Array.from(new Set<string>(listedSubnets.map((s) => s.AvailabilityZone!)));
    azs.sort();

    const subnets: Subnet[] = listedSubnets.map((subnet) => {
      let type = getTag('aws-cdk:subnet-type', subnet.Tags);
      if (type === undefined && subnet.MapPublicIpOnLaunch) {
        type = SubnetType.Public;
      }
      if (type === undefined && routeTables.hasRouteToIgw(subnet.SubnetId)) {
        type = SubnetType.Public;
      }
      if (type === undefined && routeTables.hasRouteToNatGateway(subnet.SubnetId)) {
        type = SubnetType.Private;
      }
      if (type === undefined && routeTables.hasRouteToTransitGateway(subnet.SubnetId)) {
        type = SubnetType.Private;
      }
      if (type === undefined) {
        type = SubnetType.Isolated;
      }

      if (!isValidSubnetType(type)) {
        // eslint-disable-next-line max-len
        throw new ContextProviderError(
          `Subnet ${subnet.SubnetArn} has invalid subnet type ${type} (must be ${SubnetType.Public}, ${SubnetType.Private} or ${SubnetType.Isolated})`,
        );
      }

      if (args.subnetGroupNameTag && !getTag(args.subnetGroupNameTag, subnet.Tags)) {
        throw new ContextProviderError(
          `Invalid subnetGroupNameTag: Subnet ${subnet.SubnetArn} does not have an associated tag with Key='${args.subnetGroupNameTag}'`,
        );
      }

      const name = getTag(args.subnetGroupNameTag || 'aws-cdk:subnet-name', subnet.Tags) || type;
      const routeTableId = routeTables.routeTableIdForSubnetId(subnet.SubnetId);

      if (!routeTableId) {
        throw new ContextProviderError(
          `Subnet ${subnet.SubnetArn} does not have an associated route table (and there is no "main" table)`,
        );
      }

      return {
        az: subnet.AvailabilityZone!,
        cidr: subnet.CidrBlock!,
        type,
        name,
        subnetId: subnet.SubnetId!,
        routeTableId,
      };
    });

    let grouped: SubnetGroups;
    let assymetricSubnetGroups: VpcSubnetGroup[] | undefined;
    if (args.returnAsymmetricSubnets) {
      grouped = { azs: [], groups: [] };
      assymetricSubnetGroups = groupAsymmetricSubnets(subnets);
    } else {
      grouped = groupSubnets(subnets);
      assymetricSubnetGroups = undefined;
    }

    // Find attached+available VPN gateway for this VPC
    const vpnGatewayResponse =
      (args.returnVpnGateways ?? true)
        ? await ec2.describeVpnGateways({
          Filters: [
            {
              Name: 'attachment.vpc-id',
              Values: [vpcId],
            },
            {
              Name: 'attachment.state',
              Values: ['attached'],
            },
            {
              Name: 'state',
              Values: ['available'],
            },
          ],
        })
        : undefined;
    const vpnGatewayId =
      vpnGatewayResponse?.VpnGateways?.length === 1 ? vpnGatewayResponse.VpnGateways[0].VpnGatewayId : undefined;

    return {
      vpcId,
      vpcCidrBlock: vpc.CidrBlock!,
      ownerAccountId: vpc.OwnerId,
      availabilityZones: grouped.azs,
      isolatedSubnetIds: collapse(
        flatMap(findGroups(SubnetType.Isolated, grouped), (group) => group.subnets.map((s) => s.subnetId)),
      ),
      isolatedSubnetNames: collapse(
        flatMap(findGroups(SubnetType.Isolated, grouped), (group) => (group.name ? [group.name] : [])),
      ),
      isolatedSubnetRouteTableIds: collapse(
        flatMap(findGroups(SubnetType.Isolated, grouped), (group) => group.subnets.map((s) => s.routeTableId)),
      ),
      privateSubnetIds: collapse(
        flatMap(findGroups(SubnetType.Private, grouped), (group) => group.subnets.map((s) => s.subnetId)),
      ),
      privateSubnetNames: collapse(
        flatMap(findGroups(SubnetType.Private, grouped), (group) => (group.name ? [group.name] : [])),
      ),
      privateSubnetRouteTableIds: collapse(
        flatMap(findGroups(SubnetType.Private, grouped), (group) => group.subnets.map((s) => s.routeTableId)),
      ),
      publicSubnetIds: collapse(
        flatMap(findGroups(SubnetType.Public, grouped), (group) => group.subnets.map((s) => s.subnetId)),
      ),
      publicSubnetNames: collapse(
        flatMap(findGroups(SubnetType.Public, grouped), (group) => (group.name ? [group.name] : [])),
      ),
      publicSubnetRouteTableIds: collapse(
        flatMap(findGroups(SubnetType.Public, grouped), (group) => group.subnets.map((s) => s.routeTableId)),
      ),
      vpnGatewayId,
      subnetGroups: assymetricSubnetGroups,
    };
  }