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.65k stars 3.91k forks source link

aws-imagebuilder: wrong case in CFN template for properties of AmiDistributionConfiguration #26912

Closed cvmeq closed 1 year ago

cvmeq commented 1 year ago

Describe the bug

I am deploying an EC2 Image Builder pipeline using CDK using the auto generated L1 constructs.

To configure how AMIs are distributed by the pipeline I am using CfnDistributionConfiguration.AmiDistributionConfigurationProperty (documentation here) which corresponds to AWS::ImageBuilder::DistributionConfiguration::AmiDistributionConfiguration.

The problem that I observed is that the properties of AmiDistributionConfiguration in the synthesized CloudFormation templated are generated in camel case (e.g., targetAccountIds) while they should be given in title case (e.g., TargetAccountIds).

The Image Builder pipeline is deployed and apparently works as specified, but this could be hinting at a bug somewhere so I'm reporting here.

Expected Behavior

Properties of AmiDistributionConfiguration in the synthesized should be generated with title case (e.g., TargetAccountIds).

Current Behavior

Properties of AmiDistributionConfiguration in the synthesized are generated with title case (e.g., targetAccountIds) which not only triggers cfn-lint but also leads to some non-fatal problems while deploying, as shown below

screenshot.

Reproduction Steps

MWE for a Python CDK app with a distribution configuration that illustrates the issue:

from constructs import Construct
import aws_cdk as cdk

class TestStack(cdk.Stack):
    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
        ami_dist_conf_prop = cdk.aws_imagebuilder.CfnDistributionConfiguration.AmiDistributionConfigurationProperty(
            name="Test-{{ imagebuilder:buildDate }}",
            description="My test AMI",
            ami_tags={
                "Key": "Value"
            },
            target_account_ids=[
                "111111111111",
                "222222222222",
                "333333333333",
            ]
        )
        dist_prop = cdk.aws_imagebuilder.CfnDistributionConfiguration.DistributionProperty(
            region="eu-central-1",
            ami_distribution_configuration=ami_dist_conf_prop,
        )
        cdk.aws_imagebuilder.CfnDistributionConfiguration(
            self,
            "DistributionConfiguration",
            name="DistributionConfiguration",
            description="Distribution for the AMI",
            distributions=[dist_prop],
        )

app = cdk.App()
env = cdk.Environment(account="444444444444", region="eu-central-1")
TestStack(app, "TestStack", env=env)
app.synth()

This is the resource after synthesized:

Resources:
  DistributionConfiguration:
    Type: AWS::ImageBuilder::DistributionConfiguration
    Properties:
      Description: Distribution for the AMI
      Distributions:
        - AmiDistributionConfiguration:
            amiTags:
              Key: Value
            description: My test AMI
            name: Test-{{ imagebuilder:buildDate }}
            targetAccountIds:
              - "111111111111"
              - "222222222222"
              - "333333333333"
          Region: eu-central-1
      Name: DistributionConfiguration
    Metadata:
      aws:cdk:path: TestStack/DistributionConfiguration

As it can be seen the properties amiTags, description, name, and targetAccountIds are wrongly cased. This can be further illustrated by linting the resulting template:

$ cdk synth TestStack | cfn-lint -

E3002 Invalid Property Resources/DistributionConfiguration/Properties/Distributions/0/AmiDistributionConfiguration/amiTags. Did you mean AmiTags?
-:8:13

E3002 Invalid Property Resources/DistributionConfiguration/Properties/Distributions/0/AmiDistributionConfiguration/description. Did you mean Description?
-:10:13

E3002 Invalid Property Resources/DistributionConfiguration/Properties/Distributions/0/AmiDistributionConfiguration/name
-:11:13

E3002 Invalid Property Resources/DistributionConfiguration/Properties/Distributions/0/AmiDistributionConfiguration/targetAccountIds. Did you mean TargetAccountIds?
-:12:13

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.93.0

Framework Version

No response

Node.js Version

18.16.1

OS

Ubuntu 22.04

Language

Python

Language Version

3.11.5

Other information

No response

pahud commented 1 year ago

This is a cfnspec patch issue and we are tracking at https://github.com/aws/aws-cdk/issues/21767

At this moment, you will need to specify a JSON for ami_distribution_configuration e.g.

dist_prop = cdk.aws_imagebuilder.CfnDistributionConfiguration.DistributionProperty(
            region="eu-central-1",
            ami_distribution_configuration={ "AmiTags": { "Key": "Value"}}
        )

Please check this sample for your reference.

peterwoodworth commented 1 year ago

Yes, thanks Pahud. The actual patch file is here for this case.

