I experience quite strange issues when compiling the template, where I reference a string parameter in Fn::Sub
, while the docs do explicitly say that one can use Ref
function inside of Fn::Sub
. Here is a piece of template:
"Resources": {
"LaunchConfiguration": {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"UserData": { "Fn::Base64": { "Fn::Sub": { "Ref": "UserDataParam" } } },
And here is an error I get:
Template error: One or more Fn::Sub intrinsic functions don't specify
expected arguments. Specify a string as first argument, and an
optional second argument to specify a mapping of values to replace in
the string
When I use full notation: { "Fn::Sub": [ { "Ref": "UserDataParam" }, {} ] }
, I get exactly the same error. Has anybody had the same issue? And is it possible to avoid it while still using the parameter?
You cannot directly use a Ref within a Fn::Sub function call. To achieve a value mapping, you first have to assign the Ref value into a local variable und use that one within the Fn::Sub string.
"UserData": {
"Fn::Base64": {
"Fn::Sub": [
"${variable}",
{
"variable": {
"Ref": "myS3Bucket"
}
}]
}
}
Alternatively it's possible to substitute directly without using a separate variable:
"UserData": {
"Fn::Base64": {
"Fn::Sub": "${myS3Bucket}"
}
}
The key is to use Fn::Sub
without the usual square brackets as explained at https://forums.aws.amazon.com/message.jspa?messageID=745085#745085
You are misreading the docs. While the docs do say you can use the Ref
function, it is only in the second (optional) parameter (the key-value map) where you can do that.
The example given in the docs is:
{"Fn::Sub": ["www.${Domain}", {"Domain": {"Ref": "RootDomainName"}}]}
If, however, you need to substitute into the first parameter, you must use the dollar notation.
To achieve what you appear to want, you should rewrite your code as:
{"Fn::Sub": "${UserDataParam}"}
Or in context:
"UserData": {"Fn::Base64": {"Fn::Sub": "${UserDataParam}"}}