5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Slack + Lambda (Python) でAWS API Gatewayモックを作ってみよう

Last updated at Posted at 2019-03-21

#前回までのあらすじ
前々回の記事でAPI Gatewayを使ってAPIのモックを作ってみました。
API Gatewayの統合リクエストの統合タイプ:Mockを使えば固定値を返すAPIモックは簡単に作れることが分かったので、今後も業務でちょこちょこ作っていこうと思います。
が、いちいちAWSコンソールから作るのが面倒なので、Slackからサクッと作れるようにしたいと思います。

#API Gatewayを作るLambda(Python)の作成
PythonからAWSをコントロールするためにBoto3を使います。
参考にしたBoto3のドキュメント

##Slackでのキーワード
Slackからは以下のキーワードでAPI Gatewayを作ることにします。
api_gateway [API名] [リソース名] [メソッド] [ステータスコード] [レスポンスボディ] [ステージ名]
Slackから受け取った上記のキーワードをLambdaでは以下のように取り出して変数に格納することにします。

# クエリ文字列解析
query = parse_qs(event.get('body') or '')

SETTINGS = query.get('text', [''])[0].split(' ')
API_GATEWAY_NAME = SETTINGS[1]          # API名
PATH_PART = SETTINGS[2]                 # リソース名
HTTP_METHOD = SETTINGS[3]               # メソッド
STATUS_CODE = SETTINGS[4]               # ステータスコード
RESPONSE_TEMPLATES = SETTINGS[5]        # レスポンスボディ
STAGE_NAME = SETTINGS[6]                # ステージ名

##API Gatewayの作成

REST_API_ID = agw.create_rest_api(name = API_GATEWAY_NAME)

##ルートのリソースIDの取得とリソースの作成

# ルートのリソースIDの取得
PARENT_ID = agw.get_resources(restApiId = REST_API_ID['id'])

# リソースの作成
RESOURCE_ID = agw.create_resource(
    restApiId = REST_API_ID['id'],
    parentId = PARENT_ID['items'][0]['id'],
    pathPart = PATH_PART
    )

##メソッドリクエストの作成

agw.put_method(
    restApiId = REST_API_ID['id'],
    resourceId = RESOURCE_ID['id'],
    httpMethod = HTTP_METHOD,
    authorizationType = 'None'
    )

##統合リクエストの作成

agw.put_integration(
    restApiId = REST_API_ID['id'],
    resourceId = RESOURCE_ID['id'],
    httpMethod = HTTP_METHOD,
    type = 'MOCK',
    requestTemplates = {'application/json':'{"statusCode":' + STATUS_CODE + '}'}
    )

##メソッドレスポンスの作成

agw.put_method_response(
    restApiId = REST_API_ID['id'],
    resourceId = RESOURCE_ID['id'],
    httpMethod = HTTP_METHOD,
    statusCode = STATUS_CODE,
    responseModels = {'application/json': 'Empty'}
    )

##統合レスポンスの作成

agw.put_integration_response(
    restApiId = REST_API_ID['id'],
    resourceId = RESOURCE_ID['id'],
    httpMethod = HTTP_METHOD,
    statusCode = STATUS_CODE,
    responseTemplates = {'application/json': RESPONSE_TEMPLATES }
    )

##作成したAPIのデプロイ

agw.create_deployment(
    restApiId = REST_API_ID['id'],
    stageName = STAGE_NAME
    )

##呼び出しURLをSlackに返す
手を抜いてリージョンはコードに埋め込んでいるので、可変にしたい場合は変数で逃しておいてください。

RESOURCE_NAME = agw.get_resources(restApiId = REST_API_ID['id'])
URL = 'https://' + REST_API_ID['id'] + '.execute-api.ap-northeast-1.amazonaws.com/' + STAGE_NAME + '/' + PATH_PART
return {
    'statusCode': 200,
    'body': json.dumps({
        'text': URL
        })
     }

##コードのまとめ
上記のコードをまとめると以下のようになります。
余計なリクエストを受けないようにSlackトークンをチェックしています。
SlackトークンはLambdaの環境変数にセットしそれをos.environ.get('SLACK_TOKEN')で呼び出しています。
Slackのキーワードが不足している時の処理などは入れていないので、必要に応じて追加してください。

import boto3
import json
import os
from urllib.parse import parse_qs
 
agw = boto3.client('apigateway')
token = os.environ.get('SLACK_TOKEN')
 
