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

Can't send parameters from a child CloudFormation template to another child template

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

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

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

它是这样工作的:

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

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

这是调用安全 group/subnet 模板的主模板部分:

"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": [
                        "",
                        []
                    ]
                }
            }
        }
    }
  }
}

但是此资源创建失败并出现错误:

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

我知道是最后两个变量(subnetID 和 securitygroupID)引起了问题,因为我删除了它们并且配置子模板工作正常。

我做错了什么?

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

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