"Fn :: Join" delimited by parameter?

I am trying to parameterize the delimiter used by Fn :: Join, for example. first i:

"Name" : { "Fn::Join" : [ ".", [ 
           { "Ref":"serviceName"}, { "Ref": "environment" } ] ] },

Which works well, but then I changed it to:

"Name" : { "Fn::Join" : [ {"Ref":"HostNameSeparator"}, [
           { "Ref":"serviceName"}, { "Ref": "environment" } ] ] },

I get the following error in the verification phase:

A client error (ValidationError) occurred when calling the
ValidateTemplate operation: Template error: every Fn::Join object
requires two parameters, (1) a string delimiter and (2) a list of
strings to be joined or a function that returns a list of strings
(such as Fn::GetAZs) to be joined.

Is it possible to do what I want, that is, pass the Join separator as a template parameter?

(I simplified the above examples for clarity, please ignore typos)

+4
source share
1 answer

You can achieve this using CustomResource. This CloudFormation template is ready to run and illustrates how it can work. Delimiter is passed as a parameter and you will find the concatenated string in the stack pins.

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Example Join",
    "Parameters": {
        "Delimiter": {
            "Type": "String"
        }
    },
    "Resources": {
        "LambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": ["lambda.amazonaws.com"]
                            },
                            "Action": ["sts:AssumeRole"]
                        }
                    ]
                },
                "Path": "/",
                "Policies": [
                    {
                        "PolicyName": "root",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "logs:CreateLogGroup",
                                        "logs:CreateLogStream",
                                        "logs:PutLogEvents"
                                    ],
                                    "Resource": "arn:aws:logs:*:*:*"
                                },
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "cloudformation:DescribeStacks"
                                    ],
                                    "Resource": "*"
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "LambdaJoin": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Code": {
                    "ZipFile":  { "Fn::Join": ["\n", [
                        "var response = require('cfn-response');\n",
                        "exports.handler = function (event, context) {\n",
                        "if (event.RequestType === 'Delete') {\n",
                        "return response.send(event, context, response.SUCCESS, {}, event.PhysicalResourceId);\n",
                        "}\n",
                        "var delimiter = event.ResourceProperties.delimiter || '';\n",
                        "var strings = event.ResourceProperties.strings || [];\n",
                        "return response.send(event, context, response.SUCCESS, { string: strings.join(delimiter) }, event.PhysicalResourceId);\n",
                        "};\n"
                    ]]}
                },
                "Handler": "index.handler",
                "Runtime": "nodejs",
                "Timeout": "10",
                "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }
            }
        },
        "CustomJoin": {
            "Type": "Custom::Join",
            "Version": "1.0",
            "Properties": {
                "ServiceToken": { "Fn::GetAtt": ["LambdaJoin", "Arn"] },
                "delimiter": { "Ref": "Delimiter" },
                "strings": ["first", "second", "third"]
            },
            "DependsOn": ["LambdaJoin"]
        }
    },
    "Outputs": {
        "JoinedString": {
            "Value": { "Fn::GetAtt": ["CustomJoin", "string"] }
        }
    }
}
+2

All Articles