Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS-CDK: Any way to pass vpc cidr through input parameter?

I'm trying to pass vpc cidr as input parameter like below:

import { Stack, StackProps, Construct, CfnParameter } from '@aws-cdk/core';
import { Vpc, SubnetType } from '@aws-cdk/aws-ec2';

export class VpcStructureCdkStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // VPC CIDR as input parameter
    const vpcCidr = new CfnParameter(this, 'vpcCidr', {
      type: 'String',
      description: 'Please enter the IP range (CIDR notation) for this VPC',
      allowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}'
    })

    // The code that defines your stack goes here
    new Vpc(this, 'VPC', {
      maxAzs: 3,
      cidr: vpcCidr.valueAsString,
      subnetConfiguration: [
        {
          name: 'App',
          subnetType: SubnetType.PRIVATE,
          cidrMask: 24
        },
...

But getting the following error:

Error: 'cidr' property must be a concrete CIDR string, got a Token (we need to parse it for automatic subdivision)

Same error when using environment variables.

Is there any way to don't hard code vpc cidr?

like image 243
Ilgiz Nurgaliev Avatar asked Aug 31 '25 21:08

Ilgiz Nurgaliev


1 Answers

From the documentation of CDK Parameters:

A CfnParameter instance exposes its value to your AWS CDK app via a token. Like all tokens, the parameter's token is resolved at synthesis time, but it resolves to a reference to the parameter defined in the AWS CloudFormation template, which will be resolved at deploy time, rather than to a concrete value. [...] In general, we recommend against using AWS CloudFormation parameters with the AWS CDK.

Especially the last sentence is crucial.

How do you resolve it now?

Well, as you already stated: use environment variables via your programming language. I don't know about your approach with environment variables, because you didn't show it. Let me give you an example.

// file: lib/your_stack.ts

export class VpcStructureCdkStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    // reading the value from the env. 
    // Obviously, you have to set it before or pass it before you call any cdk command
    const vpcCidr = process.env.VPC_CIDR;
    new Vpc(this, 'VPC', {
      maxAzs: 3,
      // passing it
      cidr: vpcCidr,
      subnetConfiguration: [
        {
          name: 'App',
          subnetType: SubnetType.PRIVATE,
          cidrMask: 24
        },
        // ...
      ]
    }
   }
}

That's only one way of getting a configurable value into CDK though.

A better and debuggable way is to set all your dynamic/user/domain values in the Context. The best place to do for your own values is within the cdk.json. If it doesn't exist yet, just create it and don't forget to put it into Git (or your VCS of your choice).

{
  // ...
  context: {
    // ...
    "VpcCidr": "10.0.0.0/8",
  }
}

If the cdk.json approach also isn't sufficient, you have another option:

Pass it to cdk synth/deploy as an argument via -c/--context vpcCidr=10.0.0.0/8. However, that's harder to debug, because it's not versioned necessarily.

Within your stack (the best place IMHO to do it), you can call the following method to retrieve the actual value from the context:

const vpcCidr = this.node.tryGetContext("VpcCidr");

and pass it to your VPC constructor.

like image 164
mchlfchr Avatar answered Sep 03 '25 11:09

mchlfchr