Search code examples
amazon-web-servicesaws-cloudformationaws-codepipeline

Cloudformation ImportValue within ParameterOverride CodePipeline


Problem: I have a cloudformation template that is supposed to retrieve code found in CodeCommit and push it to a Lambda. The code in CodeCommit also contains a SAM template with a few parameters. The SAM template has the following setup

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Deploy Python code to Lambda

Parameters:
  ArtifactsBucket:
    Description: The artifact bucket to get the lambda code
    Type: String
  Name:
    Description: Name of the lambda function
    Type: String
  SqsARN:
    Description: AWS SQS Arn to act as a trigger for the lambda function
    Type: String
...

and the CodePipeline Cloudformation template has the following to override the 3 parameters present in the SAM template.

...
 - Name: Deploy
    Actions:
    - Name: Deploy
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: CloudFormation
        Version: 1
      Configuration:
        ActionMode: CREATE_UPDATE
        Capabilities: 'CAPABILITY_IAM,CAPABILITY_AUTO_EXPAND,CAPABILITY_NAMED_IAM'
        ChangeSetName: !Join 
          - '-'
          - - lambda
            - !Ref CodeCommitRepoName
        ParameterOverrides: !Sub |
          {
            "ArtifactsBucket": "${ArtifactsBucket}",
            "Name": "${CodeCommitRepoName}",
            "SqsARN": {"Fn::ImportValue": "My-queue:us-east-1:Queue:Arn"}
          }
...

The ArtifactBucket and the Name parameters are easily changed by the !Sub function but I am not able to have a valid value for SqsARN which is an imported value.

QuestionIs there anyway to include ImportValue in conjungtion with a Sub function within ParametersOverride?

Attempts I also tried to switch from

{"Fn::ImportValue": "My-queue:us-east-1:Queue:Arn"}

to

!ImportValue": "My-queue:us-east-1:Queue:Arn"

which also did not work. Remove the !Sub function and using a !Ref function yields the same output/problem as with ImportValue.


Solution

  • Key thing to remember is, using JSON within YAML

    From the documentation

    You can't use the short form of !ImportValue when it contains a !Sub. It is valid for AWS CloudFormation, but not valid for YAML:

    Assuming Environment as Parameter, Here is a working example of Sub >> ImportValue >> Sub

            Value: !Sub
                - '{
                  "sqsUrl": "${sqsUrl}",
                  }'
                - {
                      sqsUrl: { 'Fn::ImportValue': { 'Fn::Sub': 'QueUrl-${Environment}' } }
                  }
    

    Applying it to above example might look something like below(using ssm for testing)

    Parameters:
        Environment:
            Type: String
            Default: DV
        ArtifactsBucket:
            Type: String
            Default: TestBucket
        CodeCommitRepoName:
            Type: String
            Default: Test
    
    Resources:
        SmsLambdaParameter:
            Type: 'AWS::SSM::Parameter'
            Properties:
                Name: !Sub
                    - '/${EnvFullUpper}/My-Param/Test'
                    - { EnvFullUpper: !Ref Environment }
                Type: 'String'
                Value: !Sub
                    - '{
                      "ArtifactsBucket": "${ArtifactsBucket}",
                      "Name": "${CodeCommitRepoName}",
                      "SqsARN": "${SqsArn}"
                      }'
                    - { SqsARN: { 'Fn::ImportValue': { 'Fn::Sub': 'QueueArn-${Environment}' } } }