Serverless Frameworkを用いてCRUDできるようにしたいと思います。
最終的なゴールはブラウザからCRUDできると良いのですが、今回はcurl
コマンドを使ってできるようにします。
こちらのチュートリアルを参考にやっていきます
aws-lambda Create Simple CRUD Operation
Lambdaはnodeを利用しています。
必要なもの
node, awscliが必要です。
nodeはanyenv
を利用してインストールしました。
バージョン
node15系を使っていたのですが、serverlessをデプロイしようとした時にエラーになってしまい、GitHubでもissueで解決されていないようでしたので、14系でやっています。
sls
とはServerless Frameworkを入れた後に使えるコマンドです。slsが短縮系なので特に違いはないらしいです。今は気にしなくても良いです。
$ node -v v14.15.4 $ aws --version aws-cli/2.1.24 Python/3.7.4 Darwin/20.2.0 exe/x86_64 prompt/off $ sls --version Framework Core: 2.22.0 Plugin: 4.4.2 SDK: 2.3.2 Components: 3.6.1
Serverless Frameworkのインストール
nodeが使えれば利用できるはずです
$ npm install serverless -g
AWSの認証情報を入力
aws configure
コマンドを使って自分の端末に認証情報を登録しましょう
以下のように入力して登録します。
リージョンは東京、データの型はjsonにしています
$ aws configure --profile user1 AWS Access Key ID [None]: {アクセスキー(各自)} AWS Secret Access Key [None]: {シークレットアクセスキー(各自)} Default region name [None]: ap-northeast-1 Default output format [None]: json
アプリケーション作成
下記のコマンドを入力して作成します。
serverless create --template aws-nodejs --path myService
コマンドを入力するとmyService
という名称のディレクトリが作られ、中にはserverless.yml, handler.jsがあるはずです。
他にもevent.json
が必要なのですが最新版だと作成されないので自分で作成します
vim event.json { "event": { "key3": "value3", "key2": "value2", "key1": "value1" } }
ファイル編集
serverless.ymlを以下のように書き変えます
チュートリアルとは違い東京リージョンで行います
service: serverless-crud provider: name: aws runtime: nodejs12.x region: ap-northeast-1 stage: dev iamRoleStatements: - Effect: Allow Action: - dynamodb:DescribeTable - dynamodb:Query - dynamodb:Scan - dynamodb:GetItem - dynamodb:PutItem - dynamodb:UpdateItem - dynamodb:DeleteItem Resource: "arn:aws:dynamodb:ap-northeast-1:*:*" functions: create: handler: handler.create events: - http: path: todos method: post cors: true readAll: handler: handler.readAll events: - http: path: todos method: get cors: true readOne: handler: handler.readOne events: - http: path: todos/{id} method: get cors: true update: handler: handler.update events: - http: path: todos/{id} method: put cors: true delete: handler: handler.delete events: - http: path: todos/{id} method: delete cors: true resources: Resources: TodosDynamoDbTable: Type: 'AWS::DynamoDB::Table' DeletionPolicy: Retain Properties: AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 TableName: 'todos'
DynamoDBのためのIAMとDynamoDBのテーブル、Lambdaを作成します
次にhandler.js
を書き換えます
'use strict'; const todosCreate = require('./lambda/todos-create.js'); const todosReadAll = require('./lambda/todos-read-all.js'); const todosReadOne = require('./lambda/todos-read-one.js'); const todosUpdate = require('./lambda/todos-update.js'); const todosDelete = require('./lambda/todos-delete.js'); module.exports.create = (event, context, callback) => { todosCreate(event, (error, result) => { const response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(result), }; context.succeed(response); }); }; module.exports.readAll = (event, context, callback) => { todosReadAll(event, (error, result) => { const response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(result), }; context.succeed(response); }); }; module.exports.readOne = (event, context, callback) => { todosReadOne(event, (error, result) => { const response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(result), }; context.succeed(response); }); }; module.exports.update = (event, context, callback) => { todosUpdate(event, (error, result) => { const response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(result), }; context.succeed(response); }); }; module.exports.delete = (event, context, callback) => { todosDelete(event, (error, result) => { const response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(result), }; context.succeed(response); }); };
次にCRUDの各Lambda関数を作成します
todos-create.js
'use strict'; const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); const uuid = require('uuid'); module.exports = (event, callback) => { const data = JSON.parse(event.body); data.id = uuid.v1(); data.updatedAt = new Date().getTime(); const params = { TableName: 'todos', Item: data }; return dynamoDb.put(params, (error, data) => { if (error) { callback(error); } callback(error, params.Item); }); };
todos-read-all.js
'use strict'; const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); module.exports = (event, callback) => { const params = { TableName: 'todos', }; return dynamoDb.scan(params, (error, data) => { if (error) { callback(error); } callback(error, data.Items); }); };
todos-read-one.js
'use strict'; const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); module.exports = (event, callback) => { const params = { TableName: 'todos', Key: { id: event.pathParameters.id } }; return dynamoDb.get(params, (error, data) => { if (error) { callback(error); } callback(error, data.Item); }); };
todos-update.js
'use strict'; const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); module.exports = (event, callback) => { const data = JSON.parse(event.body); data.id = event.pathParameters.id; data.updatedAt = new Date().getTime(); const params = { TableName: 'todos', Item: data }; return dynamoDb.put(params, (error, data) => { if (error) { callback(error); } callback(error, params.Item); }); };
todos-delete.js
'use strict'; const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); module.exports = (event, callback) => { const params = { TableName: 'todos', Key: { id: event.pathParameters.id } }; return dynamoDb.delete(params, (error, data) => { if (error) { callback(error); } callback(error, params.Key); }); };
必要なモジュールを揃える
npmで必要なモジュールを揃えます
$ npm init $ npm install aws-sdk --save $ npm install uuid --save
デプロイ
デプロイしていきます。
先ほど作成したAWSのprofileを利用していきます
$ sls deploy -v --aws-profile user1
成功するといろいろ情報が出てきます
Service Information service: serverless-crud stage: dev region: ap-northeast-1 stack: serverless-crud-dev resources: 37 api keys: None endpoints: POST - https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos GET - https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos GET - https://XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos/{id} PUT - https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos/{id} DELETE - https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos/{id}
CRUDしてみる
ターミナルでcurlコマンドを利用してCRUDしてみます。
CREATE – curl -X POST https://XXXX.execute-api.region.amazonaws.com/dev/todos --data '{ "body" : "curlでPOST" }'
READ – curl https://XXXX.execute-api.region.amazonaws.com/dev/todos
READ(ID指定) – curl https://XXXX.execute-api.region.amazonaws.com/dev/todos/<id>
UPDATE – curl -X PUT https://XXXX.execute-api.region.amazonaws.com/dev/todos/<id> --data '{ "body" : "UPDATEしたよ" }'
DELETE – curl -X DELETE https://XXXX.execute-api.region.amazonaws.com/dev/todos/<id>
//CREATE $ curl -X POST https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos --data '{"body":"curlでPOST"}' {"body":"curlでPOST","id":"0dfaf2f0-6b39-11eb-9f3a-8d5346ce6816","updatedAt":1612917835679} $ curl -X POST https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos --data '{"body":"curlでPOST2"}' {"body":"curlでPOST2","id":"7bbf61e0-6b39-11eb-9f3a-8d5346ce6816","updatedAt":1612918019838}
//READ $ curl https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos [{"id":"0dfaf2f0-6b39-11eb-9f3a-8d5346ce6816","updatedAt":1612917835679,"body":"curlでPOST"},{"id":"7bbf61e0-6b39-11eb-9f3a-8d5346ce6816","updatedAt":1612918019838,"body":"curlでPOST2"}]
//READ(ID指定) $ curl https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos/0dfaf2f0-6b39-11eb-9f3a-8d5346ce6816 {"id":"0dfaf2f0-6b39-11eb-9f3a-8d5346ce6816","updatedAt":1612917835679,"body":"curlでPOST"}
//UPDATE $ curl -X PUT https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos/0dfaf2f0-6b39-11eb-9f3a-8d5346ce6816 --data '{"body":"UPDATEしたよ"}' {"body":"UPDATEしたよ","id":"0dfaf2f0-6b39-11eb-9f3a-8d5346ce6816","updatedAt":1612918180045}
//DELETE $ curl -X DELETE https://XXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/todos/7bbf61e0-6b39-11eb-9f3a-8d5346ce6816 {"id":"7bbf61e0-6b39-11eb-9f3a-8d5346ce6816"}
すべてできましたね!
IDがハッシュ値になっているので長くなっていますが、正常にCURDできました!!
リソースを削除するときはsls remove
で削除できます。
ただしDynamoDBのテーブルは削除できないので、手動削除が必要です。