How to import an Existing VPC in AWS CDK

avatar

Borislav Hadzhiev

Sat Apr 24 20214 min read

banner

Photo by Cody Board

Updated on Sat Apr 24 2021

To import an existing, external VPC in CDK, we have to use the `fromLookup` static method on the Vpc construct.

Table of Contents #

  1. Importing an Existing VPC in AWS CDK
  2. Importing an Existing VPC by Name in CDK
  3. Imported VPC Values get Cached in Context
  4. Importing the Default VPC in CDK
  5. Importing an Existing VPC by Tags in CDK
  6. Importing an Existing VPC by VPC ID
  7. Caveats when Importing Existing VPCs in CDK

Importing an Existing VPC in AWS CDK #

In order to import an existing VPC in CDK we have to use the fromLookup static method on the Vpc construct.

We have to explicitly set the stack environment (account, region), otherwise CDK doesn't know where to perform the lookup.
bin/cdk-starter.ts
const app = new cdk.App();

new MyCdkStack(app, 'my-cdk-stack', {
  // ๐Ÿ‘‡ explicitly set region and account
  env: {
    region: 'us-east-1',
    account: '123456789',
  },
});

Importing an Existing VPC by Name in AWS CDK #

The code for this article is available on GitHub

For the purposes of the demo I'll import an existing VPC and create a Lambda function inside the VPC network.

lib/cdk-starter-stack.ts
import * as ec2 from '@aws-cdk/aws-ec2';
import * as lambda from '@aws-cdk/aws-lambda';
import {NodejsFunction} from '@aws-cdk/aws-lambda-nodejs';
import * as cdk from '@aws-cdk/core';
import * as path from 'path';

export class MyCdkStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    // ๐Ÿ‘‡ import VPC by Name
    const myVpc = ec2.Vpc.fromLookup(this, 'external-vpc', {
      vpcName: 'YOUR_VPC_NAME',
    });

    console.log('vpcId ๐Ÿ‘‰ ', myVpc.vpcId);
    console.log('vpcCidrBlock ๐Ÿ‘‰ ', myVpc.vpcCidrBlock);

    const myFunction = new NodejsFunction(this, 'my-function', {
      // ๐Ÿ‘‡ place Lambda in VPC
      vpc: myVpc,
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: 'main',
      entry: path.join(__dirname, `/../src/my-lambda/index.js`),
      allowPublicSubnet: true,
    });
  }
}

In the code snippet we've used the fromLookup static method on the VPC construct to import an existing VPC by name.

The other common lookup options options are:

  • isDefault - a boolean that matches the default VPC
  • tags - a map of tag key-value pairs
  • vpcId - a string that matches the ID of the VPC

Let's take a look at the output of the cdk synth command of the stack:

synth imported vpc

We can see that initially we got some placeholder values, until the VPC lookup was completed and the real values were fetched.

If I cdk deploy the stack, the Lambda console shows that the function has been provisioned inside of the imported VPC:

lambda in VPC

Imported VPC Values get Cached in Context #

When I ran the cdk deploy command, it didn't show the placeholder VPC values this time, because the VPC values (id, cidr, subnet groups, etc) are now cached in the cdk.context.json file in the root directory of the CDK app.

cdk deploy vpc

Now that the VPC values are cached in the cdk.context.json file, no lookups will be performed for future deployments.

However, if we change some of the VPC's configuration we might want to force a new lookup to reflect the changes in the CDK stack.

In order to refresh the VPC value and force a new lookup we have to first run the cdk context command, to get the number or key of the cached VPC value from context:

shell
npx cdk context

The output will show a table with the context number, key and value:

cdk context output

Now that we've got the number that corresponds to the VPC values, we can clear the cache with the --reset flag:

shell
cdk context --reset KEY_OR_NUMBER

After we've cleared the cache, the next time we run cdk synth the VPC lookup will be executed.

Importing the Default VPC in AWS CDK #

In order to import the default VPC we have to set the isDefault lookup option to true in the call to the fromLookup static method of the VPC construct.

lib/cdk-starter-stack.ts
const defaultVpc = ec2.Vpc.fromLookup(this, 'default-vpc-id', {
  isDefault: true,
});

Since there's only 1 default VPC per account, per region, this is enough for CDK to track it down, assuming that we've explicitly set the stack environment (account, region) when instantiating the Stack:

bin/cdk-starter.ts
const app = new cdk.App();

new MyCdkStack(app, 'my-cdk-stack', {
  env: {
    region: 'us-east-1',
    account: '123456789',
  },
});

Importing an Existing VPC by Tags in AWS CDK #

To import an existing VPC by tags we have to set the tags lookup option to a map of key-value pairs in the call to the fromLookup static method of the VPC construct.

For example if I add a tag to my VPC with a Key of app and a Value of ecommerce:

vpc tags

I can then import the VPC using the tag mapping like so:

lib/cdk-starter-stack.ts
const myVpc = ec2.Vpc.fromLookup(this, 'by-tags-id', {
  tags: {
    app: 'ecommerce',
  },
});

Importing an Existing VPC by VPC ID #

To import an existing VPC by VPC ID we have to set the vpcId lookup option when invoking fromLookup:

lib/cdk-starter-stack.ts
const myVpc = ec2.Vpc.fromLookup(this, 'external-vpc', {
  vpcId: 'vpc-091234581ee4994647',
});

Caveats when Importing Existing VPCs in CDK #

Some things to note when importing existing VPC into CDK stacks:

  1. We have to explicitly set the stack's environment (account, region), otherwise CDK doesn't know where to perform the VPC lookup

  2. We aren't allowed to update the imported VPC

  3. After the first successful VPC lookup the values are cached in the cdk.context.json file and are reused for subsequent deployments. If we update the VPC's configuration, we have to clear the cache by passing the --reset flag to the cdk context command:

shell
npx cdk context --reset CONTEXT_NUMBER_OR_KEY

Further Reading #

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee