Amazon API GatewayとLambdaのデプロイやテストについて調べたまとめ

※一部編集中ですがとりあえず更新。

# 概要
Amazon API GatewayとLambdaを用いたサーバーレスなアプリケーションをどのように管理するかという所を調べました。

# 課題
自分が経験してきたWeb開発の仕事に関していうと、ソースコード一式はWebサーバやバージョン管理ツールのリポジトリに保管され、デプロイは開発した差分なりコード一式を本番環境にコピーするというパターンが一般的でした。
これはAPIの機能を実装する時も同じで、基本的にWebアプリケーションと同じように、Webサーバにソースコードを置いて…という開発を行ってきました。

しかしサーバーレスな環境での開発では、少し考え方を変える必要がありました。

API Gatewayで定義するAPIはコードではないし、Lambdaは関数ごとに必要なソースコードとパッケージをまとめてアップロードするという手間をかける必要があります。
テストもRSpecやPHPUnitといった普通のWebアプリケーション用のテストフレームワークは使えなさそうです。

# 解決策の候補

## サーバーレスフレームワークを使う

おそらく最初に試すのはこの方法がお手軽ではないかと思う。
自分が調べ中だと以下が出てきた。
- Serverless Framework … サーバーレスアーキテクチャでの開発やデプロイフローを自動化するコマンドラインツール。
　- https://github.com/serverless/serverless
- JAWS Framework … Serverlessの前身という事らしい。
　- https://github.com/serverless/serverless
- fluct … コンセプトはServerlessと同じだが、Serverlessのほうが大規模なプロジェクトに向いてるらしい？
　- https://github.com/fluct/fluct

## ビルドツールを使う

以下のツールを使ってコマンド一発でデプロイというのがあり得る。
- Gradle ⁺ Gradle AWS Plugin … LambdaをJavaで実装するならコレでビルドすると良さそう。
　- https://github.com/classmethod/gradle-aws-plugin

# Serverlessを試してみる。
2~3時間調べて回った結果、Serverless一択な感じがしたのでインストールして動かしたりしてみようと思います。

ちなみにWindows10のコマンドプロンプト上で試してみます。
npmはインストール済です。nodejsをインストールしておけば大丈夫なはずです。

## Serverlessインストール。

```

> npm install serverless -g
> serverless version
1.0.0-rc.2

```

インストールは問題無し。

## AWS CLIインストール

pipをインストールしてなかったのでします。
Python最新版をインストールしておきます。
https://www.python.org/

Python3.5をインストールしたので、Python本体とpipが入ってるフォルダ（…\Python35と、…\Python35\Scripts）にパスを通しておきます

AWS CLIをインストールします。

```
>pip install awscli
>aws --version
aws-cli/1.10.66 Python/3.5.2 Windows/10 botocore/1.4.56
```

## AWS CLI設定

CLIを使うためには、アクセスキーとリージョンとデフォルトの出力形式を設定します。
設定ファイルに書く方法もあるみたいですが、コマンドたたくのが楽そうです。

東京リージョンでデフォルト出力形式をjsonにする例です。
APIキーはIAMで発行したものを使います。→ https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html

```
>aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

## serverlessでプロジェクトを作成する

serverlessのreadmeに従ってnodejsのプロジェクト？を作ってみます。
プロジェクト名にはアンダーバーは使えないようです。

```
>cd （プロジェクトを作りたいフォルダー）
>serverless create --template aws-nodejs --path serverlesstest
Serverless: Creating new Serverless service...
Serverless: Creating the service in "c:（プロジェクトを作りたいフォルダー）\serverlesstest"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.0.0-rc.2
 -------'

