Reputation: 125
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?
Upvotes: 4
Views: 3770
Reputation: 509
I did similar thing by reading external config file.
import * as cdk from "@aws-cdk/core";
import { Vpc, SubnetType } from "@aws-cdk/aws-ec2";
import fs = require("fs");
export class ExampleStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const configJson = fs.readFileSync(
"config/" + this.account + ".json",
"utf8"
);
let config = JSON.parse(configJson);
const vpc = Vpc.fromLookup(this, "vpc", {
vpcId: config.vpcId
});
}
}
const app = new cdk.App();
new ExampleStack(app, 'ExampleStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
}});
and have a file location at ./config/123123123.json
{
"vpcId" : "123123123"
}
Upvotes: 0
Reputation: 1473
Either create your own VPC either import the existing one. For the second solution there is fromLookup()
, which will find proper VPC (by tags, name or other VPCLookupOptions
) together with it's CIDR:
https://docs.aws.amazon.com/cdk/api/latest/typescript/api/aws-ec2/vpc.html#aws_ec2_Vpc_fromLookup
Upvotes: 1
Reputation: 4278
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.
Upvotes: 7