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.57k stars 3.88k forks source link

CfnLoadBalancer: CfnInclude broken for conditional tags #30740

Closed KyleBS closed 20 hours ago

KyleBS commented 3 months ago

Describe the bug

When you attempt to CfnInclude a AWS::ElasticLoadBalancingV2::LoadBalancer resource with valid conditional tags CDK errors out

Expected Behavior

CfnInclude should succeed

Current Behavior

An error is thrown:

CfnSynthesisError: Resolution error: Supplied properties not correct for "CfnLoadBalancerProps"                                                                                                                                                                                              
  tags: element 1: {} should have a 'key' and a 'value' property. 

Reproduction Steps

Create a stack and include the following:

const template = `{                                                                                                                         
  "AWSTemplateFormatVersion": "2010-09-09",                             
  "Parameters": {                                                      
    "IsExtraTag": {                                                       
      "Type": "String",            
      "AllowedValues": [                                                  
        "true",                                                           
        "false"                             
      ],                                                                                                                                            
      "Default": "false"                                                                                                                                                                                                                                                                                 
    }                                                                                                                                                                                                                                                                                                    
  },                                                                                                                                                
  "Conditions": {                        
    "AddExtraTag": {                                                 
      "Fn::Equals": [                                                                                                                               
        {                                                                                                                                           
          "data": "IsExtraTag",                                  
          "type": "Ref",                                 
          "isCfnFunction": true                                                                                                                     
        },                                                             
        "true"                                                                                                                                      
      ]                                                        
    }                                                                                                                                               
  },                                                                                                                                                
  "Resources": {                                                                                                                                    
    "MyLoadBalancer": {                                                
      "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",                                                                                          
      "Properties": {                                        
        "Name": "my-load-balancer",                                                                                                                 
        "Subnets": [                                                                                                                                
          "subnet-0123456789abcdef0"                                                                                                                                                                                                                                                                     
        ],                                                                                                                                          
        "SecurityGroups": [                                               
          "sg-0123456789abcdef0"                                                                                                                    
        ],                                                                
        "Scheme": "internet-facing",                                                                                                                
        "LoadBalancerAttributes": [                                       
          {                                                                                                                                         
            "Key": "idle_timeout.timeout_seconds",                      
            "Value": "60"                                                                                                                           
          }                                                               
        ],                         
        "IpAddressType": "ipv4",                                          
        "Tags": [                                                                                                                                   
          {                                 
            "Key": "Name",                                                                                                                          
            "Value": "MyLoadBalancer"                                                                                                                                                                                                                                                                    
          },                                                                                                                                                                                                                                                                                             
          {                                                                                                                                         
            "data": [                          
              "IsExtraTag",                                          
              {                                                                                                                                     
                "Key": "Name2",                                                                                                                     
                "Value": "MyLoadBalancer2"                       
              },                                         
              {                                                                                                                                     
                "data": "AWS::NoValue",                                
                "type": "Ref",                                                                                                                      
                "isCfnFunction": true                          
              }                                                                                                                                     
            ],                                                                                                                                      
            "type": "Fn::If",                                                                                                                       
            "isCfnFunction": true                                      
          }                                                                                                                                         
        ]                                                    
      }                                                                                                                                             
    }                                                                                                                                               
  }
}`;

const tmpobj = tmp.fileSync();                                                                                                                    

fs.writeFileSync(tmpobj.fd, template);                                                                                                            

new CfnInclude(this, 'MyStack', {                                                                                                                 
    templateFile: tmpobj.name                                         
});                                                                                                                                               

tmpobj.removeCallback();  

You will get the exception

CfnSynthesisError: Resolution error: Supplied properties not correct for "CfnLoadBalancerProps"                                                     
  tags: element 1: {} should have a 'key' and a 'value' property.    

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.87.0

Framework Version

No response

Node.js Version

v18.18.2

OS

AL2

Language

TypeScript

Language Version

No response

Other information

No response

ashishdhingra commented 3 months ago

@KyleBS Good afternoon. Thanks for reporting the issue. I'm unsure of your template is correct, but the issue is reproducible using below (modified) CDK code (based on guidance from Conditions and Conditionally tagging resources in CloudFormation):

