下記のAWSのブログで紹介されていたサーバレスアプリケーションを試してみました。
AWS SAM Local(ベータ版) – サーバーレスアプリケーションをローカルに構築してテストするAWS SAM Local と DynamoDB Local は、VirtualBoxの同じサーバ(CentOS7)で実行します。
1. ローカルにLambda の用意
AWS SAM Local のインストールは、こちらを参照。
template.yaml は以下のとおり。
AWSブログのものを、少し変えています。
Events に GetVotes を追加しました。
AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: VotesTable: Type: "AWS::Serverless::SimpleTable" VoteSpacesTabs: Type: "AWS::Serverless::Function" Properties: Runtime: python2.7 Handler: vote_function.vote_handler Policies: AmazonDynamoDBFullAccess Environment: Variables: TABLE_NAME: !Ref VotesTable Events: GetVotes: Properties: Method: get Path: / Type: Api Vote: Type: Api Properties: Path: / Method: post
lambdaのソースコードは、以下のとおり。
AWS SAM Local で lambda を実行した場合は、DynamoDB の接続先(endpoint) をローカルのDynamoDB しています。
192.168.56.102 は、DynamoDBが起動するローカルのIPアドレスです。
ここを、localhost にすると、AWS SAM Local で lambda が実行される Dockerコンテナ を意味し、ローカルのDynamoDB に接続できないので注意。
import os import json import boto3 def vote_handler(event, context): if os.getenv("AWS_SAM_LOCAL"): votes_table = boto3.resource( 'dynamodb', endpoint_url="http://192.168.56.102:8000/" ).Table("spaces-tabs-votes") else: votes_table = boto3.resource('dynamodb').Table(os.getenv('TABLE_NAME')) if event['httpMethod'] == 'GET': resp = votes_table.scan() return {'body': json.dumps({item['id']: int(item['votes']) for item in resp['Items']})} elif event['httpMethod'] == 'POST': try: body = json.loads(event['body']) except: return {'statusCode': 400, 'body': 'malformed json input'} if 'vote' not in body: return {'statusCode': 400, 'body': 'missing vote in request body'} if body['vote'] not in ['spaces', 'tabs']: return {'statusCode': 400, 'body': 'vote value must be "spaces" or "tabs"'} resp = votes_table.update_item( Key={'id': body['vote']}, UpdateExpression='ADD votes :incr', ExpressionAttributeValues={':incr': 1}, ReturnValues='ALL_NEW' ) return {'body': "{} now has {} votes".format(body['vote'], resp['Attributes']['votes'])}
用意したファイルは以下のとおり。
[root@centos702 lambda5]# ls template.yaml vote_function.py
2. ローカルに DynamoDB の用意
dynamodb ディレクトリを作成して、そこにDynamoDBをインストールします。
[root@centos702 ~]# mkdir dynamodb [root@centos702 ~]# cd dynamodb/ [root@centos702 dynamodb]# curl -OL https://s3-ap-northeast-1.amazonaws.com/dynamodb-local-tokyo/dynamodb_local_latest.tar.gz % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 16.2M 100 16.2M 0 0 3551k 0 0:00:04 0:00:04 --:--:-- 4084k [root@centos702 dynamodb]# tar xfz dynamodb_local_latest.tar.gz [root@centos702 dynamodb]# ls DynamoDBLocal.jar DynamoDBLocal_lib LICENSE.txt README.txt dynamodb_local_latest.tar.gz third_party_licenses
以下のようにコマンドを実行して、DynamoDBを起動します。
[root@centos702 dynamodb]# java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb Initializing DynamoDB Local with the following configuration: Port: 8000 InMemory: false DbPath: null SharedDb: true shouldDelayTransientStatuses: false CorsParams: *
別のターミナルを開きます。
以下のようにコマンドを実行して、DynamoDBにテーブルを作成します。
[root@centos702 lambda5]# aws dynamodb create-table --table-name spaces-tabs-votes --attribute-definitions AttributeName=id,AttributeType=S --key-schema AttributeName=id,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 --output table --endpoint-url http://localhost:8000 ------------------------------------------------------------------------------------------ | CreateTable | +----------------------------------------------------------------------------------------+ || TableDescription || |+------------------+-------------------------------------------------------------------+| || CreationDateTime| 1518857833.28 || || ItemCount | 0 || || TableArn | arn:aws:dynamodb:ddblocal:000000000000:table/spaces-tabs-votes || || TableName | spaces-tabs-votes || || TableSizeBytes | 0 || || TableStatus | ACTIVE || |+------------------+-------------------------------------------------------------------+| ||| AttributeDefinitions ||| ||+--------------------------------------------------------------+---------------------+|| ||| AttributeName | id ||| ||| AttributeType | S ||| ||+--------------------------------------------------------------+---------------------+|| ||| KeySchema ||| ||+--------------------------------------------------------+---------------------------+|| ||| AttributeName | id ||| ||| KeyType | HASH ||| ||+--------------------------------------------------------+---------------------------+|| ||| ProvisionedThroughput ||| ||+------------------------------------------------------------------+-----------------+|| ||| LastDecreaseDateTime | 0.0 ||| ||| LastIncreaseDateTime | 0.0 ||| ||| NumberOfDecreasesToday | 0 ||| ||| ReadCapacityUnits | 1 ||| ||| WriteCapacityUnits | 1 ||| ||+------------------------------------------------------------------+-----------------+|| [root@centos702 lambda5]#
3. ローカルに API Gateway の用意
以下のようにコマンドを実行して AMS SAM Local の API Gateway を起動します。
API Gateway にアクセスすると、ここに、ログが表示されます。
[root@centos702 lambda5]# sam local start-api A newer version of the AWS SAM CLI is available! Your version: 0.2.4 Latest version: 0.2.6 See https://github.com/awslabs/aws-sam-local for upgrade instructions 2018/02/17 18:15:27 Connected to Docker 1.35 2018/02/17 18:15:27 Fetching lambci/lambda:python2.7 image for python2.7 runtime... python2.7: Pulling from lambci/lambda Digest: sha256:87a3b9bb1ba6ae666b0087107852b67415cae0660669ae5633a0ab828aea2c69 Status: Image is up to date for lambci/lambda:python2.7 Mounting vote_function.vote_handler (python2.7) at http://127.0.0.1:3000/ [GET] Mounting vote_function.vote_handler (python2.7) at http://127.0.0.1:3000/ [POST] You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template.
4. 動作確認
API Gateway に POST メソッドでアクセスし、"tabs" に投票します。
lambda が実行されて、DynamoDBが更新されます。
[root@centos702 lambda5]# curl -XPOST -d '{"vote": "tabs"}' http://127.0.0.1:3000/ tabs now has 3 votes
API Gateway には、以下のようにログが表示されます。
2018/02/17 18:16:22 Invoking vote_function.vote_handler (python2.7) 2018/02/17 18:16:22 Mounting /root/lambda5 as /var/task:ro inside runtime container START RequestId: 6e24834b-e125-413a-ac8b-bbd219b7b77d Version: $LATEST END RequestId: 6e24834b-e125-413a-ac8b-bbd219b7b77d REPORT RequestId: 6e24834b-e125-413a-ac8b-bbd219b7b77d Duration: 1068 ms Billed Duration: 0 ms Memory Size: 0 MB Max Memory Used: 23 MB
API Gateway に GET メソッドでアクセスし、"tabs" の投票数を参照します。
[root@centos702 lambda5]# curl -XGET -d '{"vote": "tabs"}' http://127.0.0.1:3000/ {"tabs": 3}