AWS CloudFormation:在嵌套堆栈之间传递值

时间:2017-04-13 12:56:16

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

更多AWS问题!好的,所以想法是一个主模板调用所有嵌套的堆栈。在这里的帮助下,我想出了如何将参数从master传递到嵌套堆栈。现在我试图弄清楚如何将值从嵌套堆栈传递到嵌套堆栈。我相信这应该通过出口和进口来完成,但我认为我没有这么做。我不确定这是我的进口或出口是错误的。

我得到的错误是:

No export named TestStack1-VpcStackID found. Rollback requested by user.

{
    "AWSTemplateFormatVersion" : "2010-09-09",
    "Description" : "Master template",
    "Parameters" : {
        "availabilityZone" : {
            "Default" : "us-east-1d",
            "Description" : "Enter AvailabilityZone.",
            "Type" : "String"
        },
        "VpcCidrBlock" : {
            "Default" : "10.0.0.0/16",
            "Description" : "VPC CIDR Block.",
            "Type" : "String"
        },
        "PublicSubnetCidrBlock" : {
            "Default" : "10.0.0.0/24",
            "Description" : "Public subnet CIDR block.",
            "Type" : "String"
        }
    },
    "Resources" : {
        "VpcStack" : {
            "Type" : "AWS::CloudFormation::Stack",
            "Properties" : {
                "Parameters" : {
                    "VpcCidrBlock" : {
                        "Ref" : "VpcCidrBlock"
                    }
                },
                "TemplateURL" : "https://s3.amazonaws.com/url/templates/vpcStack.json",
                "TimeoutInMinutes" : "5"
            }
        },
        "PublicRouteStack" : {
            "Type" : "AWS::CloudFormation::Stack",
            "Properties" : {
                "Parameters" : {
                    "PublicSubnetCidrBlock" : {
                        "Ref" : "PublicSubnetCidrBlock"
                    },
                    "VpcStack" : {
                        "Fn::ImportValue" : {
                            "Fn::Sub" : "${AWS::StackName}-VpcStackID"
                        }
                    }
                },
                "TemplateURL" : "https://s3.amazonaws.com/url/templates/publicRouteStack.json",
                "TimeoutInMinutes" : "5"
            }
        }
    }
}

VpcStack (已嵌套 - 我认为我输出不正确):

{
    "AWSTemplateFormatVersion" : "2010-09-09",
    "Description" : "VPC template",
    "Parameters" : {
        "VpcCidrBlock" : {
            "Description" : "Vpc CIDR Block.",
            "Type" : "String"
        }
    },
    "Resources" : {
        "VpcStack" : {
            "Type" : "AWS::EC2::VPC",
            "Properties" : {
                "EnableDnsSupport" : "true",
                "EnableDnsHostnames" : "true",
                "CidrBlock" : {
                    "Ref" : "VpcCidrBlock"
                },
                "Tags" : [
                    {
                        "Key" : "Application",
                        "Value" : {
                            "Ref" : "AWS::StackName"
                        }
                    }
                ]
            }
        }
    },
    "Outputs" : {
        "VpcStack" : {
            "Description" : "VPC Stack ID.",
            "Value" : {
                "Ref" : "VpcStack"
            },
            "Export" : {
                "Name" : {
                    "Fn::Sub" : "${AWS::StackName}-VpcStackID"
                }
            }
        }
    }
}

PublicStubnetStack (我认为这是失败的地方):

{
    "AWSTemplateFormatVersion" : "2010-09-09",
    "Description" : "Public Subnet Stack",
    "Parameters" : {
        "PublicSubnetCidrBlock" : {
            "Default" : "10.0.0.0/24",
            "Description" : "Public subnet CIDR block.",
            "Type" : "String"
        },
        "VpcStack" : {
            "Description" : "VPC Stack.",
            "Type" : "String"
        }
    },
    "Resources" : {
        "PublicSubnet" : {
            "Type" : "AWS::EC2::Subnet",
            "Properties" : {
                "VpcId" : {
                    "Ref" : "VpcStack"
                },
                "CidrBlock" : {
                    "Ref" : "PublicSubnetCidrBlock"
                },
                "Tags" : [
                    {
                        "Key" : "Application",
                        "Value" : {
                            "Ref" : "AWS::StackName"
                        }
                    },
                    {
                        " Key" : "Network",
                        "Value" : "Public"
                    }
                ]
            }
        }
    },
    "Outputs" : {
        "PublicSubnet" : {
            "Description" : "Public Subnet ID.",
            "Value" : {
                "Ref" : "PublicSubnet"
            },
            "Export" : {
                "Name" : {
                    "Fn::Sub" : "${AWS::StackName}-PublicSubnetID"
                }
            }
        }
    }
}

很抱歉发布这么多,我是AWS的新手,我正在尝试快速发布。

1 个答案:

答案 0 :(得分:7)

The Problem

Your problem is that you are exporting the value as

"Export" : {
  "Name" : {
    "Fn::Sub" : "${AWS::StackName}-VpcStackID"
  }
}

You are using the ${AWS::StackName} variable which will substitute the current stack name into your export variable name. Note that this is the stack name of your nested stack.

Whereas, in your wrapper template, you are attempting to import the value as:

"Fn::ImportValue" : {
  "Fn::Sub" : "${AWS::StackName}-VpcStackID"
}

Again, you are substituting the variable ${AWS::StackName} for the current stack, which in this case is your wrapper stack.

Note that when you use nested stacks, you are actually creating a new stack, so the stack names change depending on which template you are in.

The Resolution

Do not use import/export for your variables.

In your nested templates, drop the Export element from your outputs. You don't need them. Simply use stack parameters to pass values from your wrapper stack to nested stacks, and use stack outputs to pass values back up from nested stacks to wrapper stacks.

In your wrapper stack, use the output from VpcStack like this:

"PublicRouteStack" : {
        "Type" : "AWS::CloudFormation::Stack",
        "Properties" : {
            "Parameters" : {
                "PublicSubnetCidrBlock" : {
                    "Ref" : "PublicSubnetCidrBlock"
                },
                "VpcStack" : {
                    "Fn::GetAtt" : [ "VpcStack", "Outputs.VpcStack" ]
                }
            },
            "TemplateURL" : "https://s3.amazonaws.com/url/templates/publicRouteStack.json",
            "TimeoutInMinutes" : "5"
        }
    }

Note that in this case, I am using the output named VpcStack from your VpcStack nested stack via the Fn::GetAtt function.

PS. You should change some of your names simply for clarity. Try to avoid reusing the same name all over the place. It helps make things clear.