在 AWS cloudformation 上理解 Apigateway 和嵌套堆栈时出错

Posted

技术标签:

【中文标题】在 AWS cloudformation 上理解 Apigateway 和嵌套堆栈时出错【英文标题】:Error understanding Apigateway and nested stack on AWS cloudformation 【发布时间】:2022-01-24 00:52:15 【问题描述】:

我正在努力将一个大模板与使用 apigateway AWS 的 lambda 解耦。我解决了有关嵌套堆栈过程的多个错误,但目前错误并不清楚。你能检查一下定义中的问题吗?

主堆栈显示来自 api 子堆栈创建的一般错误,但 api-substack 显示下一个错误:

Template error: instance of Fn::Sub references invalid resource attribute CreateCatalogFunctionDev.Arn

接下来展示模板代码:

主模板

  SubStackAPIDev:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: https://s3.awsroute.com/substack-api.yaml
      TimeoutInMinutes: 5      
      Parameters:
        CreateCatalogFunctionDev: !GetAtt CreateCatalogFunctionDev.Outputs.CreateCatalogFunctionDev
      
      
  SubStackCreateCatalogDev:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: https://s3.awsroute.com/substack-create-catalog.yaml
      TimeoutInMinutes: 5
      Parameters:
        APIDev: !GetAtt SubStackAPIDev.Outputs.APIGateway

SubStackCreateCatalogDev

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Description: >
  SAM template for create catalog


Parameters:
  SecretsManagerName:
    Type: String
    Description: "Secrets Manager Name"
  SnsTopicArn:
    Type: String
    Default: arn:aws:sns:us-west-2:XXXXXX:SNS-errorNotification
    Description: "Sns topic error handler email notification"
  APIDev:
    Type: AWS::Serverless::Api
    
Resources:
  LayerDev:
    Type: 'AWS::Serverless::LayerVersion'
    Properties:
      ContentUri: ../../layer
      CompatibleRuntimes:
        - python3.6
        - python3.7
        - python3.8
      RetentionPolicy: Delete
  CreateCatalogFunctionDev:
    Type: AWS::Serverless::Function
    Properties:
      Description: Recieve api request and and process data.
      CodeUri: ../../src/catalog/create_catalog/
      Handler: create_catalog.lambda_handler
      Runtime: python3.8
      FunctionName: CreateCatalogFunctionDev
      Role: arn:aws:iam::XXXXXXXX:role/lambda-essential-role
      Timeout: 480
      Environment:
        Variables:
          CREATE_CATALOG_SECRET_NAME: !Sub '$SecretsManagerName'
          SNS_ARN: !Sub '$SnsTopicArn'
      Layers:
        - arn:aws:lambda:us-west-2:XXXXXXX:layer:requests:1
        - arn:aws:lambda:us-west-2:XXXXXXX:layer:requests-oauthlib:1
        - !Ref LayerDev
      Events:
        CreateCatalogApiEvent:
          Type: Api
          Properties:
            Path: /api-channel/products/catalog
            Method: POST
            RestApiId: !Ref APIDev

子栈 API

AWSTemplateFormatVersion: "2010-09-09"

Transform: AWS::Serverless-2016-10-31

Description: >
  sub_channels_appi
   SAM template for API

Parameters:
  SwaggerFile:
    Type: String
    # TODO dejar URL de S3 de gitla-cicd
    Default: "s3://cf-templates-1hurrmgzyzoz3-ap-northeast-1/swagger_dev.yaml"
    Description: "This swagger file Amazon S3 path"
  SecretsManagerName:
    Type: String
    Default: "/channels/Dev"
    Description: "Secrets Manager Name"
  StageName:
    Type: String
    Default: "$stageVariables.alias"
    Description: "This is the alias to the swagger file"
  UsaSupplyApiUrlDev:
    Type: String
    Default: "https://thecornercloud.com/developers/index.php/"
    Description: "Corner Cloud Staging"
  SnsTopicArn:
    Type: String
    Default: arn:aws:sns:us-west-2:000365055762:channels-errorNotification
    Description: "Sns topic error handler email notification"
  CreateCatalogFunctionDev:
    Type: String

