既に作成済みのCloudFormationのAPIGateway用テンプレートを改修する対応が必要な場面があったのですが、その際にはまったポイントがありました。
CloudFormationでAPIGatwayを作成
まずは公式のサンプルテンプレートを参考に、APIGatewayをとりあえずデプロイします。
作成するリソースは、「RestApi」「Mehthod」「Deployment」の3種類とします。
次のようなテンプレートを使用します。
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Parameters:
apiName:
Type: String
Default: TestApi
Resources:
MyRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Ref apiName
MyRestApiMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref MyRestApi
ResourceId: !GetAtt MyRestApi.RootResourceId
HttpMethod: GET
AuthorizationType: NONE
RequestParameters:
method.request.header.myheader: false
Integration:
Type: MOCK
RequestTemplates:
application/json: "{\"statusCode\": 200}"
RequestParameters:
integration.request.header.header1: method.request.header.myheader
IntegrationResponses:
- StatusCode: '200'
ResponseParameters:
method.response.header.header1: integration.response.header.header1
method.response.header.header2: '''staticvalue'''
MethodResponses:
- StatusCode: '200'
ResponseParameters:
method.response.header.header1: true
method.response.header.header2: true
MyRestApiDeployment:
Type: 'AWS::ApiGateway::Deployment'
DependsOn:
- MyRestApiMethod
Properties:
RestApiId: !Ref MyRestApi
Description: My deployment
StageName: TestStage
正常にデプロイされていると、次のような応答が返されるはずです。
$ curl -i "https://iemix5tpg8.execute-api.ap-northeast-1.amazonaws.com/TestStage/"
HTTP/2 200
CloudFormationを改修する
上記のテンプレートに対し、追加のリソースとメソッドを作成してみます。
テンプレートの末尾にMyRestApiResourceとMyRestApiResourceMethodを追加しました。
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Parameters:
apiName:
Type: String
Default: TestApi
Resources:
MyRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Ref apiName
MyRestApiDeployment:
Type: 'AWS::ApiGateway::Deployment'
DependsOn:
- MyRestApiMethod
- MyRestApiResourceMethod
Properties:
RestApiId: !Ref MyRestApi
Description: My deployment
StageName: TestStage
MyRestApiMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref MyRestApi
ResourceId: !GetAtt MyRestApi.RootResourceId
HttpMethod: GET
AuthorizationType: NONE
RequestParameters:
method.request.header.myheader: false
Integration:
Type: MOCK
RequestTemplates:
application/json: "{\"statusCode\": 200}"
RequestParameters:
integration.request.header.header1: method.request.header.myheader
IntegrationResponses:
- StatusCode: '200'
ResponseParameters:
method.response.header.header1: integration.response.header.header1
method.response.header.header2: '''staticvalue'''
MethodResponses:
- StatusCode: '200'
ResponseParameters:
method.response.header.header1: true
method.response.header.header2: true
MyRestApiResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref MyRestApi
ParentId: !GetAtt
- MyRestApi
- RootResourceId
PathPart: resource1
MyRestApiResourceMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref MyRestApi
ResourceId: !Ref MyRestApiResource
HttpMethod: GET
AuthorizationType: NONE
RequestParameters:
method.request.header.myheader: false
Integration:
Type: MOCK
RequestTemplates:
application/json: "{\"statusCode\": 200}"
RequestParameters:
integration.request.header.header1: method.request.header.myheader
IntegrationResponses:
- StatusCode: '200'
ResponseParameters:
method.response.header.header1: integration.response.header.header1
method.response.header.header2: '''staticvalue'''
MethodResponses:
- StatusCode: '200'
ResponseParameters:
method.response.header.header1: true
method.response.header.header2: true
CloudFormationのデプロイを実行後、同じように確認コマンドを実行します。
すると、以下の通り、レスポンスコード200が返されません。
$ curl -i "https://iemix5tpg8.execute-api.ap-northeast-1.amazonaws.com/TestStage/resource1"
HTTP/2 403
この理由は、コンソール画面のステージメニューをみるとわかります。
CloudFormation上で追加したリソースとメソッドがステージにデプロイされていない状況であることがわかります。
CloudFormationのテンプレートを改修して、アップデートするだけではデプロイまでは自動で行われないのです。

解決方法
CloudFormationのアップデートのタイミングでデプロイまで自動で行うためには、デプロイメントを新規に作成しなおす必要があります。
したがって、CloudFormation上の論理IDを変更する必要があります。
論理IDを変更することで、CloudFormation上では別リソースと解釈され、新しい物理IDを持ったデプロイメントが作成されます。
具体的には、次のようにDeploymentリソースを修正します。
MyRestApiDeployment2: ## MyRestApiDeployment から MyRestApiDeployment2に論理IDを変更
Type: 'AWS::ApiGateway::Deployment'
DependsOn:
- MyRestApiMethod
- MyRestApiResourceMethod
Properties:
RestApiId: !Ref MyRestApi
Description: My deployment 2
StageName: TestStage
修正後のテンプレートをデプロイすると、正しくリソースとメソッドがデプロイされました。
この時、デプロイ履歴から確認できるデプロイID(デプロイメントの物理ID)も変更されています。

curlコマンドによる確認も問題なく動作しました。
$ curl -i "https://iemix5tpg8.execute-api.ap-northeast-1.amazonaws.com/TestStage/resource1"
HTTP/2 200
以上のような方法で、API Gatewayの自動デプロイメントを実現できました。
また、後の調査でわかったことではありますが、APIGatewayのステージのリソースでAWS::ApiGatewayV2::Stageを使用し、AutoDeployフィールドをtrueに設定する方法もあるようです。
参考:https://dev.classmethod.jp/articles/tsnote-cloudformation-autodeploy/
AWS::ApiGatewayのリソースで既にテンプレートが作られてしまっている場合などに本記事で紹介した方法の利用は限られそうです。
コメント