Skip to content

[Core] support complex types in Fn.conditionIf  #8396

@aaroncarlucci

Description

@aaroncarlucci

I am using the CDK to output a raw CloudFormation template as a final deliverable and am using primarily Cfn* resource constructs. We have a CfnPipeline object where I want to conditionally add a stage depending on a CfnParameter value. I have the following code:

codepipeline = aws_codepipeline.CfnPipeline(
            self,
            "Pipeline",
            artifact_store=aws_codepipeline.CfnPipeline.ArtifactStoreProperty(...),
                type="S3"
            ),
            role_arn=codepipeline_role.role_arn,
            stages=[
                aws_codepipeline.CfnPipeline.StageDeclarationProperty(...),
                aws_codepipeline.CfnPipeline.StageDeclarationProperty(...),
                aws_codepipeline.CfnPipeline.StageDeclarationProperty(...),
                core.Fn.condition_if(
                    cloudfront_enable_condition.logical_id,
                    aws_codepipeline.CfnPipeline.StageDeclarationProperty(
                        name="Finalize",
                        actions=[
                            aws_codepipeline.CfnPipeline.ActionDeclarationProperty(
                                action_type_id=aws_codepipeline.CfnPipeline.ActionTypeIdProperty(
			            category="Invoke",
                                    owner="AWS",
                                    provider="Lambda",
                                    version="1"
                                ),
                                configuration={
                                    "FunctionName": cloudfront_invalidation_lambda_function.ref
                                },
                                name="CloudFrontInvalidationAction",
                                role_arn=codepipeline_finalize_stage_role.attr_arn
                            )
                        ]
                    ),
                    core.Aws.NO_VALUE
                )
            ]
)

Which produces the following output in my CloudFormation template:

          {
            "Fn::If": [
              "CloudFrontEnableCondition",
              {
                "actions": [
                  {
                    "actionTypeId": {
                      "category": "Invoke",
                      "owner": "AWS",
                      "provider": "Lambda",
                      "version": "1"
                    },
                    "name": "CloudFrontInvalidationAction",
                    "configuration": {
                      "FunctionName": {
                        "Ref": "CloudFrontInvalidationLambdaFunction"
                      }
                    },
                    "roleArn": {
                      "Fn::GetAtt": [
                        "CodePipelineFinalizeStageRole",
                        "Arn"
                      ]
                    }
                  }
                ],
                "name": "Finalize"
              },
              {
                "Ref": "AWS::NoValue"
              }
            ]
          }
        ]

The keys of the CfnPipeline.StageDeclarationProperty and its children (CfnPipeline.ActionDeclarationProperty and CfnPipeline.ActionTypeIdProperty) are printed in camelCase, making for invalid CloudFormation objects on submission. I've also tried by wrapping the conditional statement in core.Token.as_any() with the same result.

I have resorted to using the following code:

codepipeline.add_override(
            "Properties.Stages.3",
            {
                "Fn::If": [
                    cloudfront_enable_condition.logical_id,
                    {
                        "Actions": [
                            {
                                "ActionTypeId": {
                                    "Category": "Invoke",
                                    "Owner": "AWS",
                                    "Provider": "Lambda",
                                    "Version": 1
                                },
                                "Configuration": {
                                    "FunctionName": cloudfront_invalidation_lambda_function.ref
                                },
                                "Name": "CloudFrontInvalidationAction",
                                "RoleArn": codepipeline_finalize_stage_role.attr_arn
                            }
                        ],
                        "Name": "Finalize"
                    },
                    core.Aws.NO_VALUE
                ]
            }
        )

which fixes my issue and proves that my conditional is valid in CloudFormation, but it feels messy and like the Cfn* properties should be supported in conditionals (IResolvable?).

Feels like this is a bug, but might be a feature request -- perhaps something is missing in the translation layer between nodejs and the Python API? If I'm supposed to be using the API differently, please advise.

Reproduction Steps

Run the above code patterns and inspect the cloudformation template in cdk.out

Error Log

CloudFormation complains of invalid object syntax.

Environment

  • CLI Version : 1.42.1
  • Framework Version:
  • Node.js Version: 12.16.2
  • OS : Ubuntu
  • Language (Version): Python3

Other

https://github.com/ordinaryexperts/aws-marketplace-oe-patterns-drupal/blob/f0201c49583a553832d72267ba07850b1bbe4aca/cdk/drupal/drupal_stack.py#L1870


This is 🐛 Bug Report

Metadata

Metadata

Assignees

No one assigned

    Labels

    @aws-cdk/coreRelated to core CDK functionalityeffort/largeLarge work item – several weeks of effortfeature-requestA feature should be added or improved.p1

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions