pulumi/pulumi-cdk

Unable to provision VPC

Closed this issue · 1 comments

What happened?

I am not able to provision an AWS VPC using aws-cdk

Steps to reproduce

index.ts

import * as pulumi from '@pulumi/pulumi'
import * as ec2 from 'aws-cdk-lib/aws-ec2'
import { Config } from '@pulumi/pulumi'
import { Vpc } from './vpc'

const awsConfig = new Config('aws')
const region = awsConfig.require('region')

const nomadConfig = new Config('nomad')
const cidr = nomadConfig.require('cidr')

const config = new Config()
const account = config.require('aws_account_id')

const subnets = [
  {
    name: 'public',
    type: ec2.SubnetType.PUBLIC,
    cmask: nomadConfig.requireNumber('public_subnet_cmask'),
  },
  {
    name: 'servers',
    type: ec2.SubnetType.PRIVATE_WITH_EGRESS,
    cmask: nomadConfig.requireNumber('servers_subnet_cmask'),
  },
  {
    name: 'agents',
    type: ec2.SubnetType.PRIVATE_WITH_EGRESS,
    cmask: nomadConfig.requireNumber('agents_subnet_cmask'),
  },
]

const getSubnets = (clusterName: string) => {
  const snets: ec2.SubnetConfiguration[] = []

  subnets.forEach((subnet) => {
    const { name, type, cmask } = subnet

    snets.push({
      name: `${clusterName}-nomad-${name}`,
      subnetType: type,
      cidrMask: cmask,
    })
  })

  return snets
}

export function createVpc(clusterName: string) {
  const name = `${clusterName}-vpc`

  new Vpc(
    name,
    {
      name,
      cidr,
      subnets: getSubnets(clusterName),
    },
    { props: { env: { account, region } } },
  )
}

const stack = pulumi.getStack()
const name = `sd-${stack}`

createVpc(name)

vpc.ts

import * as pulumi from '@pulumi/pulumi'
import * as pulumicdk from '@pulumi/cdk'
import * as ec2 from 'aws-cdk-lib/aws-ec2'
import { FckNatInstanceProvider } from 'cdk-fck-nat'

export interface VpcInputs {
  readonly name: string
  readonly cidr: string
  readonly subnets: ec2.SubnetConfiguration[]
}

export interface Subnet {
  readonly availabilityZone: string
  readonly subnetId: string
  readonly ipv4CidrBlock: string
  readonly routeTableId: string
}

function getSubnets(subnets: ec2.ISubnet[]): Subnet[] {
  return subnets.map((subnet) => {
    const {
      subnetId,
      availabilityZone,
      ipv4CidrBlock,
      routeTable: { routeTableId },
    } = subnet

    return { subnetId, availabilityZone, ipv4CidrBlock, routeTableId }
  })
}

export class Vpc extends pulumicdk.Stack {
  readonly id: pulumi.Output<string>
  readonly arn: pulumi.Output<string>
  readonly cidrBlock: pulumi.Output<string>
  readonly defaultNetworkAcl: pulumi.Output<string>
  readonly cidrBlockAssociations: pulumi.Output<string[]>
  readonly defaultSecurityGroup: pulumi.Output<string>
  readonly ipv6CidrBlocks: pulumi.Output<string[]>
  readonly publicSubnets: pulumi.Output<Subnet[]>
  readonly privateSubnets: pulumi.Output<Subnet[]>
  readonly isolatedSubnets: pulumi.Output<Subnet[]>
  readonly vpcAvailabilityZones: pulumi.Output<string[]>
  readonly internetGatewayId?: pulumi.Output<string | undefined>
  readonly dnsHostnamesEnabled: pulumi.Output<boolean>
  readonly dnsSupportEnabled: pulumi.Output<boolean>

  constructor(id: string, inputs: VpcInputs, options?: pulumicdk.StackOptions) {
    super(id, { ...options })

    const { name, cidr, subnets } = inputs

    const vpc = new ec2.Vpc(this, name, {
      vpcName: name,
      subnetConfiguration: subnets,
      ipAddresses: ec2.IpAddresses.cidr(cidr),
      natGatewayProvider: new FckNatInstanceProvider({
        instanceType: ec2.InstanceType.of(ec2.InstanceClass.T4G, ec2.InstanceSize.NANO),
      }),
    })

    this.id = this.asOutput(vpc.vpcId)
    this.arn = this.asOutput(vpc.vpcArn)
    this.cidrBlock = this.asOutput(vpc.vpcCidrBlock)
    this.defaultNetworkAcl = this.asOutput(vpc.vpcDefaultNetworkAcl)
    this.cidrBlockAssociations = this.asOutput(vpc.vpcCidrBlockAssociations)
    this.defaultSecurityGroup = this.asOutput(vpc.vpcDefaultSecurityGroup)
    this.ipv6CidrBlocks = this.asOutput(vpc.vpcIpv6CidrBlocks)
    this.publicSubnets = this.asOutput(getSubnets(vpc.publicSubnets))
    this.privateSubnets = this.asOutput(getSubnets(vpc.privateSubnets))
    this.isolatedSubnets = this.asOutput(getSubnets(vpc.isolatedSubnets))
    this.vpcAvailabilityZones = this.asOutput(vpc.availabilityZones)
    this.internetGatewayId = this.asOutput(vpc.internetGatewayId)
    this.dnsHostnamesEnabled = this.asOutput(vpc.dnsHostnamesEnabled)
    this.dnsSupportEnabled = this.asOutput(vpc.dnsSupportEnabled)

    this.synth()
  }
}

