aws-cdk: (core): `Vpc.fromVpcAttributes` using list tokens now throws errors

When importing a VPC using outputs from another stack, if the route table IDs are not specified for each imported subnet, a warning is printed to the console, as expected:

No routeTableId was provided to the subnet '#{Token[TOKEN.58]}'. Attempting to read its .routeTable.routeTableId will return null/undefined. (More info: https://github.com/aws/aws-cdk/pull/3171)

This warning line is wrongly evaluated by the new “floating token” check introduced by #11899, and throws an error when synthesizing the stack:

Found an encoded list token string in a scalar string context. Use 'Fn.select(0, list)' (not 'list[0]') to extract elements from token lists.

Additionally, this line is “consumed” by the floating-token check and does not reach the console.

Reproduction Steps

import * as cdk from "@aws-cdk/core";
import * as ec2 from "@aws-cdk/aws-ec2";

class TestStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    const vpcId = cdk.Fn.importValue("myVpcId");
    const availabilityZones = cdk.Fn.split(",", cdk.Fn.importValue("myAvailabilityZones"));
    const publicSubnetIds = cdk.Fn.split(",", cdk.Fn.importValue("myPublicSubnetIds"));

    ec2.Vpc.fromVpcAttributes(this, "importedVpc", {
      vpcId,
      availabilityZones,
      publicSubnetIds,
    });
  }
}

const app = new cdk.App();
new TestStack(app, "TestStack", {});

What did you expect to happen?

VPC is imported without error, and the following warning line is printed to the console:

No routeTableId was provided to the subnet '#{Token[TOKEN.58]}'. Attempting to read its .routeTable.routeTableId will return null/undefined. (More info: https://github.com/aws/aws-cdk/pull/3171)

What actually happened?

No warning is printed about the route table, and the stack fails to synthesize with the following error:

Found an encoded list token string in a scalar string context. Use 'Fn.select(0, list)' (not 'list[0]') to extract elements from token lists.

Environment

  • CDK CLI Version : 1.77.0
  • Framework Version: 1.77.0
  • Node.js Version: 12.20.0
  • OS : Linux (Pop!_OS 20.04 LTS x86_64)
  • Language (Version): TypeScript 3.9.7

Other

The floating token check should ignore CDK “logging” lines if possible.


This is 🐛 Bug Report

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 17 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@rix0rrr not sure if I’m missing something, but I’m still facing the same issue with aws-cdk@1.82.0 when attempting to spin up an EKS cluster. Maybe it’s worth mentioning, the VPC has both public/private subnets, thus public/private Routing Tables. Please find my code below:

const vpc = Vpc.fromVpcAttributes(scope, 'DefaultVpc', {
    vpcId: ssm.StringParameter.valueForStringParameter(scope, `${basePath}/VpcId`),
    availabilityZones: ssm.StringParameter.valueForStringParameter(scope, `${basePath}/AvailabilityZones`),
    privateSubnetIds: ssm.StringParameter.valueForStringParameter(scope, `${basePath}/PrivateSubnetIds`),
    privateSubnetRouteTableIds: ssm.StringParameter.valueForStringParameter(scope, `${basePath}/PrivateSubnetRouteTableIds`),
    publicSubnetIds: ssm.StringParameter.valueForStringParameter(scope, `${basePath}/PublicSubnetIds`),
    publicSubnetRouteTableIds: ssm.StringParameter.valueForStringParameter(scope, `${basePath}/PublicSubnetRouteTableIds`),
  });

const cluster = new eks.Cluster(this, 'DetestadrCluster', {
     vpc: vpc,
     defaultCapacity: 0,
     version: eks.KubernetesVersion.V1_18
});

Throwing the same error when resolving the template:

/Users/tauta/gitlab/aws/2.0aws/cdk/detestadr-configrepo-aws-ppb/cdk/node_modules/@aws-cdk/core/lib/private/resolve.ts:94
      throw new Error('Found an encoded list token string in a scalar string context. Use \'Fn.select(0, list)\' (not \'list[0]\') to extract elements from token lists.');

In addition, spinning an ECS cluster has no issues:

        const ecsCluster = new ecs.Cluster(this, 'EcsCluster', {
            clusterName: `blablablaCluster`,
            vpc: vpc,
        });