(社内勉強会) AWS サーバレスAPIハンズオン

# 概要
AWSにてWebAPIをサーバレスで構築するハンズオンです。

# ハンズオンの内容
1. AWSコンソールからAPIGatewayにてモックAPIを構築する
2. AWSコンソールから手動でAPIGatewayとLambdaを構築する
2. SAM（Serverless Application Model)により自動でAPIGatewayとLambdaを構築する`（※時間が足りれば）`

# 事前準備
- AWSアカウント登録
- AWS CLIインストール
- SAM CLIインストール

## AWSCLIのインストール
下記ページからWindowsのMSIをダウンロードして、インストールお願いします。
https://aws.amazon.com/jp/cli/

コマンドプロンプトにて下記コマンドを実行し、バージョンが表示されればOK

```
$ aws --version
aws-cli/1.16.212 Python/3.6.0 Windows/10 botocore/1.12.202
```![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10978/baa42ebc-a53b-9029-4bf5-9825423fb806.png)


## SAMCLIのインストール
下記ページからWindowsのMSIをダウンロードして、インストールお願いします。
https://aws.amazon.com/jp/serverless/sam/

コマンドプロンプトにて下記コマンドを実行し、バージョンが表示されればOK

```
$ sam --version
SAM CLI, sam --version 0.19.0
```

# 1. AWSコンソールからAPIGatewayにてモックAPIを構築する
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10978/165a2bf6-a14c-39f8-25c4-c5e5a5ea0622.png)


AWSマネジメントコンソールからログイン
https://console.aws.amazon.com/console/home

## [APIGateway]
### API作成
今すぐはじめるを選択
1. 「REST」を選択
2. 「新しいAPI」を選択
3. API名："test"
4. エンドポイントタイプ：「リージョン」
5. APIの作成ボタン押下

### モデル作成
モデルを選択
1. 「作成」ボタン押下
2. モデル名："user"
3. コンテンツタイプ："application/json"
4. モデルのスキーマを下記の通り登録

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "User Schema",
  "type" : "object",
  "properties" : {
    "userId" : { "type" : "string" },
    "userName" : { "type" : "string" }
  }
}
```

### メソッド作成
GETメソッドを作成します。
1.「アクション」→「メソッド作成」
2. 「GET」を選択
3. 統合タイプ：Mock → 保存

### 統合レスポンス
1. メソッドレスポンスのステータス：200を選択
2. マッピングテンプレート：Content-Typeを"application/json"で登録。
3. テンプレートの生成で「User」を選択して下記の通り登録し、保存ボタン押下

```
#set($inputRoot = $input.path('$'))
{
  "userId" : "1",
  "userName" : "test"
}
```
### テスト実行
レスポンス本文が下記の通りとなればOK

```
{
  "userId": "1",
  "userName": "test"
}
```

### デプロイ
アクション→APIのデプロイ
デプロイされるステージ：「新しいステージ」
ステージ名：dev
デプロイボタン押下

ステージ[dev]を選択
エクスポート：Swaggerの形式でエクスポート

### 補足
* Swagger＋Postman拡張の形式でエクスポートすると、Postmanから簡単にAPIをコールできます。
* APIクライアント開発チームにAPIスキーマとモックAPIを提供することで、APIロジック実装との並行開発が可能になります。

# 2. AWSコンソールから手動でAPIGatewayとLambdaを構築
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10978/a078a629-03ca-1dbe-9142-2439f1a90147.png)


## [AWS Lambda]
### Lambda関数作成
1. サービスから「Lambda」を選択
2. 関数の作成ボタンを押下
3. 「一から作成」を選択
4. 関数名："getUser"
5. ランタイム：「Python3.7」 ※言語はお好みで
6. 実行ロール：「基本的なLambdaアクセス権限でロールを作成」
7. 関数の作成ボタンを押下

### Lambda関数のテスト
1. テストボタン押下
2. イベント名："test"
3. 作成ボタン押下
4. コードを編集

```Python
import json

def lambda_handler(event, context):
    
    response = {
        'userId': '1234567890',
        'userName': 'hirata'
    }
    
    return {
        'statusCode': 200,
        'body': json.dumps(response)
    }
