How to add if statements to your CloudFormation CDK templates

I recently came upon a situation where I was building an application usingĀ AWS CDK (Which is a package that allows you to write Typescript code that compiles to a CloudFormation template) and I needed to reference a bucket in the template, but the bucket name would be different in Beta versus in Prod. I naively thought I could just do this:

// Don't use this, this code doesn't work
const stage = new cdk.Parameter(this, "Stage", {
  default: "beta",
  type: "String"
}).value.toString();

const bucketName = stage === "prod" ? "app-prod-bucket" : "app-beta-bucket";
const Bucket = s3.Bucket.import(this, "AppBucket", {
  bucketName
});

The mistake I made is forgetting that CDK is compiled into CloudFormation templates, so when I run cdk synthesize it takes this code, evaluates it, sees that the variable stage is currently not set (because it’s provided at runtime), and compiles the string “app-beta-bucket” into the template.

Then when running this compiled template it doesn’t matter what the parameter Stage is, that if statement has already been compiled out and it’s always going to set the bucket name to “app-beta-bucket”.

To fix this you need to use CloudFormation Conditional Statements, like so:

const stage = new cdk.Parameter(this, "Stage", {
  default: "beta",
  type: "String"
}).value.toString();

new cdk.Condition(this, "UseProdBuckets", {
  expression: cdk.Fn.conditionEquals(stage, "prod")
});

const bucketName = cdk.Fn.conditionIf(
  "UseProdBuckets",
  "app-prod-bucket",
  "app-beta-bucket"
);

const Bucket = s3.Bucket.import(this, "AppBucket", {
  bucketName
});

Now your if statement will be compiled into the template and the bucket name will change depending on the value of the “Stage” parameter