Search code examples
amazon-web-servicesaws-cloudformation

Use CloudFormation import with substitution name in conditional expression with `DeletionPolicy`


One of my AWS CloudFormation templates exports a value for "stage" (which can be e.g. "dev" or "prod") in a variable based upon the stack name, like this:

Export:
  …
      Name: !Sub "${AWS::StackName}:stage"

The stack name is in the form foo-${Env}, where Env is some value such as "bar". This Env param is passed to another CloudFormation template. The other template should be able to access the stage of that Env like this, using the external export:

      SomeResourceProperty:
        Fn::ImportValue:
          !Sub "foo-${Env}:stage"

For example if the Env parameter is set to "bar", this would pull in the external variable foo-bar:stage. And that's no problem. It works fine. I import all sorts of variables from the first stack using this form.

I would like to create a condition based upon this variable, in order to set the retention of a resource based upon the stage. First I try this:

Conditions:
  IsStageProd: !Equals
    - Fn::ImportValue:
        !Sub "foo-${Env}:stage"
    - "prod"

CloudFormation whimpers and tells me that it can't use imported values in conditions.

Never mind; I'll import the value directly in my !If function. As per Intrinsic function references in DeletionPolicy and UpdateReplacePolicy attributes, I add the AWS::LanguageExtensions transformation:

---
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::LanguageExtensions

…

Then I try to set the deletion policy of a log group:

    DeletionPolicy:
      Fn::If:
        - Fn::Equals:
            - Fn::ImportValue:
                !Sub "foo-${Env}:stage"
            - "prod"
        - Retain
        - Delete

This time CloudFormation breaks down in tears:

Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Transform AWS::LanguageExtensions failed with: Fn::If layout is incorrect

How can I conditionally retain a resource based upon the value of a variable imported from another stack, when the name of the variable depends on a parameter passed to the current template?

I have filed Use CloudFormation import with substitution name in conditional expression with DeletionPolicy. #126.


Solution

  • This is indeed a limitation. A ticket for improvement has been filed as Use Fn::ImportValue in Conditions #127.