【初心者向け】ゼロからできる！PythonでAWS SAMによるAPI作成とOpenAPIドキュメントの出力

#はじめに
以前、Swaggerツールを使ったOpenAPIドキュメント作成とAPI自動生成の流れを紹介しました。
[【超初心者向け】5分で試せる！OpenAPI(Swagger3.0)ドキュメント作成〜API自動生成](https://qiita.com/se_fy/items/ad05a3c6825bb9612170)

今回は、AWS SAM（Serverless Application Model）を使って[API Gateway](https://aws.amazon.com/jp/api-gateway/) + [AWS Lambda](https://aws.amazon.com/jp/api-gateway/)のサーバレスなwebAPIを作成し、OpenAPIドキュメントを出力してみます。
AWS SAMを使うのは初めてです。ゼロからできるように書いてみます。

#AWS SAMとは
> AWS サーバーレスアプリケーションモデル (SAM、Serverless Application Model) は、サーバーレスアプリケーション構築用のオープンソースフレームワークです。迅速に記述可能な構文で関数、API、データベース、イベントソースマッピングを表現できます。リソースごとにわずか数行で、任意のアプリケーションを定義して YAML を使用してモデリングできます。デプロイ中、SAM が SAM 構文を AWS CloudFormation 構文に変換および拡張することで、サーバーレスアプリケーションの構築を高速化することができます。

> SAM ベースのアプリケーションの構築を開始するには、AWS SAM CLI を使用します。SAM CLI により Lambda に似た実行環境が提供され、SAM テンプレートで定義されたアプリケーションの構築、テスト、デバッグをローカルで実行できます。お使いのアプリケーションを SAM CLI を使用して AWS にデプロイすることもできます。

https://aws.amazon.com/jp/serverless/sam/

[CloudFormation](https://aws.amazon.com/jp/cloudformation/)をサーバーレスアプリケーションで利用しやすくしたフレームワークのようです。
 [API Gateway](https://aws.amazon.com/jp/api-gateway/) , [AWS Lambda](https://aws.amazon.com/jp/api-gateway/) , [DynamoDB](https://aws.amazon.com/jp/dynamodb/) をひとまとめに管理できます。

#前提
OS：Mac
AWSアカウント作成済み

#やること
1. 環境構築(pyenv, pipenv)
2. AWS CLIを使えるようにする
3. AWS SAM CLIを使えるようにする
4. AWS SAMでHello Worldしてみる
5. OpenAPIドキュメントを出力する

#環境構築(pyenv, pipenv)
###1. pyenvのインストール

```
$ brew install pyenv
```
brewコマンドが使えない場合は、以下からHomebrewをインストール
https://brew.sh/index_ja.html
###2. pyenvのバージョン確認
```
$ pyenv --version
pyenv 1.2.15
```
###3. pyenvでpython3.7.0をインストール
```
$ pyenv install 3.7.0
```
###4. pyenvでインストールしたバージョンに切り替え
localの場合は今いるディレクトリに、globalの場合は全体に反映されます。

```
$ pyenv global 3.7.0
$ pyenv local 3.7.0
```
###5. 反映されているか確認
```
$ pyenv versions
  system
* 3.7.0 (set by /Users/yusaku/.pyenv/version)
```

###6. pipenvのインストール
```
$ brew install pipenv
```

###7. pipenvの仮想環境に入る
```
$ pipenv shell
```

#AWS CLIを使えるようにする
###1. aws cliのインストール
```
$ pipenv install awscli
```
###2. aws cliのバージョン確認
```
$ aws --version
aws-cli/1.16.294 Python/3.7.5 Darwin/19.0.0 botocore/1.13.30
```
###3. アクセスキーIDとシークレットアクセスキーの確認
https://console.aws.amazon.com/iam/home?#/security_credentials
`アクセスキー(アクセスキーIDとシークレットアクセスキー)`の`新しいアクセスキーの作成`からアクセスキーを作成し、アクセスキーIDとシークレットアクセスキーを確認します。

###4. awscliの設定
3で確認した情報で設定します。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-welcome.html

```
$ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

#AWS SAM CLIを使えるようにする
###1. AWS SAM CLIのインストール
```
$ pipenv install aws-sam-cli
```
###2. AWS SAM CLIのバージョン確認
```
sam --version
SAM CLI, version 0.34.0
```

#AWS SAMでHello Worldしてみる
今回はpipenv環境にインストールしたpython3.7を使います。
###1. アプリケーションの初期化
```
$ sam init

	SAM CLI now collects telemetry to better understand customer needs.

	You can OPT OUT and disable telemetry collection by setting the
	environment variable SAM_CLI_TELEMETRY=0 in your shell.
	Thanks for your help!

	Learn More: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-telemetry.html

Which template source would you like to use?
	1 - AWS Quick Start Templates
	2 - Custom Template Location
Choice: 1

Which runtime would you like to use?
	1 - nodejs12.x
	2 - python3.8
	3 - ruby2.5
	4 - go1.x
	5 - java11
	6 - dotnetcore2.1
	7 - nodejs10.x
	8 - nodejs8.10
	9 - nodejs6.10
	10 - python3.7
	11 - python3.6
	12 - python2.7
	13 - java8
	14 - dotnetcore2.0
	15 - dotnetcore1.0
Runtime: 10

Project name [sam-app]: AWSsam_test    

Allow SAM CLI to download AWS-provided quick start templates from Github [Y/n]: y

-----------------------
Generating application:
-----------------------
Name: AWSsam_test
Runtime: python3.7
Dependency Manager: pip
Application Template: hello-world
Output Directory: .

Next steps can be found in the README file at ./AWSsam_test/README.md
```

###2. アプリケーションをビルドする
```
$ cd AWSsam_test/
$ sam build
```
###3. アプリケーションをデプロイする
```
$ sam deploy --guided
```
2回目以降は`sam deploy`でOKです。

###4. 動作確認
3で出力されるエンドポイントにアクセスしてみます。

```
$ curl https://hoge.hoge-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
```
hello worldが返ってきました！
AWSコンソールにログインしてLambdaを見てみると、以下のようにAPI GatewayとLambdaが起動していました。
<img width="1170" alt="スクリーンショット 2019-12-05 15.48.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/6f3aab81-0c8e-b56d-1c15-d9d9aff67a5e.png">

###5.Lambda関数を少し変えて実行してみる
`hello_world/app.py`を以下のように変更してみます。

```hello_world/app.py
import json

# import requests


def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello Qiita",
            # "location": ip.text.replace("\n", "")
        }),
    }
```

ビルドしてデプロイします。

```
$ sam build
$ sam deploy
```
エンドポイントにアクセスしてみます。

```
$ curl https://hoge.hoge-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello Qiita"}
```
変更が反映されていることが確認できました。

#OpenAPIドキュメントを出力する
AWSコンソールからAmazon API Gatewayを選択し、デプロイしたAPIを選びます。
以下の画面が表示されるので、ステージをクリックしてエクスポートを選ぶと、Swagger仕様やOpenAPI仕様のドキュメントをjson形式やyaml形式で出力できます。
<img width="1344" alt="スクリーンショット 2019-12-06 9.24.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/3b4a9c00-78fe-b9ef-2659-c5739c6d464d.png">

#おわりに
今回はAWS SAMでREST APIを作成し、OpenAPI仕様ドキュメントをエクスポートしました。
逆にOpenAPI仕様をインポートしてAWS SAMを使ったAPI作成も実施してみたいです。
以下の記事で紹介されていますが、そんなに楽ではなさそう。。
https://dev.classmethod.jp/cloud/aws/serverless-swagger-apigateway/

#参考
[Tutorial: Deploying a Hello World Application](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html)
https://dev.classmethod.jp/cloud/aws/aws-sam-simplifies-deployment/