访问堆栈的输出数据



我正在使用CloudFormation创建一个REST API。在另一个CloudFormation堆栈中,我希望能够访问该CloudFormation脚本的输出部分(调用URL)中的值。

这是可能的吗?

您可以导出您的输出。导出使它们可以被其他堆栈访问。

来自AWS文档:

要导出堆栈的输出值,使用堆栈模板的output部分中的export字段。要导入这些值,请在其他堆栈的模板中使用Fn::ImportValue函数

下面导出一个API网关Id。

Description: API for interacting with API resources
Parameters:
TargetEnvironment:
Description: 'Examples can be dev, test or prod'
Type: 'String'

ProductName:
Description: 'Represents the name of the product you want to call the deployment'
Type: 'String'
Resources:
MyApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapi'
Outputs:
MyApiId:
Description: 'Id of the API'
Value: !Ref MyApi
Export:
Name: !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapi'
MyApiRootResourceId:
Description: 'Id of the root resource on the API'
Value: !GetAtt MyApi.RootResourceId
Export:
Name: !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapirootresource'

输出的Export部分是这里的重要部分。如果你提供了Export,那么其他栈就可以使用它。

现在,在另一个文件中,我可以通过使用Fn::Import固有函数导入MyApiId值,导入导出的名称。我还可以导入它的根资源,并在创建子API资源时使用这两个值。

来自AWS文档:

内部函数Fn::ImportValue返回另一个堆栈导出的输出值。您通常使用这个函数来创建跨堆栈引用。

Description: Resource endpoints for interacting with the API
Parameters:
TargetEnvironment:
Description: 'Examples can be dev, test or prod'
Type: 'String'

ProductName:
Description: 'Represents the name of the product you want to call the deployment'
Type: 'String'
Resources:
MyResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: {'Fn::ImportValue': !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapirootresource' }
PathPart: foobar
RestApiId: {'Fn::ImportValue': !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapi' }
这是两个完全不同的。Yaml文件,可以作为两个独立的堆栈部署,但现在它们相互依赖。如果在删除MyResource堆栈之前先删除MyApiAPI网关堆栈,会导致CloudFormation删除操作失败。你必须先删除依赖项。

要记住的一件事是,在某些情况下,您可能希望能够灵活地删除根资源,而不必担心依赖关系。在某些情况下,删除操作可能没有任何副作用。例如,删除一个SNS主题不会破坏Lambda——它只会阻止它运行。没有理由仅仅为了重新部署一个新的SNS主题而删除Lambda。在这种情况下,我使用命名约定并以这种方式将内容绑定在一起,而不是使用导出。例如,上面的AWS::ApiGateway::Resource可以基于命名约定绑定到特定于环境的API网关。

Parameters:
TargetEnvironment:
Description: 'Examples can be dev, test or prod'
Type: 'String'

ProductName:
Description: 'Represents the name of the product you want to call the deployment'
Type: 'String'
Resources:
MyResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: {'Fn::ImportValue': !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapirootresource' }
PathPart: foobar
RestApiId: !Sub '${ProductName}-${TargetEnvironment}-apigw-primaryapi'

这样,只要资源的后半部分在所有环境中命名相同,就无需担心导出/导入。环境可以通过TargetEnvironment参数来改变,这样就可以在dev, test和prod之间重用。

此方法的一个警告是,命名约定仅适用于当您想要访问可以通过名称引用的内容时。如果您需要一个属性,例如本例中的RootResource,或者EC2大小、EBS卷大小等,那么您不能只使用命名约定。您需要导出该值并导入它。在上面的例子中,我可以用命名约定替换RestApiId的导入用法,但是我不能用约定替换ParentId——我必须执行导入。

我在我的模板中混合使用这两种方法-当你建立经验时,你会发现使用一种方法比另一种方法更有意义。

最新更新