6
votes

I've a cloudformation template that uses custom resource backed by lambda function. One of the parameters of the lambda function is a list of strings. I have only one item to pass in the list and would like to use Fn:Join to concatenate create the string. However, using Fn::Join gives error as it leads to invalid json. Any inputs are appreciated.

"Subscriptions": [ "Fn::Join": [":", ["a", "b", "c"]]]

A client error (ValidationError) occurred when calling the CreateStack operation : Template format error: JSON not well-formed.

Cloudformation snippet:-

  "Resources": {
"MyCustomRes": {
      "Type": "Custom::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::Join": [ "", [
                                        "arn:aws:lambda:",
                                        { "Ref": "AWS::Region" },
                                        ":",
                                        { "Ref": "AWS::AccountId" },
                                        ":function:LambdaFn"
                                      ] ] },
        "Version": 1,
        "ResourceName": { "Ref": "ResourceName" },
        "Subscriptions"       : [ "Fn::Join": [ "", [
                                        "arn:aws:sns:",
                                        { "Ref": "AWS::Region" },
                                        ":",
                                        { "Ref": "AWS::AccountId" },
                                        ":Topic1"
                                      ] ] ]
    }
}     },
2

2 Answers

11
votes

The Fn::Join Intrinsic Function used to build the values for the the Subscriptions property needs to be an object rather than an array.

it's invalid JSON syntax to use an array like ['Fn::Join' : [...]] instead it must be of the form {"Fn::Join" : [...]}

The docs describe the syntax as

{ "Fn::Join" : [ "delimiter", [ comma-delimited list of values ] ] }

Therefore your Cloud Formation template should use the following

    "Subscriptions": {
        "Fn::Join": [":", [
            "arn:aws:sns", 
            { "Ref": "AWS::Region"},
            { "Ref": "AWS::AccountId"},
            "Topic1"]
         ]
     }
7
votes

I arrived here looking for the same syntax in YAML files. What threw me there was needing to have two lists of args: a list with 2 items to Join, the second of which is a list itself. The full YAML syntax looks like this:

  SourceArn: 
    Fn::Join: 
    - ""
    - - 'arn:aws:execute-api:'
      - !Ref AWS::Region
      - ':'
      - !Ref AWS::AccountId
      - ':'
      - !Ref ApiGatewayRestApiResource
      - '/*'