lamjet を使って AWS Lambda に CoffeeScript で書かれた関数を楽々デプロイする方法

## 1. 背景と概要

[AWS Lambda](https://aws.amazon.com/lambda/)はとても便利なサービスです。けれども、使い始めるまでが少し面倒です。
JavaScriptファイルをZIPファイルにアーカイブして、Webコンソール、ないしAPIでデプロイして・・・。
また、CoffeeScriptを使うとコードの記述は楽になりますが、さらにCoffeeScriptからJavaScriptへの変換も必要になります。

そんな面倒を解消してくれるツール「[lamjet](https://www.npmjs.com/package/lamjet)」（ラムジェット）を作りましたので紹介します。

`lamjet`の特徴は以下の通りです。

* コマンド一発でテンプレートを作成する `lamjet init`
* コマンド一発でデプロイする `gulp deploy`
* Jasmineによるテストに対応
* CoffeeScriptのみに対応

## 2. 前提条件

本稿を参照するに当たっての前提条件は以下の通りです。

* `node`がインストールされていること
  * 本稿執筆時点（2015年10月9日）では、AWS Lambdaの`node`はv0.10.36であるため、それに近い方が問題が少ないかと思います
  * 参考: [Lambda Execution Environment and Available Libraries](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/current-supported-versions.html)
* AWSアカウントを保有していること

## 3. 準備

### 3.1. IAMロールの準備

AWS Lambdaの関数（以下「Lambda関数」）を実行するためにはIAM（Identity and Access Management）ロールが必要です。
ここでは詳しく述べませんが、例えばKinesisストリームから起動されるLambda関数の場合、以下の様なIAMポリシーを持つIAMロールを作成します。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kinesis:GetRecords",
                "kinesis:GetShardIterator",
                "kinesis:DescribeStream",
                "kinesis:ListStreams"
            ],
            "Resource": [
                "arn:aws:kinesis:us-east-1:000000000000:stream/name"
            ]
        }
    ]
}
```

`lamjet`の設定ファイルにIAMロールのARN（Amazon Resource Name）を記述する必要がありますので、控えておきます。
IAMロールのARNは、例えば以下の様な識別子です。

```
arn:aws:iam::000000000000:role/name
```

### 3.2. lamjetのインストール

`lamjet`は`npm install`コマンドで簡単にインストールする事ができます。
`lamjet`コマンドが必要なので、`-g`オプションを付与し、グローバル環境にインストールします。

```
$ npm install -g lamjet
```

## 4. Lambda関数の作成、デプロイ

### 4.1. ディレクトリの作成

Lambda関数を実装するためのディレクトリを準備します。
ディレクトリ名がデフォルトの関数名となりますので、いい感じのディレクトリ名にしておきましょう。

```
$ cd /your/project/path
$ mkdir your-function-name
$ cd your-function-name
```

### 4.2. 初期化

`lamjet init`コマンドを実行すると、そのディレクトリに必要なファイル一式を生成します。
途中で関数名、メモリサイズなどについて質問されますが、IAMロール以外はデフォルト値のままで構いません。
何も入力せずにEnterキーを押下すると、デフォルト値が使用されます。

```
$ lamjet init
lamjet v0.3.1
Function name [your-function-name] ?
Version [1.0.0] ?
Description [TODO] ?
Region [us-east-1] ?
Role [arn:aws:iam::ACCOUNTID:role/ROLENAME] ? arn:aws:iam::000000000000:role/name
Memory size in MB [128] ?
Timeout in sec [3] ?
write /your/project/path/your-function-name/package.json
write /your/project/path/your-function-name/aws-lambda-config.js
write /your/project/path/your-function-name/.gitignore
write /your/project/path/your-function-name/gulpfile.coffee
write /your/project/path/your-function-name/src/index.coffee
write /your/project/path/your-function-name/src/index_spec.coffee
initialized
```

生成されるファイルは以下の通りです。

* `package.json`
  * パッケージ情報
  * 関数名、バージョン番号、説明文の情報を含んでいます
* `aws-lambda-config.js`
  * AWS Lambdaのデプロイ時に使用される設定値
  * 関数名、説明文、リージョン、IAMロールのARN、メモリサイズ、タイムアウト時間、ランタイム、ハンドラ名の情報を含んでいます
* `.gitignore`
  * `git`用の無視リスト
* `gulpfile.coffee`
  * `gulp`のタスクを定義したスクリプト
  * lamjet標準のタスクをインポートしています
* `index.coffee`
  * Lambda関数の本体
* `index_spec.coffee`
  * Lambda関数のテストスペック

### 4.3. パッケージのインストール

`lamjet`に必要なパッケージをインストールします。

```
$ npm install
```

### 4.4. テスト

デフォルトのテストスペックを実行します。
`lamjet`ではテスティングフレームワークとして[Jasmine](http://jasmine.github.io/)を使っています。
テストを実行する過程でCoffeeScriptの変換が行われ、`out`ディレクトリにJavaScriptが出力されます。

```
$ gulp
...
1 spec, 0 failures
Finished in 0 seconds
...
```

### 4.5. デプロイ

デプロイを行うためには、AWSの認証情報が必要です。
認証情報の設定方法はAWS CLIと同様、環境変数やファイルが使えます。

```
$ export AWS_ACCESS_KEY_ID=...
$ export AWS_SECRET_ACCESS_KEY=...
```

認証情報の設定が終わったら、Lambda関数をデプロイします。

```
$ gulp deploy
```

AWS LambdaのWebコンソールを確認し、Lambda関数が追加されていれば成功です。

### 4.6. 編集→デプロイ

Lambda関数の編集は、スクリプトの修正、テスト、デプロイという流れになります。

```
$ vim src/index.coffee
$ vim src/index_spec.coffee
$ gulp
$ gulp deploy
```

## 5. 最後に

素敵なAWS Lambdaライフを！