AWS Cloud9からSAM Localをためしてみる #serverless #adventcalendar #reinvent

2017.12.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも!大阪オフィスの西村祐二です。

このエントリはServerless Advent Calendar 2017の21日目の記事となります。

AWS Cloud9を利用する際に、EC2上に新しく構築するとAWS Cloud9用のAMIを使用してインスタンスが作成されます。 このAMIにはSAM Localがデフォルトでインストールされているので今回こちらをためしたいと思います。

Cloud9用AMIに含まれるコンポーネント一覧

AWS Cloud9の環境構築

下記ブログがとても参考になります。 本ブログではすでにAWS Cloud9のIDEが利用できることを前提にすすめてまいります。

AWS Cloud9 で Lambda 関数の作成・実行・デバッグ・デプロイをやってみる #reinvent

AWS Cloud9のIDEで提供されるターミナルで作業していきます。

SAM Localをためしてみる

SAM Localについては下記ブログを参考にします。

[新ツール]AWS SAMをローカル環境で実行できるSAM Localがベータリリース

確認

SAM Local が入っているか確認します。 コマンドで確認するときちんと入っているようですね。

0.2.2が入っているようですね。

最新版があるようなのであげておきましょう。

$ npm update -g aws-sam-local                                                    

> aws-sam-local@0.2.2 preuninstall /home/ec2-user/.nvm/versions/node/v6.11.4/lib/node_modules/aws-sam-local
> go-npm uninstall


> aws-sam-local@0.2.4 postinstall /home/ec2-user/.nvm/versions/node/v6.11.4/lib/node_modules/aws-sam-local
> go-npm install

Downloading from URL: https://github.com/awslabs/aws-sam-local/releases/download/v0.2.4/sam_0.2.4_linux_amd64.tar.gz
+ aws-sam-local@0.2.4
updated 3 packages in 3.25s

$ sam --version
sam version 0.2.4

これで最新版になりました。

テスト用のファイルを用意

SAMのテンプレートファイルを作成します。 今回は「python3.6」としています。

template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Local test
Resources:
  HelloWorld:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: python3.6
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /resource/{resourceId}
            Method: put

Lambda実行時に渡すeventファイルを作成します。

event.json

{
  "body": "Hello World SAM Local"
}

Lambda関数のコードを作成します。

index.py

import json

print('Loading function')

def handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    return {'statusCode': 200,
            'body': "Hello " + json.dumps(event['body']),
            'headers': {'Content-Type': 'application/json'}}

構文確認

SAM Localで構文確認をします。 Valid!となればokのようです。

$ sam validate
Valid!

動作確認

テスト用のファイルが用意できたら AWS Cloud9上のSAM LocalでLambdaを実行してみましょう。

$ sam local invoke HelloWorld -e event.json
2017/12/20 07:50:24 Successfully parsed template.yaml
2017/12/20 07:50:24 Connected to Docker 1.27
2017/12/20 07:50:24 Fetching lambci/lambda:python3.6 image for python3.6 runtime...
python3.6: Pulling from lambci/lambda
Digest: sha256:
Status: Image is up to date for lambci/lambda:python3.6
2017/12/20 07:50:24 Invoking index.handler (python3.6)
2017/12/20 07:50:24 Mounting /home/ec2-user/environment as /var/task:ro inside runtime container
START RequestId:  Version: $LATEST
Loading function
Received event: {
  "body": "Hello World SAM Local"
}
END RequestId: 
REPORT RequestId:  Duration: 0 ms Billed Duration: 0 ms Memory Size: 0 MB Max Memory Used: 18 MB

{"statusCode": 200, "body": "Hello \"Hello World SAM Local\"", "headers": {"Content-Type": "application/json"}}

作成したプログラム通りに実行されていますね。

トリガー連携のテスト

SAM LocalではLambdaを実行するための トリガーを想定したペイロードが取得できます。

下記はAPI Gatewayをトリガーとした際のeventファイルの出力です。

$ sam local generate-event api --resource /resource
{
  "body": "{ \"test\": \"body\"}",
  "resource": "/resource",
  "requestContext": {
    "resourceId": "123456",
    "apiId": "1234567890",
    "resourcePath": "/resource",
    "httpMethod": "POST",
.
.
.

オプションでパラメータを変更することが可能です。

$ sam local generate-event api --help
NAME:
   sam local generate-event api - Generates a sample Amazon API Gateway event

USAGE:
   sam local generate-event api [command options] [arguments...]

OPTIONS:
   --method value, -m value    HTTP method (default: "POST")
   --body value, -b value      HTTP body (default: "{ \\\"test\\\": \\\"body\\\"}")
   --resource value, -r value  API Gateway resource name (default: "/{proxy+}")
   --path value, -p value      HTTP path (default: "/examplepath")

実行はパイプでわたすだけいいので簡単ですね。

$ sam local generate-event api | sam local invoke <logical ID>

API Gatewayのテストをやってみる

SAMのテンプレートをもとに、AWS Cloud9上のSAM Localを使ってAPI Gatewayのテスト実行ができます。 かなり強力です。

下記コマンドで、API サーバを立ててくれます。

$ sam local start-api

2017/12/20 06:43:09 Connected to Docker 1.27
2017/12/20 06:43:09 Fetching lambci/lambda:python3.6 image for python3.6 runtime...
python3.6: Pulling from lambci/lambda
Digest: sha256:
Status: Image is up to date for lambci/lambda:python3.6

Mounting index.handler (python3.6) at http://127.0.0.1:3000/resource/{resourceId} [PUT]

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.

上記、実行ログより、 http://127.0.0.1:3000/resource/{resourceId}

に対して、リクエストして動作確認をしてみましょう。 新しくターミナルを開き、そこから下記コマンドを実行してみます。

$ curl -H "Accept: application/json" -H "Content-type: application/json" \
      -X PUT http://127.0.0.1:3000/resource/hoge \
      -d 'sam local'
      
Hello "sam local"

きちんとレスポンスのbody部分がかえってきていることがわかります。

SAM LocalでたてたAPI サーバー側のログは下記のようになってました。

2017/12/20 08:04:05 Invoking index.handler (python3.6)
2017/12/20 08:04:05 Mounting /home/ec2-user/environment as /var/task:ro inside runtime container
START RequestId:  Version: $LATEST
Loading function
Received event: {
  "httpMethod": "PUT",
  "body": "sam local",
  "resource": "/resource/hoge",
  "requestContext": {
    "resourcePath": "/resource/hoge",
    "httpMethod": "PUT",
    "stage": "prod",
    "identity": {
      "sourceIp": "127.0.0.1:54768"
    }
  },
  "queryStringParameters": {},
  "headers": {
    "Accept": "application/json",
    "Content-Length": "9",
    "Content-Type": "application/json",
    "User-Agent": "curl/7.53.1"
  },
  "pathParameters": {
    "resourceId": "hoge"
  },
  "stageVariables": null,
  "path": "/resource/hoge"
}
END RequestId: 
REPORT RequestId: Duration: 0 ms Billed Duration: 0 ms Memory Size: 0 MB Max Memory Used: 19 MB

Lambdaのコードを修正しても、再起動せずに更新してくれるので大変便利です。

さいごに

いかがだったでしょうか。

AWS Cloud9からSAM Localをためしてみました。 特に問題なく利用できました。

環境構築せずに、SAM Localを利用できるのでとても便利ですね。 AWS Cloud9上からLambda開発がはかどりそうです。

誰かの参考になれば幸いです。