Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
aaroncarlucci opened this issue Jun 5, 2020 · 11 comments
Closed

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

aaroncarlucci opened this issue Jun 5, 2020 · 11 comments
Labels
@aws-cdk/core Related to core CDK functionality effort/large Large work item – several weeks of effort feature-request A feature should be added or improved. p1

Comments

@aaroncarlucci
Copy link

aaroncarlucci commented Jun 5, 2020

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

@aaroncarlucci aaroncarlucci added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jun 5, 2020
@skinny85 skinny85 self-assigned this Jun 8, 2020
@immmapig
Copy link

I am dealing with a similar issue.

Code before the change:

.provisionedThroughput(
                            ProvisionedThroughputProperty.builder()
                                    .readCapacityUnits(1)
                                    .writeCapacityUnits(1)
                                    .build())

Code after the change:

 .provisionedThroughput(
                                Fn.conditionIf(enableFeaturesCond.getLogicalId(), ProvisionedThroughputProperty.builder()
                                        .readCapacityUnits(1)
                                        .writeCapacityUnits(1)
                                        .build(), Aws.NO_VALUE))

Template before the change:

"ProvisionedThroughput": {
      "ReadCapacityUnits": 1,
      "WriteCapacityUnits": 1
  },

Template after the change:

"ProvisionedThroughput": {
      "Fn::If": [
        "UseEngagementTable",
        {
          "readCapacityUnits": 1,
          "writeCapacityUnits": 1
        },
        {
          "Ref": "AWS::NoValue"
        }
      ]
    },

Notice that the template after the change incorrectly uses readCapacityUnits and writeCapacityUnits as the keys instead of ReadCapacityUnits and WriteCapacityUnits.

@skinny85 skinny85 added p1 and removed needs-triage This issue or PR still needs to be triaged. labels Jun 29, 2020
@NetaNir NetaNir changed the title CfnPipeline.StageDeclarationProperty does not translate to correct CloudFormation syntax when returned from conditional in Python [Core] support complex types in Fn.If conditions Aug 17, 2020
@NetaNir NetaNir self-assigned this Aug 17, 2020
@github-actions github-actions bot added the @aws-cdk/core Related to core CDK functionality label Aug 17, 2020
@NetaNir NetaNir changed the title [Core] support complex types in Fn.If conditions [Core] support complex types in Fn. conditionIf Aug 17, 2020
@NetaNir NetaNir changed the title [Core] support complex types in Fn. conditionIf [Core] support complex types in Fn.conditionIf Aug 17, 2020
@NetaNir NetaNir added the effort/medium Medium work item – several days of effort label Aug 17, 2020
@eladb eladb assigned rix0rrr and unassigned eladb Aug 17, 2020
@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 18, 2020

We don't support this and I don't see us supporting it anytime soon.

@rix0rrr rix0rrr closed this as completed Aug 18, 2020
@rix0rrr
Copy link
Contributor

rix0rrr commented Oct 5, 2020

I will reopen this issue for reference but I will reiterate that the happy path for CDK is writing ifs in TypeScript, not in CloudFormation.

@rix0rrr rix0rrr reopened this Oct 5, 2020
@rix0rrr rix0rrr added effort/large Large work item – several weeks of effort feature-request A feature should be added or improved. and removed bug This issue is a bug. effort/medium Medium work item – several days of effort labels Oct 5, 2020
@aaroncarlucci
Copy link
Author

I will reopen this issue for reference but I will reiterate that the happy path for CDK is writing ifs in TypeScript, not in CloudFormation.

@rix0rrr Thanks for reconsidering. A reminder that the use case presented in the ticket description is using Cfn* resources to generate a CloudFormation template final deliverable and the suggested happy path of doing if statements in TypeScript or Python isn't an option for us.

@bollig
Copy link

bollig commented Feb 14, 2021

+1 for the use-case to generate standalone CFN templates. I had to use the same sort of workaround for conditionals on the FSx Lustre resource configuration block. Red line is desired.

image

@namedgraph
Copy link

@bollig what is the workaround mechanism here?

I want to set NetworkLoadBalancedEc2Service.domainZone() if HostedZone is provided, but not sure how to do it with Fn.conditionIf() since it provides a string and not an object :/

@bollig
Copy link

bollig commented Jun 9, 2021 via email

@drobbins-ancile
Copy link

drobbins-ancile commented Mar 5, 2022

@rix0rrr Any chance of getting this one addressed? We are also using CDK to generate CloudFormation templates to be manually deployed in other environments so using if conditions in the language won't work for us.

This seems to be a valid use case.

@savanbthakkar
Copy link

savanbthakkar commented Mar 6, 2022

@rix0rrr We are having the same problem with DynamoDB. Depending on the input parameter value, we need to set sse_specification. It generates the cloudformation yaml file, but the output is camelCase yaml attributes, and it errors out.

 sse_specification = cdk.Fn.condition_if(
                "NotEncryptedSearchTable",
                aws_dynamodb.CfnTable.SSESpecificationProperty(
                    sse_enabled = False
                ),
                aws_dynamodb.CfnTable.SSESpecificationProperty(
                    sse_enabled = True,
                    kms_master_key_id=inputParams.EncryptionKeyArn,
                    sse_type="KMS"
                )
            )

Here is the yaml output, which is invalid.

SSESpecification:
        Fn::If:
          - NotEncryptedSearchTable
          - sseEnabled: false
          - kmsMasterKeyId:
              Ref: EncryptionKeyArn
            sseEnabled: true
            sseType: KMS

@drobbins-ancile
Copy link

@rix0rrr Can we get an official decision on the validity of this use case? Is using cdk synth to generate cloudformation templates for deployment in other environments a supported use case? If so, is there any chance this issue will be worked on?

@madeline-k
Copy link
Contributor

Thank you for submitting this feature request! After closer examination of the issue by CDK product and development team, there are no plans to implement this in the near feature.

I am moving this to a GitHub discussion so the information in this thread can continue to be accessible, and people can find the helpful workaround posted here.

@aws aws locked and limited conversation to collaborators Feb 28, 2023
@madeline-k madeline-k converted this issue into discussion #24381 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
@aws-cdk/core Related to core CDK functionality effort/large Large work item – several weeks of effort feature-request A feature should be added or improved. p1
Projects
None yet
Development

No branches or pull requests