`node-lambda` で素朴にLambdaを使ってみる

# `node-lambda` で素朴にLambdaを使ってみる

## 概要
AWS Lambdaを利用して何かをやりたい場合は以下のいずれかを使うのがイマドキでしょうか

* [AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html)
* [Serverless Framework](https://serverless.com/)
* ~~[Apex](https://apex.run/)~~ [追記: Apexは開発やめたみたいです。](https://github.com/apex/apex)

そんな時代ではありますが [node-lambda](https://github.com/motdotla/node-lambda) の紹介をします
名前の通りAWS LmabdaをNode.jsで使うときに利用します。（Node.js以外の言語には対応していません）
素朴なツールで出来ることは少ないですが、お手軽にLambdaを使ってみる分にはよいツールではないかと思います

## install

```
% npm i -g node-lambda
```

globalにinstallしたことにして話を進めます

## 初期化

適当な作業ディレクトリを作成し、そこに移動したのち `setup` を実行します

```
% node-lambda setup
Running setup.
/path/.env file successfully created
/path/event.json file successfully created
/path/deploy.env file successfully created
/path/context.json file successfully created
/path/event_sources.json file successfully created
Setup done.
Edit the .env, deploy.env, context.json, event_sources.json and event.json files as needed.%
```

`node-lambda` が利用するファイルがもりもり作成されました。
取り急ぎ使うのは `event.json` と `.env` です

* `.env`
    * Lambdaにdeployするときに利用。RoleやLambdaのメモリ設定など
* `deploy.env`
    * 名前が紛らわしいのですが、Lambdaに設定する環境変数を設定するためのファイルです
* `event_sources.json`
    * S3のイベントをトリガーにLambdaを実行したいときなどに設定します
* `event.json`
    * ローカルで実行するときに利用する
* `context.json`
    * ローカルで実行するときに利用する

## Lambdaのハンドラ例

以下のファイルを例に進めます

```index.js
exports.handler = async (event, context) => {
  console.log('Running index.handler')
  console.log('==================================')
  console.log('event', event)
  console.log('==================================')
  console.log('Stopping index.handler')

  return true
}
```

## ローカルで実行してみる

`run` を実行します。
デフォルトでは `index.js` にある `handler` という関数を実行します

```
% node-lambda run
Running index.handler
==================================
event { key: 'value', key2: 'value2', other_key: 'other_value' }
==================================
Stopping index.handler
Result:
true
```

上述のindex.jsの内容が実行されました

引数の `event` に値が渡っていることに気付くかと思います
デフォルトでは `setup` で作成された `event.json` を引数の`event`に渡します

`setup` で作成される `event.json` は以下の通りです

```
% cat ./event.json
{
  "key": "value",
  "key2": "value2",
  "other_key": "other_value"
}
```

## 設定

ローカルで動作確認できたらLambdaにdeployします
そのための設定を `.env` にします

`~/.aws/credentials` にアクセスキーなどの設定がしてあれば以下の設定くらいで十分です
変数名から何の設定かは想像できると思いますので詳細は割愛します

```config:.env
AWS_ENVIRONMENT=development
AWS_ROLE_ARN=arn:aws:iam::xxx:role/test
AWS_REGION=us-east-1
AWS_FUNCTION_NAME=test-function
AWS_HANDLER=index.handler
AWS_MEMORY_SIZE=128
AWS_TIMEOUT=5
AWS_RUNTIME=nodejs8.10
```

## deploy

`deploy` でLambdaにdeployします

```
% node-lambda deploy
=> Moving files to temporary directory
=> Running npm install --production
=> Zipping deployment package
=> Zipping repo. This might take up to 30 seconds
=> Reading zip file to memory
=> Reading event source file to memory
=> Uploading zip file to AWS Lambda us-east-1 with parameters:
{ FunctionName: 'test-function-development',
  Code:
   { ZipFile:
      <Buffer xxx more bytes> },
  Handler: 'index.handler',
  Role: 'arn:aws:iam::xxx:role/test',
  Runtime: 'nodejs8.10',
  Description: '',
  MemorySize: '128',
  Timeout: '5',
  Publish: false,
  VpcConfig: { SubnetIds: [], SecurityGroupIds: [] },
  Environment: { Variables: null },
  KMSKeyArn: '',
  DeadLetterConfig: { TargetArn: null },
  TracingConfig: { Mode: null } }
=> Done uploading. Results follow:
{ FunctionName: 'test-function-development',
  FunctionArn:
   'arn:aws:lambda:us-east-1:xxx:function:test-function-development',
  Runtime: 'nodejs8.10',
  Role: 'arn:aws:iam::xxx:role/test',
  Handler: 'index.handler',
  CodeSize: n,
  Description: '',
  Timeout: 5,
  MemorySize: 128,
  LastModified: '2019-04-04T09:30:17.015+0000',
  CodeSha256: 'zzz',
  Version: '$LATEST',
  VpcConfig: { SubnetIds: [], SecurityGroupIds: [], VpcId: '' },
  KMSKeyArn: null,
  TracingConfig: { Mode: 'PassThrough' },
  MasterArn: null,
  RevisionId: 'yyy' }
=> All tasks done. Results follow:
{}
```

以上でdeployは完了です。（`index.js` を変更した後ももう一度 `deploy` すればLambdaの更新が行えます）

Webコンソールで確認すると以下の通りです

* 一覧画面の様子
<img width="692" alt="スクリーンショット 2019-04-04 18.30.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/3800/837c123e-7657-0e52-a325-4785fbac5ed1.png">
* 関数詳細の設定内容の一部
<img width="874" alt="スクリーンショット 2019-04-04 18.31.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/3800/d0be4fe6-b4f6-0716-237b-5eae1e0d57e7.png">
<img width="868" alt="スクリーンショット 2019-04-04 18.31.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/3800/f5435052-5dc0-29d1-99a5-1735e3800837.png">

## Lambdaをinvoke

素朴なツールだけあってLambdaをinvokeする機能は提供されていません。
[READMEにもある通り](https://github.com/motdotla/node-lambda#post-invoke-script-example) `aws` コマンドでinvokeするか、Webコンソールで実行して動作確認しましょう

## まとめ

素朴なツール `node-lambda` でAWS Lambdaを使ってみました
イマドキなツールと比べると見劣りする部分も多いですが、内部でCloudFormationを使っているということもなくお手軽にLambdaをはじめるには十分だと思います
また素朴なツールなのでコードを読むとシンプルにAPIを使ってLambdaにdeployしたり、トリガーとなるイベントの紐付け方などが理解しやすいかもしれません