aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.52k stars 3.86k forks source link

aws-cdk-lib: incorrect rendering of CfnParameter in Fn.sub #28385

Open zhan9san opened 9 months ago

zhan9san commented 9 months ago

Describe the bug

The CloudFormation template generated by cdk synth is invalid if CfnParameter is in Fn.sub.

Similar to #14047 and #14068

Expected Behavior

The cdk code is valid after cdk synth runs

Current Behavior

    "Tags": [
     {
      "Key": "Environment",
      "Value": {
       "Fn::Sub": {
        "Fn::Join": [
         "",
         [
          "${AWS::StackName}-",
          {
           "Ref": "Environment"
          },
          "-foo"
         ]
        ]
       }
      }
     }
    ]
$ cfn-lint cdk.out/HelloWorldStack.template.json
E1019 Sub should be a string or array of 2 items for Resources/helloworldfunctionServiceRole6902C513/Properties/Tags/0/Value/Fn::Sub
cdk.out/HelloWorldStack.template.json:46:8

Reproduction Steps

    const env = new CfnParameter(this, 'Environment').valueAsString;
    Tags.of(this).add('Environment', Fn.sub('${AWS::StackName}-' + env + '-foo'))
$ cdk synth
$ cfn-lint cdk.out/HelloWorldStack.template.json
E1019 Sub should be a string or array of 2 items for Resources/helloworldfunctionServiceRole6902C513/Properties/Tags/0/Value/Fn::Sub
cdk.out/HelloWorldStack.template.json:46:8

Possible Solution

No response

Additional Information/Context

There is no issue if it is in the following format.

    const env = new CfnParameter(this, 'Environment').valueAsString;
    Tags.of(this).add('Environment', Fn.sub('${AWS::StackName}-' + '${env}' + '-foo', {env: env}))
    "Tags": [
     {
      "Key": "Environment",
      "Value": {
       "Fn::Sub": [
        "${AWS::StackName}-${env}-foo",
        {
         "env": {
          "Ref": "Environment"
         }
        }
       ]
      }
     }
    ]

CDK CLI Version

2.113.0 (build ccd534a)

Framework Version

No response

Node.js Version

v20.0.0

OS

MacOS

Language

TypeScript

Language Version

No response

Other information

No response

pahud commented 9 months ago

I would write this way instead

Tags.of(this).add('Environment', `${Stack.of(this).stackName}-${env}-foo`);

Does it work for you?

zhan9san commented 9 months ago

I would write this way instead

Tags.of(this).add('Environment', `${Stack.of(this).stackName}-${env}-foo`);

Does it work for you?

hi @pahud

Thanks for your suggestion.

I wonder what it is the recommended way to use fn.sub with cfnparameter.

If the way i do it is not correct, it would be great if it can be noted in the official document.