Resources:
  #######################################
  # Serverless LayerVersion
  #######################################
  LayerDev:
    Type: 'AWS::Serverless::LayerVersion'
    Properties:
      ContentUri: ../../layer
      CompatibleRuntimes:
        - python3.6
        - python3.7
        - python3.8
      RetentionPolicy: Delete

  #######################################
  # Serverless API
  #######################################
  APIDev:
    Type: AWS::Serverless::Api
    Properties:
      Auth:
        ApiKeyRequired: true
      StageName: dev
      EndpointConfiguration: REGIONAL
      DefinitionBody:
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: !Ref SwaggerFile
      Variables:
        alias: dev

  #######################################
  # ApiGateway ApiKey
  #######################################
  APIKeyDev:
    Type: AWS::ApiGateway::ApiKey
    Properties:
      Name: "APIKeyDev"
      Description: "API Key Dev"
      Enabled: true
      GenerateDistinctId: false
      StageKeys:
        - RestApiId: !Ref APIDev
          StageName: !Ref APIDev.Stage

  #######################################
  # ApiGateway UsagePlan
  #######################################
  APIUsagePlanDev:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn: APIDev
    Properties:
      ApiStages:
        - ApiId: !Ref APIDev
          Stage: !Ref APIDev.Stage
      Quota:
        Limit: 5000
        Period: MONTH
      Throttle:
        BurstLimit: 200
        RateLimit: 100
      UsagePlanName: APIUsagePlanDev
  #######################################
  # ApiGateway UsagePlanKey
  #######################################
  APIUsagePlanKeyDev:
    Type: AWS::ApiGateway::UsagePlanKey
    Properties:
      KeyId: !Ref APIKeyDev
      KeyType: API_KEY
      UsagePlanId: !Ref APIUsagePlanDev

  #######################################
  # ApiGateway Deployment
  #######################################
  DeploymentApiIdDev:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref APIDev 
Outputs:

  APIGateway:
    Description: "API Gateway Reference"
    Value: !Ref APIDev
    Export:
      Name: !Join [":", [!Ref "AWS::StackName", "APIDev"]]

最后是 swagger 文件(老实说,我没有用这种方法定义 api,并认为如果可能的话我想删除 swagger)。 swagger-开发

swagger: "2.0"
info:
  version: "1.0.0"
  title: "APIDev"
tags:
  - name: "Channels"
    description: "Manage Channels process."
schemes:
  - "https"
x-amazon-apigateway-api-key-source: "HEADER"
securityDefinitions:
  APIKey:
    type: apiKey
    name: X-Api-Key
    in: header 
paths:
  /channels/products/catalog:
    post:
      tags:
        - "Channels"
      summary: " products catalog post."
      operationId: "ProductsCatalogPostDev"
      produces:
        - "application/json"
      responses:
        201:
          description: "Successful Operation"
        400:
          description: "Invalid parameters"
        401:
          description: "Unauthorized"
        405:
          description: "Validation exception"
      security:
        - APIKey: []
      x-amazon-apigateway-integration:
        uri:
          Fn::Sub: arn:aws:apigateway:$AWS::Region:lambda:path/2015-03-31/functions/$CreateCatalogFunctionDev.Arn/invocations
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"

【问题讨论】:

【参考方案1】:

您的CreateCatalogFunctionDev 位于不同的子堆栈,然后是APIDev。您不能直接跨堆栈引用资源。您要么必须导出/导入它们的输出,要么将引用作为输入参数传递。

【讨论】:

据此,我可以像 APIDev 一样在主堆栈中传递 CreateCatalogFunctionDev 吗?我有其他子堆栈,它需要大摇大摆地定义 * Fn::Sub *? @JuanCarlosAlfonsoVergel 是的,如果它的嵌套堆栈。 我尝试了,但返回下一个错误:: Error: Failed to create changeset for the stack: Channels-dev, An error occurred (ValidationError) when calling the CreateChangeSet operation: Circular dependency between resources: [SubStackAPIDev, SubStackCreateCatalogDev].......我修改了 Initial ask 以显示我如何更改主模板

以上是关于在 AWS cloudformation 上理解 Apigateway 和嵌套堆栈时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AWS CloudFormation 在 AWS API Gateway 上应用安全策略?

如何使用 cloudformation 在 AWS cognito 上设置验证属性?

AWS cloudFormation LAMP 堆栈失败

带有 CloudFormation 的 AWS Cognito - 架构属性上的 InvalidParameterException

AWS CLI 与控制台和 CloudFormation 堆栈

AWS 中的 cloudformation 最佳实践