LocalStackを用いたAPI Gateway+Lambda+DynamoDB API作成方法 メモ


  • LocalStackを用いて、DynamoDBにデータ登録を行うAPIをAPI Gateway + Lambdaで作成する方法についてメモする。

LocalStack 準備

  • こちらの手順でDocker LocalStack環境を準備しておく。

Dynamo DB 準備

  • テーブル(sample-table)作成
  aws dynamodb create-table --table-name sample-table --attribute-definitions AttributeName=Data,AttributeType=S --key-schema AttributeName=Data,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 --endpoint-url=http://localhost:4569 --profile localstack

  {
      "TableDescription": {
          "AttributeDefinitions": [
              {
                  "AttributeName": "Data",
                  "AttributeType": "S"
              }
          ],
          "TableName": "sample-table",
          "KeySchema": [
              {
                  "AttributeName": "Data",
                  "KeyType": "HASH"
              }
          ],
          "TableStatus": "ACTIVE",
          "CreationDateTime": "2021-10-09T14:55:59.763000+09:00",
          "ProvisionedThroughput": {
              "LastIncreaseDateTime": "1970-01-01T09:00:00+09:00",
              "LastDecreaseDateTime": "1970-01-01T09:00:00+09:00",
              "NumberOfDecreasesToday": 0,
              "ReadCapacityUnits": 1,
              "WriteCapacityUnits": 1
          },
          "TableSizeBytes": 0,
          "ItemCount": 0,
          "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/sample-table"
      }
  }
  • 動作確認(データ登録)
  aws dynamodb put-item --table-name sample-table --item={\"Data\":{\"S\":\"fuga\"}}  --endpoint-url=http://localhost:4569 --profile localstack
  • 登録データ確認

    aws dynamodb scan --table-name sample-table --endpoint-url=http://localhost:4569 --profile localstack
    {
        "Items": [
            {
                "Data": {
                    "S": "fuga"
                }
            }
        ],
        "Count": 1,
        "ScannedCount": 1,
        "ConsumedCapacity": null
    }
    

API Gateway 準備

  • REST API を作成する

    • リソースID(id)を控える
    aws apigateway create-rest-api --name 'LambdaDynamoDBTestAPI' --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
    {
        "id": "0157166521",
        "name": "'LambdaDynamoDBTestAPI'",
        "createdDate": "2021-10-09T06:01:05.462000+00:00"
    }
    
  • ルートリソースID(以下id)取得

  aws apigateway get-resources --rest-api-id 0157166521 --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "items": [
          {
              "id": "4739445932",
              "path": "/",
              "resourceMethods": {
                  "GET": {}
              }
          }
      ]
  }
  • 子リソース追加

パス名:lambda_dynamodb_test

リソースID(以下id)を控える。

  aws apigateway create-resource --rest-api-id 0157166521 --parent-id 4739445932 --path-part lambda_dynamodb_test --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "id": "A-Z13318A-Z712",
      "parentId": "4739445932",
      "pathPart": "lambda_dynamodb_test",
      "path": "/lambda_dynamodb_test",
      "resourceMethods": {
          "GET": {}
      }
  }
  • HTTP POSTメソッド追加
  aws apigateway put-method --rest-api-id 0157166521 --resource-id A-Z13318A-Z712 --http-method POST --authorization-type "NONE" --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
  {
      "httpMethod": "POST",
      "authorizationType": "NONE"
  }

Lambda 準備

  • lambda_dynamodb_put_test.py

