ZappaでAWS Lambdaにサーバーレスアプリをデプロイするときにハマったこと

# そもそもZappaとは

Github(英語): https://github.com/Miserlou/Zappa
日本語訳: https://githubja.com/miserlou/zappa

>Zappa makes it super easy to build and deploy server-less, event-driven Python applications (including, but not limited to, WSGI web apps) on AWS Lambda + API Gateway. Think of it as "serverless" web hosting for your Python apps.

とのこと。FlaskやDjangoなどのWebアプリケーションフレームワークを利用したPythonアプリをAWS Lambdaへデプロイする際にとても役に立つ。


以下、ZappaによるAWS Lambdaを利用したアプリの開発時にハマった事象と解決方法を記載していく。

# ハマったこと

## 1. zappaコマンド（templateなど）を実行すると`NoRegionError`となる

### 事象

```shell
$ zappa template dev -l ${your-lambda-arn} -r ${your-role-arn}
Calling template for stage dev..
Warning! AWS Lambda may not be available in this AWS Region!
Warning! AWS API Gateway may not be available in this AWS Region!
Oh no! An error occurred! :(

==============

Traceback (most recent call last):
（中略）
botocore.exceptions.NoRegionError: You must specify a region.

==============

Need help? Found a bug? Let us know! :D
File bug reports on GitHub here: https://github.com/Miserlou/Zappa
And join our Slack channel here: https://slack.zappa.io
Love!,
 ~ Team Zappa!
```

### 解決

`zappa_settings.json`に`"aws_region": "aws-region-name"`を記載する。

```zappa_settings.json
{
    "dev": {
        "app_function": "server.app",
        "aws_region": "ap-northeast-1",
        ...
    }
}
```

## 2. `zappa template`コマンドを実行すると`AttributeError: 'ZappaCLI' object has no attribute 'apigateway_policy'`となる

### 事象

```shell
$ zappa template dev -l ${your-lambda-arn} -r ${your-role-arn}                                           
Calling template for stage dev..
Oh no! An error occurred! :(

==============

Traceback (most recent call last):
  File "/root/.local/share/virtualenvs/application-NgYdrrUH/lib/python3.6/site-packages/zappa/cli.py", line 2779, in handle
    sys.exit(cli.handle())
  File "/root/.local/share/virtualenvs/application-NgYdrrUH/lib/python3.6/site-packages/zappa/cli.py", line 509, in handle
    self.dispatch_command(self.command, stage)
  File "/root/.local/share/virtualenvs/application-NgYdrrUH/lib/python3.6/site-packages/zappa/cli.py", line 553, in dispatch_command
    json=self.vargs['json']
  File "/root/.local/share/virtualenvs/application-NgYdrrUH/lib/python3.6/site-packages/zappa/cli.py", line 666, in template
    policy=self.apigateway_policy,
AttributeError: 'ZappaCLI' object has no attribute 'apigateway_policy'

==============

Need help? Found a bug? Let us know! :D
File bug reports on GitHub here: https://github.com/Miserlou/Zappa
And join our Slack channel here: https://slack.zappa.io
Love!,
 ~ Team Zappa!
```

### 解決

zappaのバージョンを`0.47.0`に下げる。

```shell
$ zappa -v
0.48.2
$ pipenv install zappa==0.47.0 --skip-lock
Installing zappa==0.47.0…
Adding zappa to Pipfile's [packages]…
✔ Installation Succeeded 
Installing dependencies from Pipfile…
     ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 1/1 — 0
```

### 参考

https://github.com/Miserlou/Zappa/issues/1747

## 3. `zappa deploy`や`update`コマンドを実行すると`Status check on the deployed lambda failed. A GET request to '/' yielded a 500 response code.`となる

### 事象

```shell
$ zappa deploy dev
Calling deploy for stage dev..
Downloading and installing dependencies..
 - markupsafe==1.1.1: Using locally cached manylinux wheel
 - sqlite==python3: Using precompiled lambda package
Packaging project as zip.
Uploading app-dev-1560529924.zip (8.5MiB)..
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 8.91M/8.91M [00:00<00:00, 20.6MB/s]
Scheduling..
Scheduled app-dev-zappa-keep-warm-handler.keep_warm_callback with expression rate(4 minutes)!
Uploading app-dev-template-1560529930.json (1.6KiB)..
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.60K/1.60K [00:00<00:00, 24.2KB/s]
Waiting for stack app-dev to create (this can take a bit)..
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [00:15<00:00,  5.84s/res]
Deploying API Gateway..
Error: Warning! Status check on the deployed lambda failed. A GET request to '/' yielded a 500 response code.
```

### 解決

コマンドでのデプロイ時に動作確認としてAPI Gatewayの`/`リソースに対してGETリクエストが行われるが、そのリクエストに対するLambdaからのレスポンスが500エラーとなっている。
Lambda側の実行ロールの権限やソースコード自体に問題がないか確認をする。

## 4. `zappa deploy`や`update`コマンドを実行すると`Provided role 'role_arn' cannot be assumed by principal 'events.amazonaws.com'.`となる

### 事象

```shell
$ zappa update dev
Calling update for stage dev..
Downloading and installing dependencies..
 - markupsafe==1.1.1: Using locally cached manylinux wheel
 - sqlite==python3: Using precompiled lambda package
Packaging project as zip.
Uploading app-dev-1560527282.zip (8.5MiB)..
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 8.91M/8.91M [00:00<00:00, 23.3MB/s]
Updating Lambda function code..
Updating Lambda function configuration..
Uploading app-dev-template-1560527288.json (1.6KiB)..
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.60K/1.60K [00:00<00:00, 14.9KB/s]
Waiting for stack app-dev to update..
6res [00:09,  1.48s/res]                                                                                                                          
Deploying API Gateway..
Scheduling..
Unscheduled app-dev-zappa-keep-warm-handler.keep_warm_callback.
Oh no! An error occurred! :(

==============

Traceback (most recent call last):
（中略）
cannot be assumed by principal 'events.amazonaws.com'.

==============

Need help? Found a bug? Let us know! :D
File bug reports on GitHub here: https://github.com/Miserlou/Zappa
And join our Slack channel here: https://slack.zappa.io
Love!,
 ~ Team Zappa!
```

### 解決

Lambda関数の実行ロールとしたいIAMロールの信頼されたエンティティに`events.amazonaws.com`を追加する必要がある。

https://console.aws.amazon.com/iam/home より、対象のIAMロールで[信頼関係]タブ-[信頼関係の編集]から、ポリシードキュメントの`events.amazonaws.com`を追記し、[信頼ポリシーの更新]をクリック。

以下はポリシードキュメントの編集例。

```PolicyDocument_example.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "events.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

### 参考

https://silvaneves.org/provided-role-cannot-be-assumed-by-principal-eventsamazonawscom.html

以上