AWSメモ >
aws-sdk と AWS CLI をインストールしておく。
AWSローカル開発環境の構築 を参照
# NPMでインストール npm install -g aws-sam-local # インストール(バージョン)確認 sam --version
「SAM Local は docker-lambda というカスタマイズされた Docker イメージを自動的に提供します」という事らしい。
http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/docker-basics.html
インストールガイドに従ってインストール
https://docs.docker.com/engine/installation/
参考)
http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBLocal.html
https://s3.ap-south-1.amazonaws.com/dynamodb-local-mumbai/dynamodb_local_latest.zip からダウンロード、解凍する。
DymanoDBの開始
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
※デフォルトでは localhost:8000 で動作する。
※AWS CLI で エンドポイント指定するか、http://localhost:8000/shell から各種操作が可能。
上記で起動した DynamoDB はホストOS上の 8000ポートで動作しているが、
sam local は docker上で動作する為、sam local から ローカルへの DynamoDB には
localhost:8000 という指定ではアクセスはできない。
なので、ローカルホストの IPアドレスを確認し、lo0 に 127.0.0.1 (localhost) 以外のアドレスが割り当たっていない場合は、以下の通り割り当てる。
sudo ifconfig lo0 alias 10.20.30.40/24※10.20.30.40/24 は 割り当てる IPアドレスとサブネットマスク
コマンド | 説明 | 補足 |
start-api | すべての Lambda 関数をホストするローカル HTTP サーバーを作成する。 | |
invoke | ローカル Lambda 関数を一度呼び出し、呼び出しの完了後に終了する。 | |
generate-event | 疑似サーバーレスイベントを生成する。 | |
validate | テンプレートを検証する。 | |
package および deploy | AM アプリケーションのパッケージングおよびデプロイメントを行う | http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/serverless-deploy-wt.html#serverless-deploy |
https://github.com/awslabs/serverless-application-model/tree/master/examples/2016-10-31/api_backend
book.js
'use strict'; var AWS = require('aws-sdk'); var dynamoOpt = {apiVersion: '2012-08-10'}; if (process.env.DYNAMO_REGION && process.env.DYNAMO_END_POINT) { dynamoOpt.region = process.env.DYNAMO_REGION; dynamoOpt.endpoint = process.env.DYNAMO_END_POINT; } var documentClient = new AWS.DynamoDB.DocumentClient(dynamoOpt); const createResponse = (callback, statusCode, body) => { var res = { "statusCode": statusCode, "body": JSON.stringify(body) } callback(null, res); } exports.handler = (event, context, callback) => { var req = event.body || event; if (typeof(req) === "string" && req !== "") { req = JSON.parse(req); } var id = false; if (event.pathParameters){ id = event.pathParameters.id || false; } switch(event.httpMethod){ case "GET": if(id && id > 0) { var params = { TableName : 'Books', FilterExpression : 'id = :id', ExpressionAttributeValues : {':id' : id } }; documentClient.scan(params, function(err, data) { if (err) { console.log(err); createResponse(callback, 500, { "msg": "Get Error!", "err": err}); } else { createResponse(callback, 200, data); console.log(data); } }); return; } else { var params = { TableName : 'Books' }; documentClient.scan(params, function(err, data) { if (err) { console.log(err); createResponse(callback, 500, { "msg": "List Error!", "err": err}); } else { createResponse(callback, 200, data); console.log(data); } }); } break; case "POST": var params = { TableName : 'Books', Item: { "id" : req.id, "isbn" : req.isbn, "title" : req.title, "price" : parseInt(req.price,10) } }; documentClient.put(params, function(err, data) { if (err) { console.log(err); createResponse(callback, 500, { "msg": "Create Error!", "err": err, "req": req}); } else { createResponse(callback, 200, { "msg": "Create OK!"}); } }); break; case "PUT": var params = { TableName : 'Books', Key: { "id" : id }, ExpressionAttributeNames: { "#isbn" : "isbn", "#title" : "title", "#price" : "price" }, ExpressionAttributeValues: { ":isbn" : req.isbn, ":title" : req.title, ":price" : parseInt(req.price, 10) }, UpdateExpression: "SET #isbn = :isbn, #title = :title, #price = :price" }; documentClient.update(params, function(err, data) { if (err) { console.log(err); console.log(data); createResponse(callback, 500, { "msg": "Update Error!", "err": err}); } else { createResponse(callback, 200, { "msg": "Update OK!"}); } }); break; case "DELETE": var params = { TableName : 'Books', Key: { "id" : id } }; documentClient.delete(params, function(err, data) { if (err) { console.log(err); console.log(data); createResponse(callback, 500, { "msg": "Delete Error!", "err": err}); } else { createResponse(callback, 200, { "msg": "Delete OK!"}); } }); break; default: console.log("Error: unsupported HTTP method (" + event.httpMethod + ")"); createResponse(callback, 501, { "msg": "Error: unsupported HTTP method (" + event.httpMethod + ")" } ); } }
template-local.yml
AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Test serverless application. Resources: BookFunction: Type: AWS::Serverless::Function Properties: Handler: book.handler Runtime: nodejs6.10 Environment: Variables: DYNAMO_END_POINT: http://10.20.30.40:8000 #上記で確認/設定したローカルのIPアドレス DYNAMO_REGION: localhost Events: List: Type: Api Properties: Path: /book Method: get Create: Type: Api Properties: Path: /book Method: post Update: Type: Api Properties: Path: /book/{id} Method: put Delete: Type: Api Properties: Path: /book/{id} Method: delete
sam local start-api --template template-local.yml
一覧
curl -v http://localhost:3000/book
登録
curl -v -XPOST --data '{ "id" : "A01", "isbn" : "ABC001", "title" : "テスト001", "price": 1008 }' http://localhost:3000/book
キー指定検索
curl -v http://localhost:3000/book/A01
更新(キー指定)
curl -v -XPUT --data '{ "id" : "A01", "isbn" : "ABC001", "title" : "テスト001", "price": 2016 }' http://localhost:3000/book/A01
削除(キー指定)
curl -v -XDELETE http://localhost:3000/book/A01
http://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/dynamodb-examples.html
http://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/lambda-examples.html
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/test-sam-local.html
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/test-sam-local.html#sam-cli-simple-app
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/deploying-lambda-apps.html
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/serverless-deploy-wt.html
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/automating-deployment.html