nodeをLambdaに自動デプロイ

はじめに

AWS の Lambda を初めて,色々と試したいことがあり,その度に function をコンソールからデプロイするのが面倒でした. 特に,必要なライブラリ(モジュール)の ZIP 化やその後の cli を用いたアップロード作業は煩わしいと思います. そこで,node を対象に簡単なシェルスクリプトで,ZIP 化とデプロイ作業を自動化(ラップ)します.

環境

Mac
aws-cli で,lambda function を作成できる権限を持っている必要あり.

環境

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ mkdir lambda-test
$ cd lambda-test
$ npm init -y
Wrote to lambda-test/package.json:

{
  "name": "lambda-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

今回は,lambda で Slack に通知を送ります.
コードは以下の通りです.
your URL は置き換えてください.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ cat index.js
var request = require('request');

var options = {
  uri: 'your URL',
  headers: { 'Content-Type': 'application/json' },
  json: {
    username: 'lambda',
    icon_emoji: ':ghost:'
  }
};

exports.handler = function(event, context) {

  options.json.text = "hello world";

  request.post(options, function(error, response, body){
    if (!error && response.statusCode == 200) {
      console.log(body);
    } else {
      console.log('error: '+ response.statusCode + '\n' + response.body);
    }
  });
};

必要なモジュールをインストールします.

1
$ npm install request --save

自動化スクリプト

設定ファイルと実行スクリプト2つを用意します.

1
2
3
4
5
6
7
$ cat lambda-config.json
{
  "functionName": "sample",
  "region": "ap-northeast-1",
  "handler": "index.handler",
  "role": "arn:aws:iam::xxxxxxxxxxxx:role/lambda-execution-role"
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$ cat create_lambda.sh
$ cat ./create-lambda.sh
#! /bin/bash -eu

DIST_DIR="dist"
DIST_DIR_ZIP=${DIST_DIR}".zip"
INDEX_JS="index.js"

delete_lambda_zip () {
  (
     rm -rf ${DIST_DIR}
     rm -rf ${DIST_DIR_ZIP}
  )
}

create_lambda_zip () {
  (
    mkdir ${DIST_DIR} && cp package.json ${INDEX_JS} ${DIST_DIR}
  )

  (
    npm --prefix ${DIST_DIR} install ${DIST_DIR} --production
  )

  (
    cd ${DIST_DIR} && zip -r ./../${DIST_DIR_ZIP} ./ -x ${DIST_DIR}/package.json
  )
}

create_lambda () {
  local config="lambda-config.json"
  local region=$(cat ${config} | jq -r ".region")
  local role=$(cat ${config} | jq -r ".role")
  local handler=$(cat ${config} | jq -r ".handler")
  local func_name=$(cat ${config} | jq -r ".functionName")

  aws lambda create-function \
    --function-name ${func_name} \
    --runtime nodejs6.10 \
    --role ${role} \
    --handler ${handler} \
    --zip-file fileb://${DIST_DIR_ZIP} \
    --region ${region}
}

deploy_lambda () {
  delete_lambda_zip
  create_lambda_zip
  create_lambda
}

deploy_lambda

スクリプトは,単純です.
create_lambda_zipで,必要なモジュールを dist ディレクトリにインストールし,index.js と一緒に ZIP 化しています.
create_lambdaで,設定ファイルから値を読み出し,lambda function を作成しています.

実行

以下のようなディレクトリ配置で実行します(場合によっては node_modules があるかも).

1
2
3
4
5
6
$ pwd
lambda-test
$ ls
create-lambda.sh   index.js           lambda-config.json package-lock.json  package.json
$ ./create-lambda.sh
(snip)

おわりに

今回は,シェルスクリプトでラップしましたが,Windows ではデフォルトで利用できませんし,シェルの種類によっては動作しないケースも考えられます. 将来的には,gulp のようなタスクランナーや npm scripts で環境の差異を取り除きたいです.