无法将子CloudFormation模板中的参数发送到另一个子模板

时间:2016-10-21 19:24:00

标签: templates amazon-web-services amazon-cloudformation

我正在制作一个CloudFormation模板的怪物,它使用AWS::CloudFormation::Stack资源来生成其他嵌套堆栈。这样做的目的是经典的职责分离和管理。

总体目标是从头开始构建应用程序环境(从VPC开始到应用程序实例结束)。

到目前为止,大部分都有效。但是我参考了子网CF模板和安全组CF模板的输出,用于创建EC2实例。

它的工作原理如下:

主模板 - >构建VPC - >调用子模板来构建子网 - >调用子模板来构建安全组 - >调用子模板来构建EC2实例

我需要将子网和安全组模板的输出传递给EC2实例模板,以便可以将实例配置到架构的正确部分。 VPC ID ref和KeyPairs传递正常,但是subnetID和securitygroupID没有。

以下是调用安全组/子网模板的主模板部分:

"DevNetworkStack": {
        "Type": "AWS::CloudFormation::Stack",
        "DependsOn": [
            "SNVPC",
            "SNIGW"
        ],
        "Properties": {
            "TemplateURL": {
                "Fn::FindInMap": [
                    "TemplateURLs",
                    "DevNetworkStack",
                    "URL"
                ]
            },
            "TimeoutInMinutes": "30",
            "Parameters": {
                "VPCID": {
                    "Ref": "SNVPC"
                },
                "SNIGW": {
                    "Ref": "SNIGW"
                }
            }
        }
    },
    "DevSecurityGroupsStack": {
        "Type": "AWS::CloudFormation::Stack",
        "DependsOn": "DevNetworkStack",
        "Properties": {
            "TemplateURL": {
                "Fn::FindInMap": [
                    "TemplateURLs",
                    "DevSecurityGroupsStack",
                    "URL"
                ]
            },
            "TimeoutInMinutes": "30",
            "Parameters": {
                "VPCID": {
                    "Ref": "SNVPC"
                }
            }
        }
},

这些工作正常。他们创造,一切都很好。模板提供如下输出:

"Outputs": {
     "DevAdminSubnetID": {
        "Description": "DevAdminSubnetID",
        "Value": {
            "Ref": "DevAdminSubnet"
        }
},

...

"Outputs": {
     "DevAdminSecurityGroupID": {
        "Description": "DevAdminSecurityGroupID",
        "Value": {
            "Ref": "DevAdminSecurityGroup"
        }
},

我可以在CF控制台中看到输出。

现在,下一个模板正在尝试使用安全组ID和子网ID。但它不起作用。

主模板将下一个孩子称为:

"DevAdminStack": {
       "Type": "AWS::CloudFormation::Stack",
        "DependsOn": [
            "DevNetworkStack",
            "DevSecurityGroupsStack",
            "EC2DevRoleInstanceProfile",
            "S3DevUserDataBucket",
            "S3DevHomeDirsDataBucket"
        ],
        "Properties": {
            "TemplateURL": {
                "Fn::FindInMap": [
                    "TemplateURLs",
                    "DevAdminStack",
                    "URL"
                ]
            },
            "TimeoutInMinutes": "30",
            "Parameters": {
                "AdminKeyPair": {
                    "Ref": "AdminServersKeyPair"
                },
                "VPCID": {
                    "Ref": "SNVPC"
                },
                "DevAdminSecurityGroupID": [
                    {
                        "Fn::GetAtt": [
                            "DevSecurityGroupsStack",
                            "Outputs.DevAdminSecurityGroupID"
                        ]
                    }
                ],
                "DevAdminSubnetID": [
                    {
                        "Fn::GetAtt": [
                            "DevNetworkStack",
                            "Outputs.DevAdminSubnetID"
                        ]
                    }
                ]
            }
        }
}

...并且子模板看起来像这样(为了简洁起见删除了一些部分,因为我现在只是测试)

{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Dev-Admin",
"Mappings": {
    "RegionMap": {
        "DevAdminServer": {
            "AMI": "ami-6fc9770e",
            "InstanceType": "t2.micro"
        }
    }
},
"Parameters": {
    "AdminKeyPair": {
        "Type": "AWS::EC2::KeyPair::KeyName"
    },
    "VPCID": {
        "Type": "AWS::EC2::VPC::Id"
    },
    "DevAdminSecurityGroupID": {
        "Type": "AWS::EC2::SecurityGroup::Id"
    },
    "DevAdminSubnetID": {
        "Type": "AWS::EC2::Subnet::Id"
    }
},
"Resources": {
    "DevAdminServer": {
        "Type": "AWS::EC2::Instance",
        "Metadata": {
            "Comment": "Sets up administrative tools for the server",
            "AWS::CloudFormation::Init": {
                "config": {
                    "packages": {
                        "yum": {}
                    },
                    "files": {},
                    "services": {}
                }
            }
        },
        "Properties": {
            "ImageId": {
                "Fn::FindInMap": [
                    "RegionMap",
                    "DevAdminServer",
                    "AMI"
                ]
            },
            "SecurityGroupIds": [
                {
                    "Ref": "DevAdminSecurityGroupID"
                }
            ],
            "SubnetId": {
                "Ref": "DevAdminSubnetID"
            },
            "InstanceType": {
                "Fn::FindInMap": [
                    "RegionMap",
                    "DevAdminServer",
                    "InstanceType"
                ]
            },
            "KeyName": {
                "Ref": "AdminKeyPair"
            },
            "Tags": [
                {
                    "Key": "Application",
                    "Value": {
                        "Ref": "AWS::StackId"
                    }
                }
            ],
            "UserData": {
                "Fn::Base64": {
                    "Fn::Join": [
                        "",
                        []
                    ]
                }
            }
        }
    }
  }
}

但是这个资源在创建时失败并出现错误:

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

我知道这是导致问题的最后两个变量(subnetID和securitygroupID),因为我删除了它们并且配置子模板工作得很好。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

DevAdminSecurityGroupIDDevAdminSubnetID的值在主模板中定义为JSON数组[],但它们应该是字符串(在Fn::GetAtt内部函数扩展之后):

            "DevAdminSecurityGroupID":
                {
                    "Fn::GetAtt": [
                        "DevSecurityGroupsStack",
                        "Outputs.DevAdminSecurityGroupID"
                    ]
                },
            "DevAdminSubnetID":
                {
                    "Fn::GetAtt": [
                        "DevNetworkStack",
                        "Outputs.DevAdminSubnetID"
                    ]
                }