import * as cdk from 'aws-cdk-lib';
import { CfnInclude } from 'aws-cdk-lib/cloudformation-include';
import { Construct } from 'constructs';
import * as fs from 'fs';
const tmp = require('tmp');

export class Issue30740Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const template = `{                                                                                                                         
      "AWSTemplateFormatVersion": "2010-09-09",                             
      "Parameters": {                                                      
        "IsExtraTag": {                                                       
          "Type": "String",            
          "AllowedValues": [                                                  
            "true",                                                           
            "false"                             
          ],                                                                                                                                            
          "Default": "false"                                                                                                                                                                                                                                                                                 
        }                                                                                                                                                                                                                                                                                                    
      },                                                                                                                                                
      "Conditions": {                        
        "AddExtraTag": {                                                 
          "Fn::Equals": [                                                                                                                               
            {                                                                                                                                           
              "Ref": "IsExtraTag",                                                                                                                 
            },                                                             
            "true"                                                                                                                                      
          ]                                                        
        }                                                                                                                                               
      },                                                                                                                                                
      "Resources": {                                                                                                                                    
        "MyLoadBalancer": {                                                
          "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",                                                                                          
          "Properties": {                                        
            "Name": "my-load-balancer",                                                                                                                 
            "Subnets": [                                                                                                                                
              "subnet-0123456789abcdef0"                                                                                                                                                                                                                                                                     
            ],                                                                                                                                          
            "SecurityGroups": [                                               
              "sg-0123456789abcdef0"                                                                                                                    
            ],                                                                
            "Scheme": "internet-facing",                                                                                                                
            "LoadBalancerAttributes": [                                       
              {                                                                                                                                         
                "Key": "idle_timeout.timeout_seconds",                      
                "Value": "60"                                                                                                                           
              }                                                               
            ],                         
            "IpAddressType": "ipv4",                                          
            "Tags": [                                                                                                                                   
              {                                 
                "Key": "Name",                                                                                                                          
                "Value": "MyLoadBalancer"                                                                                                                                                                                                                                                                    
              },                                                                                                                                                                                                                                                                                             
              {                                                                                                                                         
                "Fn::If": [                          
                  "AddExtraTag",                                          
                  {                                                                                                                                     
                    "Key": "Name2",                                                                                                                     
                    "Value": "MyLoadBalancer2"                       
                  },                                         
                  {                                                                                                                                     
                    "Ref": "AWS::NoValue",
                  }                                                                                                                                     
                ]                                    
              }                                                                                                                                         
            ]                                                    
          }                                                                                                                                             
        }                                                                                                                                               
      }
    }`;

    const tmpobj = tmp.fileSync();                                                                                                                    

    fs.writeFileSync(tmpobj.fd, template);                                                                                                            

    new CfnInclude(this, 'MyStack', {                                                                                                                 
        templateFile: tmpobj.name                                         
    });                                                                                                                                               

    tmpobj.removeCallback(); 
  }
}

Got the below error during cdk synth command:

CfnSynthesisError: Resolution error: Supplied properties not correct for "CfnLoadBalancerProps"
  tags: element 1: {} should have a 'key' and a 'value' property.
    at ValidationResult.assertSuccess (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/runtime.js:1:2707)
    at convertCfnLoadBalancerPropsToCloudFormation (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/aws-elasticloadbalancingv2/lib/elasticloadbalancingv2.generated.js:1:96969)
    at CfnLoadBalancer.renderProperties (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/aws-elasticloadbalancingv2/lib/elasticloadbalancingv2.generated.js:1:90724)
    at PostResolveToken.Resources (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/cfn-resource.js:1:7803)
    at PostResolveToken.postProcess (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/util.js:1:1653)
    at Object.postProcess (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:1205)
    at DefaultTokenResolver.resolveToken (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/resolvable.js:1:1483)
    at resolve (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:2711)
    at Object.resolve (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:1079)
    at resolve (/Users/REDACTED/dev/repros/cdk/issue30740/node_modules/aws-cdk-lib/core/lib/private/resolve.js:1:2990) {
  type: 'CfnSynthesisError'
}

Subprocess exited with error 1

It is more likely related to existing open issue https://github.com/aws/aws-cdk/issues/27594.

Thanks, Ashish

github-actions[bot] commented 20 hours ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.

github-actions[bot] commented 20 hours ago

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.