Amazon web services 使用Ref作为Fn::Sub内在函数中的第一个参数

Amazon web services 使用Ref作为Fn::Sub内在函数中的第一个参数,amazon-web-services,amazon-cloudformation,Amazon Web Services,Amazon Cloudformation,我在编译模板时遇到了非常奇怪的问题,我在Fn::Sub中引用了一个字符串参数,而do明确表示可以在Fn::Sub中使用Ref函数。下面是一个模板: "Resources": { "LaunchConfiguration": { "Type" : "AWS::AutoScaling::LaunchConfiguration", "Properties" : { "UserData": { "Fn::Base64": { "Fn::Sub": { "R

我在编译模板时遇到了非常奇怪的问题,我在
Fn::Sub
中引用了一个字符串参数,而do明确表示可以在
Fn::Sub
中使用
Ref
函数。下面是一个模板:

"Resources": {
    "LaunchConfiguration": {
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
      "Properties" : {
        "UserData": { "Fn::Base64": { "Fn::Sub": { "Ref": "UserDataParam" } } },
我得到一个错误:

模板错误:一个或多个Fn::子内在函数未指定 预期参数。指定字符串作为第一个参数,并指定 可选的第二个参数,用于指定要在中替换的值的映射 弦


当我使用完整表示法:
{“Fn::Sub”:[{“Ref”:“UserDataParam”},{}]}
时,我得到了完全相同的错误。有人有过同样的问题吗?在仍然使用参数的情况下,是否可以避免此问题?

您不能在Fn::Sub函数调用中直接使用Ref。要实现值映射,首先必须将Ref值赋给局部变量,并在Fn::子字符串中使用该局部变量

"UserData": {
  "Fn::Base64": {
    "Fn::Sub": [
      "${variable}",
      {
        "variable": {
          "Ref": "myS3Bucket"
        }
      }]
  }
}

或者,也可以不使用单独变量直接替换:

"UserData": {
  "Fn::Base64": {
    "Fn::Sub": "${myS3Bucket}"
  }
}

关键是使用
Fn::Sub
,而不使用通常的方括号,如

所述,您误读了文档。虽然文档确实说您可以使用
Ref
功能,但只有在第二个(可选)参数(键值映射)中才能使用该功能

文件中给出的示例如下:

{"Fn::Sub": ["www.${Domain}", {"Domain": {"Ref": "RootDomainName"}}]}
但是,如果需要替换为第一个参数,则必须使用美元表示法

要实现您看起来想要的,您应该将代码重写为:

{"Fn::Sub": "${UserDataParam}"}
或在上下文中:

"UserData": {"Fn::Base64": {"Fn::Sub": "${UserDataParam}"}}

如果在元数据中编写bash脚本时遇到此错误,则我的示例代码中的选项1和2是有效的,但选项3不是因为“-|”告诉子内在函数期望另一个“-|”,如选项1所示,它应该提供值映射(例如){某种类型的映射})以替换{blablabla}中的字符串。当未找到第二个映射时,将引发错误

Metadata:
  AWS::CloudFormation::Init:
   files:
   ##### use
    '/dir/subdir':
      content: !Sub
        - |
          {blablabla}
        - {A mapping of some sort}
    ###### or 

    '/dir2/subdir2':
      content: !Sub |
          {blablabla}

    ##### But don't mix like so

    '/dir3/subdir3':
      content: !Sub
        - |
          {blablabla}

使用此方法不会替换“myS3Bucket”中的变量,我认为这将是将其作为
Sub
第一个参数的主要目标。真正的问题是OP希望从参数中获取变量,而这种形式的Sub从提供的键值映射中获取变量。我认为如果迁移到ServerFault,这将更好地实现。