SAM LocalをAmazon Linux AMIで試そうとしたらハマりまくったので、手順を覚え書きしておく。
目的
Lambda関数のデプロイがすごくめんどいので、ローカルでLambda関数をテストできるようにしたい。
SAM Localとやらを試してみることにする。
記事を読んでみる
Lambda関数を直接invokeするんじゃなく、バックエンドがLambdaであるようなAPIを作ってそのAPIをcurlで叩くような使い方をするっぽい。
Amazon Linux AMIで試す時にハマった箇所
go-npm
aws-sam-localを入れる前に、go-npmというヤツもnpmで入れておく必要があった。
# go-npmなしにaws-sam-localを入れようとしてもうまくいかない。
$ npm install -g aws-sam-local
> aws-sam-local@0.2.0 postinstall /home/ec2-user/.nvm/versions/node/v6.11.2/lib/node_modules/aws-sam-local
> go-npm install
$ sam validate
-bash: sam: command not found
# -gオプションを外すと詳しいエラーメッセージを見られる。
$ npm install aws-sam-local
...
npm ERR! Failed at the aws-sam-local@0.2.0 postinstall script 'go-npm install'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the aws-sam-local package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! go-npm install
...
# go-npmも入れておけばうまくいく。
$ npm install -g go-npm
$ npm install -g aws-sam-local
$ sam validate
open template.yml: no such file or directory
Docker
Docker入れておかないと、sam local start-api
に失敗する。
$ sam local start-api
2017/09/03 08:03:28 Running AWS SAM projects locally requires Docker. Have you got it installed?
2017/09/03 08:03:28 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
下記のdocumentに、Docker要るよと書いてある。
https://github.com/awslabs/aws-sam-local#installation
$ sudo yum install docker -y
$ sudo service docker start
Starting cgconfig service: [ OK ]
Starting docker: . [ OK ]
npmでインストールしたコマンドをsudoで実行する
sam local start-api
コマンドを叩く時、sudo付けないと、docker周りの権限エラーでうまくいかない。
しかし、sudo sam local start-api
を実行しようとすると、samがないよ、と言われてしまう。
npmでインストールしたコマンドをsudoで実行するには、リンクを張っておかないとダメらしい。
$ sudo ln -s /usr/local/bin/node /usr/bin/node
$ sudo ln -s /usr/local/lib/node /usr/lib/node
$ sudo ln -s /usr/local/bin/npm /usr/bin/npm
$ sudo ln -s /usr/local/bin/node-waf /usr/bin/node-waf
動くまでの過程
適当にディレクトリ作って、テンプレートとLambdaのコードの、2つのファイルを置く。
テンプレート
SAMのテンプレートの記法のリファレンスは下記。
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md
下記のようなテンプレートを作ってみた。
ファイル名はtemplate.yaml。
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
SAMLocalFunction:
Type: "AWS::Serverless::Function"
Properties:
Runtime: nodejs6.10
Handler: index.handler
Timeout: 60
Role: arn:aws:iam::123412341234:role/lambda_sam_test_role
Events:
Root:
Type: Api
Properties:
Path: /
Method: post
Lambda関数
blueprintのhelloworldをコピー。
ファイル名はindex.js。
'use strict';
console.log('Loading function');
exports.handler = (event, context, callback) => {
const body = JSON.parse(event['body']);
console.log('Received body:', JSON.stringify(body, null, 2));
console.log('value1 =', body.key1);
console.log('value2 =', body.key2);
console.log('value3 =', body.key3);
callback(null, {statusCode:200});
callback('Something went wrong');
};
動かす
2つのファイルが置いてあるディレクトリで下記作業。
# テンプレートの検証
$ sam validate
Valid!
# apiを生成
$ sam local generate-event api
# 初回起動時にいろいろと落としてくるみたい。
$ sudo sam local start-api
2017/09/03 08:44:01 Connected to Docker 1.27
2017/09/03 08:44:01 Successfully parsed template.yaml
2017/09/03 08:44:01 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
nodejs6.10: Pulling from lambci/lambda
cf9c84c367d8: Pull complete
aeeaf5aea2af: Pull complete
a0458750b065: Pull complete
4315c1ddcefe: Pull complete
Digest: sha256:b9a57b98dcfe226cac3fb0b8329594eefb62ba7089fa27cf8ac968e5736cc04a
Status: Downloaded newer image for lambci/lambda:nodejs6.10
Mounting static files from /home/ec2-user/sam-test at /
Mounting index.handler (nodejs6.10) 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.
# バックグラウンドで実行
$ sudo sam local start-api &
[1] 10567
$ curl -d '{
"key3": "value3",
"key2": "value2",
"key1": "value1"
}' http://127.0.0.1:3000/
2017/09/03 08:55:45 Invoking index.handler (nodejs6.10)
START RequestId: e25578f0-a494-1da8-4de6-bf2442b6977c Version: $LATEST
2017-09-03T08:55:45.426Z e25578f0-a494-1da8-4de6-bf2442b6977c Loading function
2017-09-03T08:55:45.428Z e25578f0-a494-1da8-4de6-bf2442b6977c Received body: {
"key3": "value3",
"key2": "value2",
"key1": "value1"
}
2017-09-03T08:55:45.428Z e25578f0-a494-1da8-4de6-bf2442b6977c value1 = value1
2017-09-03T08:55:45.428Z e25578f0-a494-1da8-4de6-bf2442b6977c value2 = value2
2017-09-03T08:55:45.429Z e25578f0-a494-1da8-4de6-bf2442b6977c value3 = value3
END RequestId: e25578f0-a494-1da8-4de6-bf2442b6977c
REPORT RequestId: e25578f0-a494-1da8-4de6-bf2442b6977c Duration: 5.56 ms Billed Duration: 100 ms Memory Size: 0 MB Max Memory Used: 28 MB
CloudWatch Logsに出力されるログとかも全部見られてすごい便利。
その他
npmを入れる手順
Amazon Linux AMIでnpm使えるようにする手順を覚え書き。
http://dev.classmethod.jp/server-side/building-node-js-express-dev-env-in-aws-ec2-with-images/
$ sudo yum install git gcc-c++ make openssl-devel -y
$ git clone git://github.com/creationix/nvm.git .nvm
$ source ~/.nvm/nvm.sh
$ nvm ls-remote
$ nvm install v6.11.2
$ node -v
$ nvm alias default v6.11.2
$ history
http://arfyasu.hatenablog.com/entry/2016/01/26/212543
起動時にnvm使えるようにするために、~/.bashrcを編集しておく。
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
npmで-gオプション付けてinstallした時のファイルの在り処の調べ方
下記コマンドで調べられる。
$ npm -g root
/home/ec2-user/.nvm/versions/node/v6.11.2/lib/node_modules