Track the issue Pahud linked #21767 for a long term solution, else, be mindful of whether the CDK docs are asking for the defined types, or if they're just asking for JSON.

github-actions[bot] commented 1 year ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.

pahud commented 9 months ago

Hi

I am offering a full working sample now. Please note according to the CDK Python API doc as ami_distribution_configuration is type Any, you will need to specify a full JSON for ami_distribution_configuration in CDK Python.

ami_distribution_configuration (Optional[Any])

Check out my full working sample below:

from aws_cdk import (
    CustomResource,
    CfnOutput,
    Stack,
    custom_resources as cr,
    aws_imagebuilder as imagebuilder,
    aws_lambda as lambda_,
)
from constructs import Construct
import os

class IssueTriagePyStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here

        ec2_distribution_configuration = imagebuilder.CfnDistributionConfiguration(self,
            id=f"ToolingTeamcityAmzn2023BaseDistributionConfiguration",
            description="Some description",
            distributions=[
                imagebuilder.CfnDistributionConfiguration.DistributionProperty(
                    region="us-east-1",
                    ami_distribution_configuration={
                        "AmiTags": {
                            "BuildVersion": "{{ imagebuilder:buildVersion }}",
                            "CostCenter": "hosting-deployment",
                            "Created": "{{ imagebuilder:buildDate }}",
                            "Description": "some description",
                            "Name": "some name",
                            "Region": "us-east-1",
                            "Version": "1.0.0",
                        },
                        "Description": "some description",
                        "LaunchPermissionConfiguration": {
                            "UserIds": ["123456789012"],
                        },
                        "Name": "some name - {{ imagebuilder:buildDate }}"
                    }
                )
            ],
            name="some name",
            tags={
                "ConfigurationDescription": "some description",
                "ConfigurationName": "some name",
                "CostCenter": "hosting-deployment",
            },
        )

And the synthesized output from CDK is like

{
 "Resources": {
  "ToolingTeamcityAmzn2023BaseDistributionConfiguration": {
   "Type": "AWS::ImageBuilder::DistributionConfiguration",
   "Properties": {
    "Description": "Some description",
    "Distributions": [
     {
      "AmiDistributionConfiguration": {
       "AmiTags": {
        "BuildVersion": "{{ imagebuilder:buildVersion }}",
        "CostCenter": "hosting-deployment",
        "Created": "{{ imagebuilder:buildDate }}",
        "Description": "some description",
        "Name": "some name",
        "Region": "us-east-1",
        "Version": "1.0.0"
       },
       "Description": "some description",
       "LaunchPermissionConfiguration": {
        "UserIds": [
         "123456789012"
        ]
       },
       "Name": "some name - {{ imagebuilder:buildDate }}"
      },
      "Region": "us-east-1"
     }
    ],
    "Name": "some name",
    "Tags": {
     "ConfigurationDescription": "some description",
     "ConfigurationName": "some name",
     "CostCenter": "hosting-deployment"
    }
   },
   "Metadata": {
    "aws:cdk:path": "IssueTriagePyStack/ToolingTeamcityAmzn2023BaseDistributionConfiguration"
   }
  },
  "CDKMetadata": {
   "Type": "AWS::CDK::Metadata",
   "Properties": {
    "Analytics": "v2:deflate64:H4sIAAAAAAAA/yWJQQ6CMBAA38K9XQWNiWd8gIEHmLYsuALbZLsbY4x/F+NpMjMN1M0R9lV4Fp+G2S8U4d1rSLPb0o3WMGE0WgYUaEe+UFGhaEqZ28wjTSbhJ26bHZZskvDjri+9Z94d4Az1qXoUIi/GSitC9+cXeQhnxHgAAAA="
   },
   "Metadata": {
    "aws:cdk:path": "IssueTriagePyStack/CDKMetadata/Default"
   }
  }
 },
 "Parameters": {
  "BootstrapVersion": {
   "Type": "AWS::SSM::Parameter::Value<String>",
   "Default": "/cdk-bootstrap/hnb659fds/version",
   "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
  }
 },
 "Rules": {
  "CheckBootstrapVersion": {
   "Assertions": [
    {
     "Assert": {
      "Fn::Not": [
       {
        "Fn::Contains": [
         [
          "1",
          "2",
          "3",
          "4",
          "5"
         ],
         {
          "Ref": "BootstrapVersion"
         }
        ]
       }
      ]
     },
     "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
    }
   ]
  }
 }
}

And you should not see any warning in cloudformation console.

As mentioned above this is a cfnspec issue and we are tracking in issue#21767. At this moment we need to specify the full JSON as describe above.