Example of iterating output

I have two TerraformStack classes - one sets up the base infrastructure (e.g. VPC) and a second that deploys an application on top of it. In the base stack, I am using the vpc module to create the VPC and subnets. I would like to refer to the subnet IDs of the VPC in my application stack.

The vpc module has an output named public_subnets, whose description is “List of IDs of public subnets”.

But the following doesn’t work:

// base.ts
export default class BaseStack extends TerraformStack {

    public publicSubnets: string[] | undefined;
    constructor(scope: Construct, name: string) {
        const vpc = new Vpc(this, `${name}-ue1-main`, {
            ...
            publicSubnets: ['10.0.0.0/24', '10.0.1.0/24','10.0.2.0/24' ],
          })
    }
    this.publicSubnets = vpc.publicSubnetsOutput;
}


// main.ts
...
new AppStack(app, "test", {
  subnets: base.publicSubnets,
})

This is because vpc.publicSubnetsOutput is a string, but BaseStack.publicSubnets is a string[].

Note that there’s a vpc.publicSubnets property, but that gives me the input value (['10.0.0.0/24', '10.0.1.0/24','10.0.2.0/24']) instead of the subnet IDs.

In the documentation, it says that:

Outputs return an HCL expression representing the underlying Terraform resource, so the return type must always be string . When TerraformOutput is any other type than string, you must add a typecast to compile the application (e.g. mod.numberOutput as number ). If a module returns a list, you must use an escape hatch to access items or loop over it. Refer to the Resources page for more information about how to use escape hatches.

But I am not sure how to use the escape hatch to iterate over an output using for_each, since publicSubnetsOutput is a string, not a map nor a set of strings.

vpc.addOverride("private_subnets_test", {
  for_each: vpc.privateSubnetsOutput,
  content: "${private_subnets.value}",
});

I’ve also tried things like vpc.publicSubnetsOutput.split(",") but that didn’t work.

tl;dr: How can I get a list of public subnet IDs (as a list and not string) from the vpc module using cdktf?

Hey there,

The problem the CDK has with modules is that we don’t know for sure which return type a module output has so we default to string. This means we need to type cast this into a list, the easiest way to do it is using the Fn object in cdktf: subnets: Fn.tolist(base.publicSubnets).

I can see you are using cross stack references, please be aware that you need to deploy the stacks in the right order, so VPC first and your App second.