AWS LambdaをApexでDeployします

## 概要
今更ながらLambda使い始めたものの依存するAWSリソース管理(IAM/S3等)・Deploy・バージョン管理、コンソールからの操作では辛い、そこで今回これらのツールを使用してそれらの課題を解決しようと思います。

なお、今回はTerraformやその他の方法で既にリソースが作られている状態でリリースのみにapexを使用する方法をご紹介します。

## Apexとは
AWS Lambdaの管理、ビルド/デプロイを行ってくれるツールです。

 - LambdaへのDeploy
 - LambdaにDeployしたfunctionのロールバックが可能
 - ApexからLogの確認が可能
 - 複数のfunctionをまとめて管理する事が可能
 - ApexからTerraformを呼べるのでLambdaの環境構築も可能
 - Dry-runを利用して変更の確認が可能
[公式](http://apex.run) [README](https://github.com/apex/apex)

## 対応言語
 - Node.js
 - Golang
 - Python
 - Java
 - Rust
 - Clojure

## インストール方法

```
$ curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh
```

場合によってはsudoが必要となる事がある。

```
$ curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh
```


## 新規関数の作成
AWS のCredentials情報が必要なので `aws profile` 等で事前に作成しておきましょう。

[作成コマンド]

```
$ apex init test
```

[説明]

```
$ apex init <function name>
```

[実行結果]

```

             _    ____  _______  __
            / \  |  _ \| ____\ \/ /
           / _ \ | |_) |  _|  \  /
          / ___ \|  __/| |___ /  \
         /_/   \_\_|   |_____/_/\_\



  Enter the name of your project. It should be machine-friendly, as this
  is used to prefix your functions in Lambda.

    Project name: test-01

  Enter an optional description of your project.

    Project description: test_01

  [+] creating IAM test-01_lambda_function role
  [+] creating IAM test-01_lambda_logs policy
  [+] attaching policy to lambda_function role.
  [+] creating ./project.json
  [+] creating ./functions

  Setup complete, deploy those functions!

    $ apex deploy
```

[作成されたファイル]

```
.
├── functions
│   └── hello
│       └── index.js
└── project.json
```


※過去のバージョンを確認すると `apex init` 実行時にTerraformで使用する`infrastructure` ディレクトリを作成してくれたっぽいですが現在は作成されなくなっています。

とここで思ったのはこれだけであれば特にinitを実行する必要もない！

`apex init` で作成される`project.json`を自分で作成すれば良い。

```
{
  "name": "hello",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::xxxxxxx:role/xxx",
  "environment": {}
}
```


## ディレクトリ構成
今回 `crawler`というサービスで`api`と`batch`というlambda functionを作成する例で説明してみます。

```
.
├── functions
│   └── api
│   │   ├── function.json
│   │   └── index.js
│   └── batch
│       ├── function.json
│       └── index.js
└── project.json
```


Projectという概念の中にそれぞれのfunctionを作成してみました。
また、このような構成にすると共有の`project.json`を使い回し、
差分だけ`function.json`に記載できるので管理コストの削減になるかと思います。

また、 `project.json`と`function.json`は定義が適用されるスコープが違うだけで記述は同じです。

今回はそれぞれこのように設定しました。
[project.json]

```
{
  "name": "crawler"
}
```

[function.json]

```
{
  "name": "api",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::xxxx:role/xxxx",
  "environment": {}
}
```


## Deploy
ディレクトリ構成のところで例に出した構成でのDeployを説明します。

```
$ apex deploy api
$ apex deploy batch
```

はい、とても簡単です。
しかし、Lambdaの環境変数設定を行うのにはどのようにすればいいか？という疑問が出ると思います。

```
$ apex deploy api -s DB_PASS=xxxx -s TOKEN=xxxx
```

このように`-s`オプションでLambdaの環境変数が設定可能です。

## ロールバック

```
$ apex rollback
```

そのままですね！
しかしここでイケてないところに気づきました。

```
$ apex rollback                                                                                                                                                       
   • rolling back              env= function=api
   • rollback to version: 6    env= function=api
   • function rolled back      current version=6 env= function=api

$ apex rollback                                                                                                                                                       
   • rolling back              env= function=api
   • rollback to version: 7    env= function=api
   • function rolled back      current version=7 env= function=api

$ apex rollback                                                                                                                                                       
   • rolling back              env= function=api
   • rollback to version: 6    env= function=api
   • function rolled back      current version=6 env= function=api

$ apex rollback                                                                                                                                                       
   • rolling back              env= function=api
   • rollback to version: 7    env= function=api
   • function rolled back      current version=7 env= function=api
```

うん・・・versionが `6 -> 7 -> 6 -> 7`・・・・
とは言えこの機能で今の所十分ではある。