4
4

More than 3 years have passed since last update.

AWS SAM LocalのCodeUri設定に罠があった

Last updated at Posted at 2017-11-27

この記事は、自分のブログからの転載です。
http://selmertsx.hatenablog.com/

やりたいこと

  • TypeScript で書かれている AWS Lambda のコードを AWS SAM Local で動かしたい
  • TypeScriptのコードとbuild後のコードは別ディレクトリで保持したい
  • AWS SAM LocalのREADMEではそこの説明が無いので、自分でなんとか動く方法を模索する必要がある

結論

CodeUri プロパティはcloudformation.ymlからの相対パスを指定する必要がある

AWS SAM Localとは

AWS Lambda関数をローカルで実行しテストができるようになるツール。
S3, DynamoDB, Kinesis 等のリソースからのイベントをエミュレートすることもできる。
API Gatewayをlocalで動かし、Lambdaコードの変更をhot reloadすることもできる。

AWS SAM のinstall

npm install -g aws-sam-local
sam --version # installできているか確認する

上記コマンドだけで installが可能。Dockerも必要なので気をつけること。

設定内容

AWS SAMの説明とcloudformation.yml の書き方についてはここに書いてあるので、ここを見ながら設定を行う。
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction

yamlの設定内容


# cloudformation.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Simple Lambda functions

Resources:
  HelloWorld:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: build/src
      Handler: index.post
      Runtime: nodejs6.10
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /chat-bot
            Method: post

上記の設定ファイルが SAM Localを使う上で、自分が設定した CloudFormationのymlである。CloudFormationに Transform: AWS::Serverless-2016-10-31 という値を追加することで、SAMの定義をCloudFormationで行うことが可能となる。

In order to include objects defined by AWS SAM within a CloudFormation template, the template must include a Transform section in the document root with a value of AWS::Serverless-2016-10-31.

ここで重要なのは HelloWorldリソースのCodeUri プロパティで、こいつはjsファイルのディレクトリを指す。気をつけなければならないのは、指定するディレクトリパスは絶対パスか、cloudformation.ymlからの相対パスを指定しなければならないということ。よって、このときのディレクトリ構成は下記のようになる。


➜  speee_pf_checker git:(aws_saml) ✗ tree -I node_modules
.
├── build
│   └── src
│       ├── index.js
 |          ...
│       └── index.js.map
├── cloudformation.yml
├── package.json
├── src
│   ├── application.ts
│   ├── index.ts
 |      ...
│   └── pc_environment.ts
├── tsconfig.json
├── tslint.json
└── yarn.lock

ちなみにドキュメントでは下記のように記載されている。

For example, if your AWS Lambda function source code is in the /home/user/code/lambdafunction/ folder, specify CodeUri: /home/user/code/lambdafunction for the AWS::Serverless::Function resource. The command returns a template and replaces the local path with the S3 location: CodeUri: s3://mybucket/lambdafunction.zip.

ということで、絶対パスじゃないといけないかと思ったら、絶対パス指定して実行したら下記のエラーとなった。


➜  speee_pf_checker git:(aws_saml) ✗ echo '{"body": "chiba"}' |  sam local invoke HelloWorld --template cloudformation.yml
2017/11/27 19:22:28 Successfully parsed cloudformation.yml
2017/11/27 19:22:28 Connected to Docker 1.34
2017/11/27 19:22:28 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
nodejs6.10: Pulling from lambci/lambda
Digest: sha256:0721cee9614fe0c995c2eb0f52b9803a23d1c2da3007d46cb54b745d970850a0
Status: Image is up to date for lambci/lambda:nodejs6.10
2017/11/27 19:22:31 Reading invoke payload from stdin (you can also pass it from file with --event)
2017/11/27 19:22:31 Invoking index.post (nodejs6.10)
START RequestId: 08f01507-747c-1789-1312-b3368c5a26ad Version: $LATEST
Unable to import module 'index': Error
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
END RequestId: 08f01507-747c-1789-1312-b3368c5a26ad
REPORT RequestId: 08f01507-747c-1789-1312-b3368c5a26ad  Duration: 13.31 ms  Billed Duration: 0 ms   Memory Size: 0 MB   Max Memory Used: 29 MB

{"errorMessage":"Cannot find module '/var/task/index'","errorType":"Error","stackTrace":["Function.Module._load (module.js:417:25)","Module.require (module.js:497:17)","require (internal/module.js:20:19)"]}

JavaScriptのコード


// build/src/index.js
'use strict';
console.log('Loading function');

exports.post = (event, context, callback) => {
    callback(null, {
        statusCode: 200,
        headers: { "x-custom-header" : "my custom header value" },
        body: "Hello " + event.body
    });
};

確認用のシンプルなJSコード。

動作確認

➜  speee_pf_checker git:(aws_saml) yarn build
yarn run v1.3.2
$ tsc
✨  Done in 3.25s.
➜  lambda git:(aws_saml) ✗ echo '{"body": "chiba"}' |  sam local invoke HelloWorld --template cloudformation.yml
2017/11/27 18:04:54 Successfully parsed cloudformation.yml
...
{"statusCode":200,"headers":{"x-custom-header":"my custom header value"},"body":"Hello chiba"}

上記コマンドで確認した結果、aws sam localが動いていることが確認できた。

後程確認すること

  • node_modulesを AWS SAM Localで読み込む
  • API GatewayをLocalで使う
4
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4