Pulumi.dev.yaml

config:
  aws-native:region: us-west-2
  aws:region: us-west-2
  infrastructure:aws_account_id: "your_aws_account_id"
  nomad:agents_subnet_cmask: "20"
  nomad:cidr: 10.10.0.0/16
  nomad:public_subnet_cmask: "24"
  nomad:servers_subnet_cmask: "22"

Expected Behavior

The AWS VPC should get provisioned.

Actual Behavior

Provisioning of AWS VPC fails with the following output.

    Type                                                       Name
     pulumi:pulumi:Stack                                        infrastructure-dev
 +   ├─ cdk:index:Stack                                         sd-dev-nomad
 +   │  └─ cdk:construct:Vpc                                    sd-dev-nomad/sd-dev-nomad
 +   │     └─ cdk:construct:Vpc                                 sd-dev-nomad/sd-dev-nomad/sd-dev-nomad
 +   │        ├─ cdk:construct:PublicSubnet                     sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-pub-nm
 +   │        │  ├─ aws:ec2:Eip                                 sddevnomadsddevpubnmdSubnet2EIPFEE9E5AB
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevpubnmdSubnet2RouteTableF01D2CB9
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevpubnmdSubnet2Subnet6432C5B0
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevpubnmdSubnet2RouteTableAssociationFC0FBFF9
 +   │        │  ├─ aws:ec2:Route                               sddevnomadsddevpubnmdSubnet2DefaultRoute415B30F8
 +   │        │  └─ aws:ec2:NatGateway                          sddevnomadsddevpubnmdSubnet2NATGateway2A202C5B
 +   │        ├─ cdk:construct:PrivateSubnet                    sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-ser-nm
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevsernmdSubnet1SubnetCC517582
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevsernmdSubnet1RouteTableAD2F9E46
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevsernmdSubnet1RouteTableAssociation4E958184
 +   │        │  └─ aws:ec2:Route                               sddevnomadsddevsernmdSubnet1DefaultRoute8877D9AF
 +   │        ├─ cdk:construct:PrivateSubnet                    sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-age-nm
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevagenmdSubnet3RouteTableE55F6F0E
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevagenmdSubnet3SubnetA16CBD09
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevagenmdSubnet3RouteTableAssociation53319F5C
 +   │        │  └─ aws:ec2:Route                               sddevnomadsddevagenmdSubnet3DefaultRoute06FAC36E
 +   │        ├─ cdk:construct:PrivateSubnet                    sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-ser-nm
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevsernmdSubnet3Subnet176B51D4
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevsernmdSubnet3RouteTableA5490635
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevsernmdSubnet3RouteTableAssociation0A4FD0A9
 +   │        │  └─ aws:ec2:Route                               sddevnomadsddevsernmdSubnet3DefaultRouteACCB7DAF
 +   │        ├─ cdk:construct:PublicSubnet                     sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-pub-nm
 +   │        │  ├─ aws:ec2:Eip                                 sddevnomadsddevpubnmdSubnet1EIP8D049AD3
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevpubnmdSubnet1RouteTable173B3FEB
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevpubnmdSubnet1SubnetB013F315
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevpubnmdSubnet1RouteTableAssociation8F19258C
 +   │        │  ├─ aws:ec2:Route                               sddevnomadsddevpubnmdSubnet1DefaultRouteF4632F25
 +   │        │  └─ aws:ec2:NatGateway                          sddevnomadsddevpubnmdSubnet1NATGatewayC856B197
 +   │        ├─ cdk:construct:PublicSubnet                     sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-pub-nm
 +   │        │  ├─ aws:ec2:Eip                                 sddevnomadsddevpubnmdSubnet3EIPBDCB562B
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevpubnmdSubnet3SubnetE96F6114
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevpubnmdSubnet3RouteTable6C87849F
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevpubnmdSubnet3RouteTableAssociation06FA27FA
 +   │        │  ├─ aws:ec2:Route                               sddevnomadsddevpubnmdSubnet3DefaultRoute9944437D
 +   │        │  └─ aws:ec2:NatGateway                          sddevnomadsddevpubnmdSubnet3NATGateway5A4D9C62
 +   │        ├─ cdk:construct:PrivateSubnet                    sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-ser-nm
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevsernmdSubnet2Subnet7BFF9A93
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevsernmdSubnet2RouteTable753378E5
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevsernmdSubnet2RouteTableAssociationAEFBA795
 +   │        │  └─ aws:ec2:Route                               sddevnomadsddevsernmdSubnet2DefaultRoute7E09DF3C
 +   │        ├─ cdk:construct:PrivateSubnet                    sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-age-nm
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevagenmdSubnet1Subnet89B94FE1
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevagenmdSubnet1RouteTable661A46E4
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevagenmdSubnet1RouteTableAssociation062ED5D6
 +   │        │  └─ aws:ec2:Route                               sddevnomadsddevagenmdSubnet1DefaultRouteABE14730
 +   │        ├─ cdk:construct:PrivateSubnet                    sd-dev-nomad/sd-dev-nomad/sd-dev-nomad/sd-dev-age-nm
 +   │        │  ├─ aws-native:ec2:Subnet                       sddevnomadsddevagenmdSubnet2Subnet66799117
 +   │        │  ├─ aws-native:ec2:RouteTable                   sddevnomadsddevagenmdSubnet2RouteTable77541FBB
 +   │        │  ├─ aws-native:ec2:SubnetRouteTableAssociation  sddevnomadsddevagenmdSubnet2RouteTableAssociationD498699B
 +   │        │  └─ aws:ec2:Route                               sddevnomadsddevagenmdSubnet2DefaultRoute5CF6585D
 +   │        ├─ aws-native:ec2:VPC                             sddevnomad9168BF25
 +   │        ├─ aws-native:ec2:InternetGateway                 sddevnomadIGWB9CF05EE
 +   │        └─ aws:ec2:InternetGatewayAttachment              sddevnomadVPCGW8D7DFD6F
 +   └─ aws:ec2:Tag                                             sd-dev-nomad-vpc


