【CloudFormation/SAM】既存の API Gateway(REST API) を AWS::Serverless::Api としてインポートする

記事タイトルとURLをコピーする

サービス開発部兼ドラクエ部のくればやしです。

今度、淡路島のニジゲンノモリというところにある[ドラゴンクエスト アイランドに遊びに行く予定です。アトラクションもさることながら、グッズコーナーに行くのも非常に楽しみです。

nijigennomori.com

はじめに

前回の記事では、既存のLambda関数をAWS::Serverless::Function としてインポートする方法を解説しました。

blog.serverworks.co.jp

本記事では一歩進んで、API Gateway(REST API)をAWS::Serverless::Api としてインポートする方法を解説したいと思います。

インポートの方法

サンプルとして以下のモックのメソッドが1つあるリソースを考えます。

素のCloudFormationの場合

まず、基本として、素のCloudFormationのテンプレートとしてインポートする場合を確認します。 以下のようなテンプレートを用意してインポートできます。

cfn_template.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: The AWS CloudFormation template
Resources:
  ApiGatewayRestApi:
    Type: AWS::ApiGateway::RestApi
    DeletionPolicy: Retain
import.json
[
    {
        "ResourceType": "AWS::ApiGateway::RestApi",
        "LogicalResourceId": "ApiGatewayRestApi",
        "ResourceIdentifier": {
            "RestApiId": "xxxxxxx"
        }
    }
]
インポートコマンド(例)
aws cloudformation create-change-set \
  --stack-name tmp \
  --change-set-name import1 \
  --change-set-type IMPORT \
  --template-body file://cfn_template.yml \
  --resources-to-import file://import.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-east-1

SAMの場合

SAMテンプレートの場合は、テンプレートのプロパティにStageNameの指定が必須となります。

sam_template.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: The AWS CloudFormation template for this Serverless application
Transform: AWS::Serverless-2016-10-31

Resources:
  ApiGatewayRestApi:
    Type: AWS::Serverless::Api
    DeletionPolicy: Retain
    Properties:
      StageName: prod
import_sam.json

またインポート時に指定する実リソースとの紐づけ用のファイルにはAPI Gatewayに加えて、Deployment と Stage の指定が必要になります。 Deployment の論理IDを確認する方法が分かりませんでしたが、インポート時に AWS::ApiGateway::Deployment の指定無しで行うとエラーの表示部分にIDが表示されます。(他に方法があるかもしれません)

[
    {
        "ResourceType": "AWS::ApiGateway::RestApi",
        "LogicalResourceId": "ApiGatewayRestApi",
        "ResourceIdentifier": {
            "RestApiId": "xxxx"
        }
    },
    {
        "ResourceType": "AWS::ApiGateway::Deployment",
        "LogicalResourceId": "ApiGatewayRestApiDeploymentddddddd",
        "ResourceIdentifier": {
            "DeploymentId":"ddddd",
            "RestApiId": "xxxx"
        }
    },
    {
        "ResourceType": "AWS::ApiGateway::Stage",
        "LogicalResourceId":"ApiGatewayRestApiprodStage",
        "ResourceIdentifier": {
            "StageName":"prod",
            "RestApiId": "xxxx"
        }
    }
]
インポートコマンド(例)
aws cloudformation create-change-set \
  --stack-name tmp \
  --change-set-name import2 \
  --change-set-type IMPORT \
  --template-body file://sam_template.yml \
  --resources-to-import file://import_sam.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --region us-east-1

メソッドのインポート

上述のような指定でAPI Gatewayのインポートは可能になります。しかし、上述のように実施すると、API Gatewayのメソッドが削除されてしまうと思います。

メソッドも合わせてインポートするにはテンプレートファイルに DefinitionBody を追加し、メソッドの定義を追加した上でインポートすると、メソッドも合わせてインポートできます。

AWSTemplateFormatVersion: "2010-09-09"
Description: The AWS CloudFormation template for this Serverless application
Transform: AWS::Serverless-2016-10-31

Resources:
  ApiGatewayRestApi:
    Type: AWS::Serverless::Api
    DeletionPolicy: Retain
    Properties:
      StageName: prod
      DefinitionBody:
        swagger: "2.0"
        info:
          title: "tmp"
        paths:
          /:
            get:
              x-amazon-apigateway-integration:
                type: mock
                httpMethod: GET
                uri: arn:aws:execute-api:us-east-1:xxxxxxxxxxxxxxxxx:dddddddd/*/GET/

"AWS::ApiGateway::Method" リソースを別でテンプレートファイルに記載する方法も試してみましたが、こちらはインポート処理時にエラー(NotFoundException)となってしまいました。SAMリソースとしてインポートする場合は上述のような定義でインポートする必要があるようです。

メソッドの統合タイプがLambda関数で、Eventsプロパティにメソッドを定義する場合

また、メソッドの統合タイプをLambdaにした場合は、 "AWS::Serverless::Function" を同時にインポートし、そのEventsにメソッドの定義を記載することでメソッドをインポートすることも可能のようです。(この場合は前述のようなAPI Gatewayの DefinitionBody の定義は不要)

HelloLambdaFunction:
  Type: AWS::Serverless::Function
  DeletionPolicy: Retain
  Properties:
    CodeUri: s3://xxxxxxxxxxx/xxxxx.zip
    Handler: handler.hello
    Runtime: python3.12
    FunctionName: xxxxxxxx
    Events:
      ApiEvent:
        Type: Api
        Properties:
          RestApiId: !Ref ApiGatewayRestApi
          Path: /
          Method: GET

おわりに

今回、既存のAPI GatewayをAWS::Serverless::Api としてインポートする方法を解説しました。どなたかの一助になれば幸いです。

紅林輝(くればやしあきら)(サービス開発部) 記事一覧

サービス開発部所属。2015年にサーバーワークスにJOIN。クラウドインテグレーション部を経て、現在はCloud Automatorの開発に従事。ドラクエ部。推しナンバーはⅤ、推しモンスターはクックルー。