Serverless FrameworkでLambdaファンクションをプロジェクトごとに一括管理する

## 概要
![serverless_readme_header.jpg](https://qiita-image-store.s3.amazonaws.com/0/65478/f51ea2fd-ee6a-b5aa-499e-c04560fdaff9.jpeg)
アプリケーションフレームワークのServerlessを試してみたところ、ローカルでLambdaの実行やデプロイが可能だったので、今稼働している[AWS Mobile HubでAMIMOTOマネージドホスティングの管理をサーバレスにした話](https://ja.amimoto-ami.com/2015/11/27/aws-mobile-hub-admin-serverless/)で書いたAMIMOTOの管理ツールで使っているLambdaファンクションをServerlessで再構築しました。

## Serverless Frameworkのインストールと設定
[サーバレスアプリケーションフレームワーク JAWS を使ってみる](http://dev.classmethod.jp/server-side/framework/jaws-quick-start/)
[AWS Lambdaを活用したServerless Frameworkを触ってみる](http://qiita.com/susieyy/items/1c2af0ef7b88b742c37a)
上記の記事を参考にServerlessの初期インストールとセットアップを行います。

## ServerlessでLambdaファンクションを作る
AMIMOTO Mobileアプリケーションは以下の6つのファンクションで構成されています

| function名   | 役割  |
|:------------:|:------------:|
| get-metric-cpu|         CloudWatchのCPUメトリックを取得 |
| describe-instance-by-id|       EC2インスタンスのinstance_idからメタ情報を取得 |
| describe-instances|  EC2インスタンスのメタ情報のリストを取得 |
| start-instance|      EC2インスタンスを起動 |
| stop-instance|       EC2インスタンスを停止 |
| modify-instance|     EC2インスタンスのインスタンスタイプ変更 |

以下のコマンドにてひとつづつ必要な関数を作っていきます
```
$ serverless function create <ファンクション名>
```

最終的に出来たディレクトリ構成は以下のとおりです。
<img width="480" alt="スクリーンショット 2015-12-17 10.13.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/21c6266f-f577-1865-ec70-3d1e7b185c7b.png">

実際に動作するLambdaファンクションはlibディレクトリ以下に配置されます。
最初はindex.jsがあるのみなので、それぞれ必要なファンクション毎に分けて上げる必要があります。

こんな感じでリネームしてコードを書きます。

```js:start-instance.js
var AWS = require('aws-sdk');
AWS.config.update({region: 'ap-northeast-1'});

module.exports.respond = function(event, cb) {
  console.log(event.instance_id);
  var ec2 = new AWS.EC2();
  var params = {
        InstanceIds: [
            event.instance_id
        ]
    };
 
    ec2.startInstances(params, function(err, data) {
        if (err){ console.log(err, err.stack);
        } else {
            ec2.waitFor('instanceRunning', params, function(err, data) {
                if (err) {
                  console.log(err, err.stack);
                } else {
                  return cb(null, JSON.stringify(data)); 
                }
            });
        }
    });

};
```
start-instance/handler.jsにてrequreする関数を上記の関数にするように修正します。
また、入力値としてevent変数に渡す値はevent.jsonに記述します

```json:event.json
{"undefined":{"instance_id":"<インスタンスID>"}}
```


## ローカルでLambdaファンクションを実行
```
$ sls function run
```
このコマンドでファンクションを選んで実行できます

<img width="714" alt="スクリーンショット 2015-12-20 0.33.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/da7c72ea-8e3b-add6-f31a-09749d35b13b.png">
コマンド発行後、実行したい関数をコマンドラインで選択して実行します

## Blue Green デプロイメント
Serverlessフレームワークを使うとBlue Green デプロイメントもコマンドラインのみで実行可能です。

こんな感じで本番用のタグを作ります。

```
$ sls stage create -s prod -r us-east-1
```

そして作ったLambdaファンクションをデプロイする場合は以下のコマンドで可能です

```
$ sls function deploy
```

<img width="694" alt="スクリーンショット 2015-12-20 0.46.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/c28d479a-34ab-ce1a-1ab2-0e7798dd002e.png">
本番環境では本番用のstageをつかい、テスト環境ではそれ以外のstageを使います。
これを利用することで本番及びテスト環境にデプロイ先を適宜変更することで体系だった運用が可能となります

## まとめ
ローカルでLambdaファンクションの実行とデプロイが出来るのは非常に良いです。
マネジメントコンソール上だとLambdaファンクションがどのプロジェクトで使われていて、必要不必要もよくわからなくなります。しかし、Serverlessフレームワークを使うことで必要なLambdaファンクションがプロジェクトごとに管理できるので非常にやりやすいです。

後はテストのやり方がServerlessフレームワーク内で保管してもらえればすごい良さそう

それではよいServerlessライフを！