API 带有 SAM 的网关未正确更新

API Gateway with SAM isn't updated correctly

我们使用 Cloud Formation 来定义一堆 Lambda 函数:

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

Resources:
  MyLambda:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: com.handler::MyLambda
      Runtime: java8
      CodeUri: .
      Description: Some desc
      MemorySize: 512
      Timeout: 15
      Role: !Ref LambdaRole
      FunctionName: MyLambda
      Events:
        MyLambdaEvt:
          Type: Api
          Properties:
            RestApiId: !Ref MyApiDef
            Path: /lambda/my
            Method: get

  MyApiDef:
    Type: AWS::Serverless::Api
    Properties:
      DefinitionUri: s3://a-bucket/api-gateway.yml
      StageName: prod

Outputs:
  ApiUrl:
    Description: URL of your API endpoint
    Value: !Join
      - ''
      - - https://
        - !Ref MyApiDef
        - '.execute-api.'
        - !Ref 'AWS::Region'
        - '.amazonaws.com/prod'

CodePipeline 生成变更集并执行它。

通过这种方式,所有 Lambda 函数都已正确更新,但 API 网关端点未正确更新,我们需要在 s3://a-bucket/api-gateway.yml 中手动导入和部署 YML。

为什么 API 不更新(有根据的猜测)

为了将更改添加到 change set,CloudFormation 必须检测更改。如果部署之间唯一发生变化的(MyApiDef)是 S3 上的 .yaml 文件的内容,CloudFormation 将不会检测到它需要添加到更改集中的更改。

如果此 API 定义存在于 CF 模板中,而不是 S3 上的文件中,CF 将(显然)检测到每个更改并为您更新 API。

由于定义存在于 S3 中,并且文件名未更改,因此未检测到任何更改,因此不会更新任何内容。

可能的解决方法

您必须让 CloudFormation 相信您的 API 定义发生了一些变化。这两件事对我有用:

  • 更新 MyApiDef 密钥本身每个 运行 有效。 (MyApiDefv2, MyApiDefv3,等等)
  • 更新 DefinitionUri 有效。 (即版本 S3 中的文件名).

这两个都不是很好,但在 S3 中将版本附加到文件名似乎比其他选项更合理。

可能还有其他方法可以让 CloudFormation 相信发生了变化。值得注意的是,我可以 notVariables 为此目的工作。