def lambda_handler(event, context):
     
    # クエリ文字列解析
    query = parse_qs(event.get('body') or '')
     
    # 設定値
    SETTINGS = query.get('text', [''])[0].split(' ')
    API_GATEWAY_NAME = SETTINGS[1]          # API名
    PATH_PART = SETTINGS[2]                 # リソース名
    HTTP_METHOD = SETTINGS[3]               # メソッド
    STATUS_CODE = SETTINGS[4]               # ステータスコード
    RESPONSE_TEMPLATES = SETTINGS[5]        # レスポンスボディ
    STAGE_NAME = SETTINGS[6]                # ステージ名
     
    # slackトークンの確認
    if query.get('token', [''])[0] != token:
        return { 'statusCode': 400 }
     
    # API Gatewayの作成
    REST_API_ID = agw.create_rest_api(name = API_GATEWAY_NAME)
 
    # ルートのリソースIDの取得
    PARENT_ID = agw.get_resources(restApiId = REST_API_ID['id'])
    # リソースの作成
    RESOURCE_ID = agw.create_resource(
        restApiId = REST_API_ID['id'],
        parentId = PARENT_ID['items'][0]['id'],
        pathPart = PATH_PART
        )
     
    # メソッドリクエストの作成
    agw.put_method(
        restApiId = REST_API_ID['id'],
        resourceId = RESOURCE_ID['id'],
        httpMethod = HTTP_METHOD,
        authorizationType = 'None'
        )
     
    # 統合リクエストの作成
    agw.put_integration(
        restApiId = REST_API_ID['id'],
        resourceId = RESOURCE_ID['id'],
        httpMethod = HTTP_METHOD,
        type = 'MOCK',
        requestTemplates = {'application/json':'{"statusCode":' + STATUS_CODE + '}'}
        )
     
    # メソッドレスポンスの作成
    agw.put_method_response(
        restApiId = REST_API_ID['id'],
        resourceId = RESOURCE_ID['id'],
        httpMethod = HTTP_METHOD,
        statusCode = STATUS_CODE,
        responseModels = {'application/json': 'Empty'}
        )
     
    # 統合レスポンスの作成
    agw.put_integration_response(
        restApiId = REST_API_ID['id'],
        resourceId = RESOURCE_ID['id'],
        httpMethod = HTTP_METHOD,
        statusCode = STATUS_CODE,
        responseTemplates = {'application/json': RESPONSE_TEMPLATES }
        )
 
    # 作成したAPIのデプロイ
    agw.create_deployment(
        restApiId = REST_API_ID['id'],
        stageName = STAGE_NAME
        )
         
    # 呼び出しURLをSlackに返す
    RESOURCE_NAME = agw.get_resources(restApiId = REST_API_ID['id'])
    URL = 'https://' + REST_API_ID['id'] + '.execute-api.ap-northeast-1.amazonaws.com/' + STAGE_NAME + '/' + PATH_PART
    return {
        'statusCode': 200,
        'body': json.dumps({
            'text': URL
            })
        }

#AWS Gatewayの作成
上記で作ったLambdaを呼び出すAPI Gatewayを以下の設定で作成します。
・ プロトコル:REST
・ メソッド:POST
・ 統合リクエスト
 ・ 統合タイプ:Lambda関数
 ・ Lambdaプロキシ統合の使用:チェックON
 ・ Lambda関数:作成したLambda関数を指定

#Slackの発信Webhookの作成
・ Outgoing Webhookで
 ・ チャンネル:botを参加させるSlackチャンネルを指定
 ・ 引き金となる言葉:Lambda関数を起動させるトリガー(今回は「api_gateway」と指定)
 ・ URL:上で作成したAPI Gatewayのステージの呼び出しURL
 ・ トークン:表示されているトークンをコピーして、Lambda関数の環境変数に登録
  ・ キー:SLACK_TOKEN(今回の場合)、値:Slackに表示されているトークン
名前のカスタマイズやアイコンはお好みで。

#まとめ
SlackからAPI Gatewayを作れるようになりました。
API Gatewayの削除などまだまだ足りない機能はありますが、上記を参考に追加してみてください。

#プチ連載
1回目 AWS API Gatewayでモックを作ってみよう
2回目 AWS API Gateway + Lambda (Python) でモックを作ってみよう
3回目 Slack + Lambda (Python) でAWS API Gatewayモックを作ってみよう(本記事)

#We're hiring!
AIチャットボットを開発しています。
ご興味ある方は Wantedlyページ からお気軽にご連絡ください!

#参考記事
Boto3 Docs Lambda
Qiita AWS Lambda (Python3) + API Gateway で Slackのbotを作ろう
Qiita [JAWS-UG CLI] API Gateway: #1 RestAPIの作成
Qiita AWS CLIのレスポンス処理は jq 使う前に --query オプションの利用を考えてみよう!
Qiita 【AWS Lambda】API Gatewayを一発で作成するスクリプトを作成してみた(Python版)
AWS CLI Command Reference apigateway

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?