I have some userdata scripts which are currently used by standalone EC2 instances. I'd like to be able to use these with cloudformation and include calls to the 'cfn-' helper scripts to signal the cloudformation stack of the progress. Essentially, I'd like to be able to prepend some data to the userdata script, and append some data to it. To do so I planned to take the existing script and use sed to remove the leading shebang/script line, and pass that slightly modified script into cloudformation as a parameter. This script needs to be base64 encoded before being passed as a parameter. I base64 encode and then split based on a 4096 byte size (the parameter size limit). My cloudformation template has 4 'userdata' parameter fields that I can pass data into. This currently works in existing scripts:
"UserData" : { "Fn::Join" : [ "", [ { "Ref" : "UserData" }, { "Ref" : "UserData2" }, { "Ref" : "UserData3" }, { "Ref" : "UserData4" }]]},
Note: I don't have to use the base64 intrinsic function here as the individual parameters are already base64 encoded.
I've been trying this, but I'm getting an error (show further down):
"UserData" : {
"Fn::Join": [
"", [
{ "Fn::Base64":
{ "Fn::Join": [
"", [
"#!/bin/bash\n",
{"Fn::Join": ["", ["AWS_REGION=",{ "Ref" : "AWS::Region" },"\n"]]},
{"Fn::Join": ["", ["STACKNAME=",{ "Ref" : "AWS::StackName" },"\n"]]},
"LAUNCHCONFIG=LaunchConfig\n",
"# # Signalling cloudformation\n",
{"Fn::Join": ["", ["/opt/aws/bin/cfn-init -v --stack ",{ "Ref" : "AWS::StackName" }," --resource LaunchConfig --region ",{ "Ref" : "AWS::Region" },"\n"]]},
]
]}
},
{ "Ref" : "UserData" },
{ "Ref" : "UserData2" },
{ "Ref" : "UserData3" },
{ "Ref" : "UserData4" },
{ "Fn::Base64":
{ "Fn::Join": [
"", [
{"Fn::Join": ["", ["/opt/aws/bin/cfn-signal -e $? --stack ",{ "Ref" : "AWS::StackName" }," --resource AutoScalingGroup --region ",{ "Ref" : "AWS::Region" },"\n"]]},
]
]}
}
]
]
},
The error received is:
UserData does not appear to be base64 encoded (Service: AmazonAutoScaling; Status Code: 400; Error Code: ValidationError
I want to avoid the situation where I need to know the appropriate parameters ahead of time - and thus generating a new userdata script including that detail which could be passed as a parameter - as I would like to avoid generating a custom userdata file specifically to use with cloudformation.
I've passed in empty values for the four 'userdata' parameters, so it appears that the leading and trailing elements in the join are not being base64 encoded. I appreciate any insight into this, or how I might accomplish what I have described.