【问题标题】:Access to output data from stack访问堆栈中的输出数据
【发布时间】:2021-10-13 07:43:15
【问题描述】:

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

这可能吗?如果可以,怎么做?

【问题讨论】:

    标签: amazon-cloudformation aws-serverless aws-rest-api


    【解决方案1】:

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

    来自AWS Docs:

    要导出堆栈的输出值,请使用堆栈模板的输出部分中的导出字段。要导入这些值,请在其他堆栈的模板中使用 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 是这里的重要部分。如果您提供导出,则其他堆栈可以从中使用。

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

    来自AWS Docs:

    内部函数 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 堆栈之前尝试删除MyApi API 网关堆栈,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 参数更改,因此可以在开发、测试和生产中重复使用。

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

    我在我的模板中混合使用了这两种方法 - 你会发现在积累经验时使用一种方法而不是另一种方法更有意义。

    【讨论】:

      猜你喜欢
      • 2015-01-09
      • 2014-07-26
      • 2011-03-28
      • 1970-01-01
      • 2016-08-28
      • 2018-06-15
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多