```

ファイルを上書き（Ctrl+S)して、保存ボタン押下
テストボタン押下

実行結果の下記の通りに表示されたらOK

```
{
  "statusCode": 200,
  "body": "{\"userId\": \"1234567890\", \"userName\": \"hirata\"}"
}
```

## [APIGateway]
### APIGatewayからLambda関数を呼ぶ設定を行う
1. サービスから「API Gateway」を選択
2. 先程作成したAPI「test」を選択
3. GETメソッド選択
4. 統合リクエストを選択
5. 統合タイプ：「Lambda 関数」に変更
6. Lambdaプロキシ統合の仕様：OFF
7. Lambdaリージョン：「ap-northeast-1」を選択
8. Lambda関数：「getUser」を入力
9. デフォルトタイムアウトの使用：ON
10. 保存ボタン押下

### APIテスト
APIGatewayのGETメソッドのテストを実行
下記のように結果が返ってこればLambda関数が呼ばれたことが確認できます。

[レスポンス本文]

```
{
  "statusCode": 200,
  "body": "{\"userId\": \"22872\", \"userName\": \"hirata\"}"
}
```

# 3. SAMにより自動でAPIGatewayとLambdaを構築
## SAMとは
AWS サーバーレスアプリケーションモデル
https://aws.amazon.com/jp/serverless/sam/

サーバーレスアプリケーション構築用のオープンソースフレームワーク

## 準備
### IAMユーザー作成
AWSマネジメントコンソールにログイン
1. サービスから「IAM」を選択
2. ユーザーを選択
3. 「ユーザーを追加」ボタン押下
4. ユーザー名："SAM"
5. アクセスの種類：「プログラムによるアクセス」を選択 → 「次のステップ」ボタン押下
6. 「既存のポリシーを直接アタッチ」を選択
7. 「AWSCloudFormationFullAccess」「AWSLambdaFullAccess 」「AmazonAPIGatewayAdministrator」「IAMFullAccess」を検索してチェック→「次のステップ」ボタン押下　`※`
8. そのまま「次のステップ」ボタン押下
9. そのまま「ユーザーの作成」ボタン押下
10. 作成完了画面にて「.CSVのダウンロード」ボタンを押下（後で利用するので大事に保管してください）

`※本来は必要最低限の権限を付与しますがハンズオンのため割愛`

### S3バケット作成（sam-deploy-test-{社員番号}) 
1. サービスから「S3」を選択
2. 「バケットを作成する」ボタン押下
3. バケット名："sam-deploy-test-{社員番号}"`※` → 次へボタン押下
4. オプションの設定：そのまま次へボタン押下
5. アクセス許可の設定：そのまま次へボタン押下
6. 確認：「バケットを作成」ボタン押下

`※同じ名前のバケットを作成できないため`

### ローカル環境にAWS認証情報設定
ローカル環境のコマンドプロンプトにて下記コマンド実行
先程ダウンロードしたCSVを確認してアクセスキーとシークレットキーを入力

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

### SAM実行
#### プロジェクト作成

```
$ sam init --runtime python3.7 --name test
```

作成されたtestフォルダに移動
testフォルダの中身を確認

```
hello_world ←ここにLambdaで実行するソースファイルが入っています
tests
.gitignore
event.json
README.md
template.yaml ←SAMテンプレート
```

#### デプロイパッケージ作成

```
$ sam package --s3-bucket sam-deploy-test-{社員番号} --output-template-file packaged.yaml --no-verify
・・・
Successfully packaged artifacts and wrote output template to file packaged.yaml.
```

package.yamlファイルが作成され、S3に「sam-deploy-test-{社員番号}」のバケットとその中にデプロイ用のファイルがアップロードされます。

※プロキシ経由の場合は下記実行しておく

```
SET HTTPS_PROXY=http://{ユーザー}:{パス}@{ホスト}:{ポート}
```

#### デプロイ

```
$ sam deploy --template-file packaged.yaml --stack-name api --no-verify --capabilities CAPABILITY_IAM

・・・・
Successfully created/updated stack - api
```
デプロイは、WEBコンソールのCloudformation画面からも可能です。

#### 確認
スタック作成結果は、コンソールのCloudformation画面にて確認
APIGatewayのAPI、Lambda関数が作成されているのを確認

最後はお片付けとして、コンソールのCloudformation画面にてスタック削除することで、作成されたAPIとLambdaが削除されます。

## おまけ
### AWSのサーバレスAPI環境をコード化することでデプロイ自動化が可能
![ci.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10978/b9a6b0b2-537d-61cc-a1f2-37d039f9fd7b.png)