DynamoDBテーブルsample-tableにデータを登録する。

  import boto3
  from boto3.session import Session
  from datetime import datetime 

  session = Session(aws_access_key_id='dummy',
      aws_secret_access_key='dummy',
      region_name='ap-northeast-1'
  )

  dynamodb = session.resource(
      service_name='dynamodb', 
      endpoint_url='http://localhost:4569'
  )

  def lambda_handler(event, context):
      table = dynamodb.Table('sample-table')
      data = 'sample_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
      response = table.put_item(
         Item={
              'Data': data
          }
      )
      return response
  • 上記ファイルをlambda_dynamodb_put_test.zipにzip化する。

  • アップロード

  aws lambda create-function --function-name="lambda-dynamodb-put" --runtime=python3.8 --role="arn:aws:iam::123456789012:role/service-role/lambda-sample-role" --handler=lambda_dynamodb_put_test.lambda_handler --zip-file fileb://lambda_dynamodb_put_test.zip --endpoint-url=http://localhost:4574 --profile=localstack
  • 起動
aws lambda invoke --cli-binary-format raw-in-base64-out --function-name lambda-dynamodb-put result.log --endpoint-url=http://localhost:4574 --profile=localstack

{"StatusCode": 200}
  • 動作確認
aws dynamodb scan --table-name sample-table --endpoint-url=http://localhost:4569 --profile localstack

{
    "Items": [
        {
            "Data": {
                "S": "fuga"
            }
        },
        {
            "Data": {
                "S": "sample_2021-10-09-06-38-16"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2,
    "ConsumedCapacity": null
}

※データが追加されている。

API Gateway - Lambda 設定

  • Lambda ARN確認
  aws lambda list-functions --endpoint-url=http://localhost:4574 --profile=localstack{    "Functions": [        {            "FunctionName": "lambda-dynamodb-put",            "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:lambda-dynamodb-put",            "Runtime": "python3.8",            "Handler": "lambda_dynamodb_put_test.lambda_handler",            "Timeout": 60,            "Version": "$LATEST"        }    ]}
  • API Gateway - Lambda設定
  aws apigateway put-integration --rest-api-id 0157166521 --resource-id A-Z13318A-Z712 --http-method POST --type AWS_PROXY --integration-http-method POST --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:lambda-dynamodb-put/invocations --passthrough-behavior WHEN_NO_MATCH --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack {    "type": "AWS_PROXY",    "httpMethod": "POST",    "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:lambda-dynamodb-put/invocations",    "integrationResponses": {        "200": {            "statusCode": 200,            "responseTemplates": {                "application/json": null            }        }    }}
  • 設定デプロイ
  aws apigateway create-deployment --rest-api-id 0157166521 --stage-name test --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack{    "id": "1850348379",    "description": "",    "createdDate": "2021-10-09T06:43:04.032000+00:00"}

動作確認

  • APIリクエスト
POST /restapis/0157166521/test/_user_request_/lambda_dynamodb_test HTTP/1.1
Host: localhost:4567
Content-Type: application/json
Content-Length: 2

{}
  • APIレスポンス
{"ResponseMetadata": {"RetryAttempts": 0, "HTTPStatusCode": 200, "RequestId": "9f2c5ca3-6187-4d92-811d-5cd62c5f5289", "HTTPHeaders": {"x-amzn-requestid": "9f2c5ca3-6187-4d92-811d-5cd62c5f5289", "content-length": "2", "access-control-allow-methods": "HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH", "server": "BaseHTTP/0.3 Python/2.7.13, Jetty(8.1.12.v20130726)", "x-amz-crc32": "2745614147", "date": "Sat, 09 Oct 2021 06:44:22 GMT", "access-control-allow-origin": "*", "access-control-allow-headers": "authorization,content-type,content-md5,x-amz-content-sha256,x-amz-date,x-amz-security-token,x-amz-user-agent", "content-type": "application/x-amz-json-1.0"}}}
  • DynamoDB登録データ確認
aws dynamodb scan --table-name sample-table --endpoint-url=http://localhost:4569 --profile localstack

{
    "Items": [
        {
            "Data": {
                "S": "fuga"
            }
        },
        {
            "Data": {
                "S": "sample_2021-10-09-06-38-16"
            }
        },
        {
            "Data": {
                "S": "sample_2021-10-09-06-44-22"
            }
        }
    ],
    "Count": 3,
    "ScannedCount": 3,
    "ConsumedCapacity": null
}

※データが追加されている。

参考情報