Diagnostics:
  pulumi:pulumi:Stack (infrastructure-dev):
    error: Error: invocation of aws-native:index:getSsmParameterString returned an error: operation error SSM: GetParameter, https response error StatusCode: 400, RequestID: fb0e830a-6a62-4911-a556-44b0fb42b683, ParameterNotFound:
        at Object.callback (/Users/munjalapatel/workspace/sd/dops-infrastructure/node_modules/@pulumi/runtime/invoke.ts:159:33)
        at Object.onReceiveStatus (/Users/munjalapatel/workspace/sd/dops-infrastructure/node_modules/@grpc/grpc-js/src/client.ts:338:26)
        at Object.onReceiveStatus (/Users/munjalapatel/workspace/sd/dops-infrastructure/node_modules/@grpc/grpc-js/src/client-interceptors.ts:426:34)
        at Object.onReceiveStatus (/Users/munjalapatel/workspace/sd/dops-infrastructure/node_modules/@grpc/grpc-js/src/client-interceptors.ts:389:48)
        at /Users/munjalapatel/workspace/sd/dops-infrastructure/node_modules/@grpc/grpc-js/src/call-stream.ts:276:24
        at processTicksAndRejections (node:internal/process/task_queues:78:11)

Output of pulumi about

CLI
Version      3.46.1
Go Version   go1.19.3
Go Compiler  gc

Plugins
NAME        VERSION
aws         5.19.0
aws         5.10.0
aws-native  0.18.0
docker      3.5.0
eks         0.42.7
kubernetes  3.22.1
kubernetes  3.20.2
nodejs      unknown
tls         4.6.1

Host
OS       darwin
Version  13.0
Arch     x86_64

This project is written in nodejs: executable='/Users/munjalapatel/.nvm/versions/node/v16.13.2/bin/node' version='v16.13.2'

Backend
Name           pulumi.com
URL            https://app.pulumi.com/sd-dev
User           sd-dev
Organizations  sd-dev

Dependencies:
NAME                              VERSION
@pulumi/pulumi                    3.46.0
@typescript-eslint/eslint-plugin  5.42.0
eslint-plugin-prettier            4.2.1
@pulumi/aws                       5.19.0
@pulumi/cdk                       0.4.0
@pulumi/eks                       0.42.7
@types/node                       18.11.9
cdk-fck-nat                       1.0.44
cz-conventional-changelog         3.3.0
@commitlint/config-conventional   17.2.0
@kubernetes/client-node           0.17.1
@pulumi/tls                       4.6.1
@types/fs-extra                   9.0.13
commitizen                        4.2.5
eslint-config-prettier            8.5.0
eslint                            8.26.0
husky                             8.0.1
@pulumi/awsx                      0.40.1
@pulumi/kubernetes                3.22.1
prettier                          2.7.1
validate-commit-email             1.0.1
@typescript-eslint/parser         5.42.0
lint-staged                       13.0.3
@commitlint/cli                   17.2.0
@pulumi/kubernetesx               0.1.6

Pulumi locates its logs in /var/folders/zv/ypxkdwcx46d9vrf40tckqq880000gn/T/ by default
warning: Failed to get information about the current stack: No current stack

Additional context

No response

Contributing

Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

I fixed it by properly bootstrapping my AWS account with aws-cdk by running

npm install -g aws-cdk
cdk bootstrap aws://<aws_account_id>/<aws_region>

** It would be great if this is documented, may save the next person some time.