Serverless FrameworkでChatwork通知用APIを作成する方法
こんにちは。串上です。
前回ReactとAWS API Gatewayの連携方法を書いた者です。
前回の記事を読んでいただいた方は思ったかもしれませんが、API Gatewayって手動で設定するの面倒ですよね。
そこで今回はそのあたりの設定をコマンド一発で自動化してくれる素敵なフレームワークであるServerless Framework(v1.1)について書きたいと思います。 https://serverless.com/
Serverless Frameworkを利用するにあたって、 AWS CLI(AWSをコマンドラインからごにょごにょするツール)をインストールする必要があるので、まずはそちらから。
pipをインストール
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py" sudo python get-pip.py
え、AWS CLIちゃうん?って思った方、そうあせらないでください。
AWS CLIをインストールするためにはPythonのパッケージ管理ツールpipが必要なんです。
とりあえず入れて下さい。
こんな感じになればインストール完了です。
Collecting pip Downloading pip-9.0.1-py2.py3-none-any.whl (1.3MB) 100% |████████████████████████████████| 1.3MB 816kB/s Collecting wheel Downloading wheel-0.29.0-py2.py3-none-any.whl (66kB) 100% |████████████████████████████████| 71kB 5.9MB/s
次に行きます。
AWS CLIをインストール
sudo pip install awscli
で、OKと思ったらsixがどうちゃら言われてエラーが出たら、以下の魔法版で実行して下さい。
sudo pip install awscli --upgrade --ignore-installed six
するとこんな感じにインストールが完了します。
Collecting awscli Downloading awscli-1.11.15-py2.py3-none-any.whl (1.0MB) 100% |████████████████████████████████| 1.0MB 804kB/s Collecting six Downloading six-1.10.0-py2.py3-none-any.whl ... Successfully installed awscli-1.11.15 botocore-1.4.72 colorama-0.3.7 docutils-0.12 futures-3.0.5 jmespath-0.9.0 pyasn1-0.1.9 python-dateutil-2.6.0 rsa-3.4.2 s3transfer-0.1.9 six-1.10.0
AWS CLIのインストールは完了しましたが、このままではまだ「だれのAWSに接続するん?」って話なんで、そのあたりも設定していきます。
AWS CLIの設定
aws configure
ってコマンドを打つと、以下のように質問してくるので答えます。
AWS Access Key ID [None]: xxxxxxxxxx AWS Secret Access Key [None]: yyyyyyyyyy Default region name [None]: ap-northeast-1 Default output format [None]: json
region nameとoutput formatは好きに変えて下さい。
自分はjson好きの日本在住なので上記の設定にしています。
xxxxxxxxxxとyyyyyyyyyyはAWSのユーザーを作成したときの一回だけしかダウンロードまたは表示ができないアレです。
一回だけだなんて厳しいですよね。
しかもユーザー作成したときなんて何にもわかってないときやのに、ダウンロードってなんやねんって感じですよね。
でもダウンロードはしといてください。
そして安全な場所に保管しておいて下さい。
確かファイル名はcredentialsだったような。
これが完了すると、~/.aws/credentialsっていうファイルが出来ます。 中身はこんな感じ。
[default] aws_access_key_id = xxxxxxxxxx aws_secret_access_key = yyyyyyyyyy
これでAWS CLIが使えるようになったので、ついにServerless Frameworkをインストールします。
※Serverless Frameworkをインストールするにはnpmが必要です。
npmって何?ってひとはこちらを参考にしてください。
Serverless Frameworkをインストール
npm install -g serverless
こんな感じになればインストール完了です。
└─┬ serverless@1.1.0 ├── agent-base@2.0.1 ├── ansi-regex@2.0.0 ├── ansi-styles@2.2.1 ├─┬ archiver@1.1.0 │ └── async@2.1.1 ...
これでserverlessコマンドが使えるようになったんですが、いちいちserverlessとか長いしタイポしそうなんで、
slsって短縮コマンドも用意されています。
早速プロジェクトを作成しましょう!
Serverless Frameworkでプロジェクトを作成
mkdir serverless-chatwork cd serverless-chatwork sls create --template=aws-nodejs
するとこんな感じにカッコイイロゴが表示されれば、プロジェクトの作成は完了です。
Serverless: Generating boilerplate… _______ __ | _ .-----.----.--.--.-----.----| .-----.-----.-----. | |___| -__| _| | | -__| _| | -__|__ --|__ --| |____ |_____|__| \___/|_____|__| |__|_____|_____|_____| | | | The Serverless Application Framework | | serverless.com, v1.1.0 -------' Serverless: Successfully generated boilerplate for template: "aws-nodejs" Serverless: NOTE: Please update the "service" property in serverless.yml with your service name
nodejs?僕パイソニスタなんだけど。って人はpython版で作成してください。 templateのaws-nodejsをaws-pythonに変更すればOKです。
ではプロジェクトの設定をしていきましょう。
Serverless Frameworkプロジェクトの設定
serverless.ymlというファイルがあるので以下のように編集します。
service: serverless-chatwork # プロジェクト名です。好きな値をどうぞ。 provider: name: aws runtime: nodejs4.3 # stage: dev # デプロイする環境。デフォルトではdevになってる。開発環境なんていらんよ。って人はproduction等に変更しましょう。 profile: default # ~/.aws/credentialsの中の[]の中の文字です。defaultの場合はこの行削除してもいいです。 region: ap-northeast-1 # AWSのリージョンです。東京に変更したい場合はこんな感じ。 functions: push: # 作成するLambdaの名前 handler: handler.push # handler.js内の関数名 events: - http: path: v1/push # API Gatewayのエンドポイント v1とかバージョンを作っとくと大規模な改修の際に便利かも? method: post # get, post, put, delete等 cors: true # これ設定するとCORSが有効になって外部からも叩けるよ plugins: - serverless-run-function-plugin # あとで説明するけど、これ入れとくとローカルでテストできます。
上の設定で出て来るserverless-run-function-pluginですが、デプロイする前にローカルでAPIのテスト出来るようになるので入れておきましょう。
serverless-run-function-pluginのインストール
npm install -g serverless-run-function-plugin
早速ローカルでテストを実行する前に、handler.jsも修正しましょう。 handler.jsはLambdaの中身になります。
handler.jsとevent.jsonの設定
今回は以下のように修正して下さい。 簡単に補足するとevent.jsonはコマンドから実行するときにhandler.jsのeventに任意の値を設定するためのものです。
handler.js
'use strict'; // 厳しいモードでいきましょう。 const request = require('request'); const CHATWORK_TOKEN = 'チャットワークAPIを利用するためのトークン'; module.exports.push = (event, context, callback) => { var response = { statusCode: 200, // CORSを有効にする場合は設定必要。*は全てなので許可する範囲を設定したい人は修正してください。 headers: { "Access-Control-Allow-Origin" : "*" }, }; // postでjson文字列を送信した場合、受け取ったデータは全てevent.bodyに入っています const post = JSON.parse(event.body); // room_idは必須にする if(typeof post.room_id == 'undefined'){ response.statusCode = 400; response.body = JSON.stringify({ message: 'room_idを指定して下さい。' }); return callback(null, response); } // textは必須にする if(typeof post.text == 'undefined'){ response.statusCode = 400; response.body = JSON.stringify({ message: 'textを指定して下さい。' }); return callback(null, response); } // チャットワークにチャット送信 pushToChatwork(post.room_id, post.text); response.body = JSON.stringify({ message: '送信完了' }); callback(null, response); }; // チャットワークにチャット送信 const pushToChatwork = (room_id, text) => { var options = { url: 'https://api.chatwork.com/v1/rooms/' + room_id + '/messages', headers: { 'X-ChatWorkToken': CHATWORK_TOKEN }, form: { body: text }, json: true }; request.post(options); }
event.json
{ "body": "{\"room_id\": \"チャットワークのルームID\", \"text\": \"投稿したい文字列\"}" }
また、今回requestパッケージを使用したので、npmの下準備をしてインストールしましょう。
npm init Press ^C at any time to quit. name: (serverless-chatwork) version: (1.0.0) description: Chatwork API with Serverless Framework entry point: (handler.js) test command: git repository: keywords: author: license: (ISC) About to write to /Users/shunkushigami/tmp/serverless-chatwork/package.json: { "name": "serverless-chatwork", "version": "1.0.0", "description": "Chatwork API with Serverless Framework", "main": "handler.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
requestのインストール
npm install request --save
これでnode_modulesというディレクトリが出来て、デプロイ時に一緒にアップしてくれます。
ローカルでテストを実行
sls run -f push
-fの後に実行する関数名を指定すると実行してくれます。
こんな感じに表示されて、
Serverless: ----------------- Serverless: Success! - This Response Was Returned: Serverless: { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*" }, "body": "{\"message\":\"送信完了\"}" }
指定のルームにチャットが届けば成功です!
今のままではローカルでしか実行できないので、いよいよデプロイします。
Serverless FrameworkでAWSにデプロイする
sls deploy
たったのこれだけです。
Serverless Frameworkやばいですね。
これだけでCloudFormationを作成してくれて、それらをS3にアップしてくれて、Lambda作ってくれて、API Gateway作ってくれます。
こんな感じでエンドポイントが表示されればデプロイ完了です。
Serverless: Creating Stack… Serverless: Checking Stack create progress… .. Serverless: Stack create finished… Serverless: Deprecation Notice: Starting with the next update, we will drop support for Lambda to implicitly create LogGroups. Please remove your log groups and set "provider.cfLogs: true", for CloudFormation to explicitly create them for you. Serverless: Packaging service… Serverless: Uploading CloudFormation file to S3… Serverless: Uploading service .zip file to S3… Serverless: Updating Stack… Serverless: Checking Stack update progress… ................. Serverless: Stack update finished… Service Information service: serverless-chatwork stage: dev region: ap-northeast-1 api keys: None endpoints: POST - https://xxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/v1/push functions: serverless-chatwork-dev-push: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxxxx:function:serverless-chatwork-dev-push
では、AWSにアップされたようなのでコマンドから実際にエンドポイントが効いているか試してみましょう。
Serverless FrameworkでAPIをコールする
sls invoke -f push -p event.json
このコマンドで実際にリモートのAPIをevent.jsonの内容でコールしてくれます。
-pで使用するevent用jsonを指定します。
以下のように表示されて、実際にチャットが届けば完了です!
{ "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*" }, "body": "{\"message\":\"送信完了\"}" }
作ったはいいけど、他の人に試してもらうためには以下のように教えてあげましょう。
jQueryから試す
jQueryマイスターには以下で試してもらいましょう。
var data = { room_id: "チャットワークのルームID", text: "投稿したい文字列" } $.ajax({ url: "生成したエンドポイント", type: "POST", dataType: "JSON", data: JSON.stringify(data) });
Curlから試す
コマンドライン大好きな人には以下で試してもらいましょう。
curl 生成したエンドポイント -X POST -d "{\"room_id\": "チャットワークのルームID", \"text\": \"投稿したい文字列\"}"
まとめ
以上、長々と書きましたが、Serverless Frameworkを実践的に使用する方法を解説しました。
Serverless Frameworkとかサーバーレス自体に興味ある人はぜひ試してみて下さい。
次回以降はDynamoDBとの連携方法や、Lambdaの定期実行等も書いていきたいと思いますので、乞うご期待!
お疲れ様でした。