18

我正在尝试将列表参数从主模板传递到子模板,但是我遇到了两个错误。这些是我在主模板上的当前参数。

"Parameters": {
    "ELBSubnets": {
        "Default": "subnet-5d8fea67,subnet-3e35cf15",
        "Type": "CommaDelimitedList"
    },
    "LCKeyPair": {
        "Default": "key-master",
        "Type": "String"
    },
    "LCSecurityGroups": {
        "Default": "sg-10a15c74,sg-880e5fec",
        "Type": "CommaDelimitedList"
    }
},

当传递给子模板时,它们在同一模板上的此方法中被引用。

    "ChildTempate1": {
        "Properties": {
            "Parameters": {
                "ELBSubnets": {
                    "Ref": "ELBSubnets"
                },
                "KeyPair": {
                    "Ref": "LCKeyPair"
                },
                "LCSecurityGroups": {
                    "Ref": "LCSecurityGroups"
                }
            },

在子模板上,它们的声明完全相同。

"Parameters": {
    "ELBSubnets": {
        "Type": "CommaDelimitedList"
    },
    "LCKeyPair": {
        "Type": "String"
    },
    "LCSecurityGroups": {
        "Type": "CommaDelimitedList"
    }
},

并且它们在子模板中的此方法中被引用。

            "KeyName": {
                "Ref": "LCKeyPair"
            },
            "SecurityGroups": {
                "Fn::Join": [
                    ",",
                    [
                        {
                            "Ref": "LCSecurityGroups"
                        }
                    ]
                ]
            }
        },

这是模板的另一部分。

            "Subnets": {
                "Fn::Join": [
                    ",",
                    [
                        {
                            "Ref": "ELBSubnets"
                        }
                    ]
                ]
            }
        },

当我尝试在主模板上使用 fn::join 时,它说

“模板验证错误:模板错误:每个 Fn::Join 对象都需要两个参数,(1) 字符串分隔符和 (2) 要连接的字符串列表或返回字符串列表的函数(例如 Fn:: GetAZs) 加入。”

当我不在主模板上使用 fn::join 时,错误是

属性参数的值必须是具有字符串(或简单类型)属性的对象

无论我是否在子模板中的相同参数上有 fn::join。

两个模板都可以在这里找到: https ://github.com/slimg00dy/Troposphere-CloudformationTests

4

3 回答 3

21

问题是在 CommaDelimitedList 上使用 Ref 时,您传递了一个列表,因此它传递的是“[a,b,c]”而不是“a,b,c”

所以在主模板上,我使用 Join(",") 传递列表,使用 Join(" ") 传递字符串。这样它们被引用为“a,b,c”和“String”

在子模板上,我将参数设置为列表的 CommaDelimitedLists 和字符串中的字符串。这是因为它们从主模板传递的方式。

然后我在子模板上使用了 Ref 而没有在子模板上使用 Join()。这将 CommaDelimitedLists 创建到列表中,并且将使用 Join(" ") 连接的字符串作为字符串传递。

这是我在主模板上的参数声明。

"Parameters": {
    "ELBSubnets": {
        "Default": "subnet-5d8fea67,subnet-3e35cf15",
        "Type": "CommaDelimitedList"
    },
    "LCKeyPair": {
        "Default": "key-master",
        "Type": "CommaDelimitedList"
    },
    "LCSecurityGroups": {
        "Default": "sg-10a15c74,sg-880e5fec",
        "Type": "CommaDelimitedList"
    }
},

下面是我如何使用 Join(",")、Join(" ") 和 Ref。由于 Ref 将 CommaDelimitedLists 转换为 Lists,因此我使用 Join(",") 将它们保留为 CommaDelimitedLists 并将它们传递给子模板。

至于 KeyPair 字符串,我确保它在父模板上声明为 CommaDelimitedList 并与 Join(" ") 连接,这在引用子模板时有效地将其变为字符串。

            "Parameters": {
                "ELBSubnets": {
                    "Fn::Join": [
                        ",",
                        {
                            "Ref": "ELBSubnets"
                        }
                    ]
                },
                "LCKeyPair": {
                    "Fn::Join": [
                        " ",
                        {
                            "Ref": "LCKeyPair"
                        }
                    ]
                },
                "LCSecurityGroups": {
                    "Fn::Join": [
                        ",",
                        {
                            "Ref": "LCSecurityGroups"
                        }
                    ]
                }
            },

在子模板上,它们是这样声明的。

 "Parameters": {
    "ELBSubnets": {
        "Type": "CommaDelimitedList"
    },
    "LCKeyPair": {
        "Type": "String"
    },
    "LCSecurityGroups": {
        "Type": "CommaDelimitedList"
    }
},

并且它们都被正常引用,而无需在子模板上使用 Join。

Subnets": {
                "Ref": "ELBSubnets"
            }

可能有很多不同的方法可以做到这一点。我本可以在子模板而不是父模板上加入。但是,我更喜欢让一个模板保持复杂,而其余的则尽可能干净。希望这可以帮助其他人。

我也应该能够将列表作为子模板上的列表传递,但是随后我收到错误“未知参数类型:列表”

于 2015-05-23T14:47:28.300 回答
6

CommaDelimtedList 只能解析一次,所以在模板中,需要将类型设置为“String”,然后在模板中,保持为 CommaDelimitedList,和之前一样。

问题正在发生,因为 CloudFormation 正在解析父模板中的 CommaDelimitedList,然后尝试在子模板中再次解析它。

于 2015-08-18T10:35:17.893 回答
0

所以我之前的回答有点令人困惑——但我认为基础知识仍然存在。最后,当您在需要列表的参数中使用 CommaDelimitedList 时,您不必加入()。我刚刚查看了您对共享的 repo 的最新更新,我认为您走在正确的轨道上。如果您需要更多帮助,请告诉我!

于 2015-05-23T04:15:21.947 回答