Serverless: Successfully created service with template: "aws-nodejs"
```

--pathで指定した名前でフォルダーが出来ていると思います。

## serverlessの動作確認をしてみる。

readmeに従い以下のコマンドをたたいていきます。

```
>cd (指定したプロジェクト名)
>serverless deploy Deploy to your AWS account
>serverless invoke --function hello
```

デプロイしてみます。CloudFormationを使うので、AWSのアカウントに権限が必要です。
権限の付与で一度困ったので以下に記録を残しました。
http://qiita.com/murakami_jyk/items/aee40783108e90a09c71

```
>cd serverlesstest
>serverless deploy

  Error --------------------------------------------------

     ServerlessError: ServerlessError: User: arn:aws:iam::XXXXXXXXXXXX:user/serverless
     is not authorized to perform: cloudformation:DescribeStackResources
     on resource: arn:aws:cloudformation:us-east-1:XXXXXXXX:stack/serverlesstest-dev/*

     For debugging logs, run again after setting SLS_DEBUG env var.

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues

     Please report this error. We think it might be a bug.
```

エラーになりました。リージョンがus-east-1になっていますが、自分はIAMユーザーに付与したのはap-northeast-1なので、権限が合わないようです。

「--region / -r」というオプションでリージョンを指定できるようなので、指定して再度試します。

```
>serverless deploy -r ap-northeast-1
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
......
Serverless: Stack create finished...
Serverless: Packaging service...

  Serverless Error ---------------------------------------

     Stack 'serverlesstest-dev' does not exist

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
```

順調に行ってたと思ったけど失敗した。
「--verbose / -v 」オプションを付けると全てのイベントを表示できるようなので、これで何が起きてるか分かると思います。

```
>serverless deploy -r ap-northeast-1 -v
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - serverlesstest-dev
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_FAILED - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - DELETE_IN_PROGRESS - AWS::CloudFormation::Stack - serverlesstest-dev
CloudFormation - DELETE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - DELETE_COMPLETE - AWS::CloudFormation::Stack - serverlesstest-dev
Serverless: Stack create finished...
Serverless: Packaging service...

  Serverless Error ---------------------------------------

     Stack 'serverlesstest-dev' does not exist

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
```

S3のBucket作るのに失敗したようです。
権限与えなおします。最終的にCloudformation、S3、IAM、Lambdaの権限がいくつか必要でした。

```
>serverless deploy -r ap-northeast-1 -v
Serverless: Packaging service...
Serverless: Removing old service versions...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - serverlesstest-dev
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - serverlesstest-dev
Serverless: Stack update finished...

Service Information
service: serverlesstest
stage: dev
region: ap-northeast-1
api keys:
  None
endpoints:
  None
functions:
  serverlesstest-dev-hello: arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:serverlesstest-dev-hello
```

デプロイできました。IAMロールやLambda関数ができてました。
Lambda関数を呼び出してみます。「--log / -l」オプションでログを出力してくれるのでテストの時は出しておくと良いかもしれない。

```
>serverless invoke --function hello -r ap-northeast-1 -l
{
    "message": "Go Serverless v1.0! Your function executed successfully!",
    "event": {}
}
--------------------------------------------------------------------
START RequestId: 6640d222-8afa-11e6-8fbc-1b17ce22866f Version: $LATEST
END RequestId: 6640d222-8afa-11e6-8fbc-1b17ce22866f
REPORT RequestId: 6640d222-8afa-11e6-8fbc-1b17ce22866f  Duration: 0.54 ms       Billed Duration: 100 ms         Memory Size: 1024 MB    Max Memory Used: 34 MB
```

デプロイして呼び出すところまで動かす事ができました。
あとAPI Gatewayを構築するのも試して、運用イメージを固めていきたいところです。

# serverlessでAPI Gatewayを追加する。

以下の説明を参照します。
https://github.com/serverless/serverless/blob/master/docs/01-guide/05-event-sources.md

serverlssフレームワークでAPI Gatewayを追加するということは、「関数にHTTPのイベントを追加する」という意味合いになるようです。
serverless.ymlに設定を追記します。AIMポリシーもAPIGatewayの権限を追加する必要があります。

```
 functions:
   hello:
     handler: handler.hello
+    events:
+      - http: GET greet
```

デプロイしてみます。

```
>serverless deploy -r ap-northeast-1 -v
Serverless: Packaging service...
Serverless: Removing old service versions...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - UPDATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::RestApi - ApiGatewayRestApi
CloudFormation - UPDATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceGreet
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Resource - ApiGatewayResourceGreet
CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Resource - ApiGatewayResourceGreet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodGreetGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Method - ApiGatewayMethodGreetGet
CloudFormation - CREATE_COMPLETE - AWS::Lambda::Permission - HelloLambdaPermissionApiGateway
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Method - ApiGatewayMethodGreetGet
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1475741880646
CloudFormation - CREATE_IN_PROGRESS - AWS::ApiGateway::Deployment - ApiGatewayDeployment1475741880646
CloudFormation - CREATE_COMPLETE - AWS::ApiGateway::Deployment - ApiGatewayDeployment1475741880646
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - serverlesstest-dev
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - serverlesstest-dev
Serverless: Stack update finished...

Service Information
service: serverlesstest
stage: dev
region: ap-northeast-1
api keys:
  None
endpoints:
  GET - https://eq0gn26gw1.execute-api.ap-northeast-1.amazonaws.com/dev/greet
functions:
  serverlesstest-dev-hello: arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:serverlesstest-dev-hello
```

API Gatewayが追加され、のエンドポイントが出力されました。

# その他便利なツール

## Postman
API単体でテストしたり、自前で作ったAPI以外も含めて動作確認やテストがしたいときはPostmanというツールが便利そうです。
APIごとにテストを作れるし、一連の流れのテストにも使えます。
JMeterとかでも似たようなことはできそうですが、手軽さとチーム内のシェア機能が特徴かと思います。
　‐ https://www.getpostman.com/