Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a list item conditional in Cloud Formation template?

I have the following cloud formation template that creates a code pipeline. The pipeline has three stages:

  Stages:
    -
      Name: "Source"
      Actions:
        -
          Name: "Source"
          ActionTypeId:
            Category: "Source"
            Owner: "ThirdParty"
            Version: "1"
            Provider: "GitHub"
          OutputArtifacts:
            - Name: "MyApp"
          Configuration:
            Owner: !Ref GithubOwner
            Repo: !Ref GithubRepo
            PollForSourceChanges: "true"
            Branch: !Ref GithubBranch
            OAuthToken: !Ref GithubTokenParameter
          RunOrder: 1
    -
      Name: "Run-Unit-Tests"
      Actions:
        -
          InputArtifacts:
            - Name: "MyApp"
          Name: "UnitTests"
          ActionTypeId:
            Category: "Test"
            Owner: "AWS"
            Version: "1"
            Provider: "CodeBuild"
          OutputArtifacts:
            - Name: "MyTests"
          Configuration:
          ProjectName: !Ref CodeBuildName
          RunOrder: 1
    -
      Name: "Deploy-Staging"
      Actions:
        -
          InputArtifacts:
            - Name: "MyApp"
          Name: "Deploy-Staging"
          ActionTypeId:
            Category: "Deploy"
            Owner: "AWS"
            Version: "1"
            Provider: "ElasticBeanstalk"
          Configuration:
            ApplicationName: !Ref BeanstalkApplicationName
            EnvironmentName: !Ref BeanstalkEnvironmentStaging
          RunOrder: 1

I also have a condition:

IncludeStagingEnv: !Equals [Staging, !Ref CodePipelineEnvironment]

When the condition is false, I would like to omit the 3rd item in the Code Pipeline stages list.

I tried using !If with AWS::NoValue, but NoValue is not a valid list item:

Stages:
  - !IF
    - IncludeStagingEnv
    - Name: "Deploy-Staging"
      Actions:
        -
          InputArtifacts:
            - Name: "MyApp"
          Name: "Deploy-Staging"
          ActionTypeId:
            Category: "Deploy"
            Owner: "AWS"
            Version: "1"
            Provider: "ElasticBeanstalk"
          Configuration:
            ApplicationName: !Ref BeanstalkApplicationName
            EnvironmentName: !Ref BeanstalkEnvironmentStaging
            RunOrder: 1
    - AWS::NoValue

How can I omit the last item when IncludeStagingEnv==false?

like image 931
Tim W. Avatar asked Aug 13 '17 20:08

Tim W.


People also ask

Which section of CloudFormation template does not allow for conditions?

According to the docs, Conditions should be used at the top level of the resource you want to conditionally create. Putting a Condition inside the Instance UserData section isn't supported. To use Conditions in your situation, you'd want separate Resources conditionally created based on the Parameter.

What is conditions in cloud formation?

With conditions, you can define which resources are created and how they're configured for each environment type. Conditions are evaluated based on predefined pseudo parameters or input parameter values that you specify when you create or update a stack.

What is pseudo parameter in AWS CloudFormation?

Pseudo parameters are parameters that are predefined by AWS CloudFormation. You don't declare them in your template. Use them the same way as you would a parameter, as the argument for the Ref function.


2 Answers

Same problem occurs on my template for a Cloudfront distribution.

The solution was to use AWS::NoValue with the Ref attribute.

...
LambdaFunctionAssociations: 
  Fn::If: 
    - Authentication
    - - EventType: "viewer-request"
        LambdaFunctionARN: "arn:aws:lambda:us-east-1:..."
    - - Ref: "AWS::NoValue"
...

If this work for all resources same, you should change your conditional part to:

Stages:
  - !If
    - IncludeStagingEnv
    - - Name: "Deploy-Staging"
        Actions:
          - InputArtifacts:
            ...
    - - Ref: "AWS::NoValue"

Hope this helps!

like image 57
Fabi755 Avatar answered Oct 19 '22 21:10

Fabi755


@Fabi755's answer put me on the right path thank you!

I was fighting with the same LambdaFunctionAssociations challenge. I settled on a slightly different, slightly better approach as follows. I think it is better in that it works for multiple optional list items.

          LambdaFunctionAssociations:
          - !If
            - HasOriginResponseFunctionArn
            - EventType: origin-response
              LambdaFunctionARN: !Ref OriginResponseFunctionArn
            - !Ref AWS::NoValue
          - !If
            - HasViewerRequestFunctionArn
            - EventType: viewer-request
              LambdaFunctionARN: !Ref ViewerRequestFunctionArn
            - !Ref AWS::NoValue
like image 31
Aaron Avatar answered Oct 19 '22 22:10

Aaron