SAM LocalをAmazon Linux AMIで試そうとしたらハマりまくったので、手順を覚え書きしておく。

目的

Lambda関数のデプロイがすごくめんどいので、ローカルでLambda関数をテストできるようにしたい。

SAM Localとやらを試してみることにする。

記事を読んでみる

https://aws.amazon.com/jp/blogs/news/new-aws-sam-local-beta-build-and-test-serverless-applications-locally/

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で実行するには、リンクを張っておかないとダメらしい。

https://stackoverflow.com/questions/4976658/on-ec2-sudo-node-command-not-found-but-node-without-sudo-is-ok

$ 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