10

I have been attempting to use the AWS CDK to programmatically build a CloudFormation stack template, but am having trouble with using CfnParameters to parameterize the template.

When I write a template manually in json/yaml, I declare ParameterGroups with nested Parameters lists, as well as defining the individual parameters including Type, Description, AllowedPattern, etc. Then in the definition of my resources, I can reference those parameters via Ref values, eg

"CidrBlock": {
  "Ref": "MyVpcCidr"
}

My question is how do I use this feature via the CDK, defining a parameter and referencing it later in the template?

I have tried the following using software.amazon.awscdk.core.CfnParameter, but receive an error

final CfnParameter myVpcCidrParameter =
    CfnParameter.Builder.create(this, "MyVpcCidr")
        .type("String")
        .description("The CIDR block for the VPC")
        .build();

final Vpc vpc =
    Vpc.Builder.create(this, "vpc")
        .cidr(myVpcCidrParameter.getValueAsString()) // <-- error on this line
        .enableDnsSupport(true)
        .enableDnsHostnames(true)
        .build();
...

The error states

JsiiException: 'cidr' property must be a concrete CIDR string, got a Token

which seems reasonable because myVpcCidrParameter.getValueAsString() returns "${Token[TOKEN.10]}".

However I don't see any other method on CfnParameter or the Vpc.Builder to allow me to use a parameter reference to specify the property value as a reference to my parameter.

What is the proper way to use the CDK to build a template with parameters and resources defined using those parameters?

wutch
  • 395
  • 2
  • 12

1 Answers1

1

Your use of CfnParameters looks correct however there are known issues when used with resources such as:

  • VPCs
  • Load balancers
  • Load balancer targets

Here's an explanation of why this occurs.

A better alternative would be to use CDK context

Here's your example updated using context:

final String myVpcCidr = (String)this.getNode().tryGetContext("myVpcCidr");

final Vpc vpc =
    Vpc.Builder.create(this, "vpc")
        .cidr(myVpcCidr) // <-- Use context value
        .enableDnsSupport(true)
        .enableDnsHostnames(true)
        .build();

Similar to parameters, you can provide the context key/value via CLI:

cdk synth --context myVpcCidr=value MyStack

Context values can also be provided to your AWS CDK app in 5 other ways:

  • Automatically from the current AWS account.
  • In the project's cdk.context.json file.
  • In the context key of the project's cdk.json file.
  • In the context key of your ~/.cdk.json file.
  • In your AWS CDK app using the construct.node.setContext() method.

See the CDK context docs for more info.

Ryan
  • 1,482
  • 2
  • 11
  • 19