Slash CommandsとAWS Lambdaで作るChatOpsの基本機能
モバイルアプリサービス部の五十嵐です。
SlackでChatOpsを始めようと思い、SlackのSlashCommandsという機能とAWS Lambdaを使って基本的な機能を作ってみました。
はじめに
Slash Commandsは、 /command
のフォーマットで任意のコマンド機能を作成できる機能です。
まずは以下の記事を参照いただくと、基本的な仕組みが理解できると思います。
【新機能】AWS LambdaにSlack連携のBluePrintが登場。ChatOpsがより手軽に | Developers.IO
注意点としては、Slash Commandsには以下の制約があります。
Slash Commandsのレスポンスは、Slash Commandsはの実行者にしか見えない。<2016-09-08 20:23:32 訂正>- デフォルトではSlash Commandsはの実行者にしか見えないのですが、レスポンスのオプションで
"response_type": "in_channel"
を付けることで見るようになります。
- デフォルトではSlash Commandsはの実行者にしか見えないのですが、レスポンスのオプションで
- Slash Commandsのリクエストは3秒でタイムアウトする。
実際に何かの処理をするのにはたいてい3秒以上かかりますし、ログが実行者にしか見えないのも困ります。これらを解決するために、チャンネルへのログ出力はSlack Botを使い、時間のかかる処理は非同期実行で行う方法を以下に紹介します。
Slack Bot
Slack Botを使うには、Slash Commandsのリクエストパラメータに含まれる response_url
にメッセージをPostします。以下はリクエストパラメータのサンプルです。
token=MXTo9FagJ91hN2crCGgZifNe team_id=T0001 team_domain=example channel_id=C2147483705 channel_name=test user_id=U2147483697 user_name=Steve command=/weather text=94070 response_url=https://hooks.slack.com/commands/1234/5678
このURLは、Slash Commandsがリクエストされてから 30分間有効で、5回まで使うことができます。 6回目は 404 Not Found
になります。メッセージのフォーマットは Message Formatting | Slack などを参照してください。
非同期実行
Slash Commandsのリクエストは3秒以内に返す必要があるので、リクエストを受け付けるLambdaから更に非同期で後続の何かに処理を渡す必要があります。最初は後続の処理もAPI Gateway+Lambdaという構成にしてHTTPリクエストで処理を渡そうとしたんですが、Lambdaの起動にわずかながら時間がかかることがあるのでトータルで3秒を超えてしまうことがありました。
そこで後続の処理はHTTPリクエストではなく直接Lambdaを非同期でinvokeすることにしました。以下はリファレンスのスニペットですが、 InvocationType
を Event
にすることで終了を待たずに実行することができます。
Class: AWS.Lambda — AWS SDK for JavaScript
var params = { FunctionName: 'STRING_VALUE', /* required */ ClientContext: 'STRING_VALUE', InvocationType: 'Event | RequestResponse | DryRun', LogType: 'None | Tail', Payload: new Buffer('...') || 'STRING_VALUE', Qualifier: 'STRING_VALUE' }; lambda.invoke(params, function(err, data) { if (err) console.log(err, err.stack); // an error occurred else console.log(data); // successful response });
シーケンス図にすると以下の様なイメージです。
実行例
実際に動作させた画像がこちらです。
今回は /echo
という、入力したコマンドとパラメータをBOTがオウム返しするだけのコマンドです。
このように入力すると...
BOTが入力したコマンドの情報をまとめてオウム返ししています。 Only visible to you と書かれたメッセージは、SlashCommandsリクエストに対するレスポンスに設定したメッセージです。
サンプルコード
Node.jsの書き方が拙いですが、サンプルコードをGistに公開しました。
Lambda1
Lambda2
注意点としては、slackCommandEntry.jsのLambdaからslackCommandProcess.jsのLambdaを起動するため、slackCommandEntry.jsのLambdaには以下の様なLambdaの実行権限が必要です。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1472382370000", "Effect": "Allow", "Action": [ "lambda:InvokeAsync", "lambda:InvokeFunction" ], "Resource": [ "*" ] } ] }
余談
なぜChatOpsが必要かを書いておきたいと思います。
システムを運用するにはたくさんのツール(例えばデプロイツールや運用オペレーションツールなど)が使われます。それらは要望によりどんどん増えていくものです。またツールによって依存する言語環境やライブラリが違うということも良くあります。このような状況になってくると、エンジニア以外の人が使うためのハードルが高くなったり、引き継ぎが大変になるなどの問題が出てきます。
このような問題への対処の一つとしてChatOpsが使えると思います。ChatOpsならチャット画面にコマンドを打つだけなので、誰でも操作ができて環境依存がありません(もちろんバックエンドはありますが、それを知る必要があるのは一部のエンジニアだけです)。また、ログがチャット上に残るので誰がどのような操作を行ったか一目でわかるのも大きなメリットです。
まとめ
この基本機能を使用すれば、AWS SDKを使ってAWS上のリソースの操作を行ったり、HTTPリクエストで外部のサービスの操作を行ったり、LambdaでできることならChatOpsに置き換えられると思います。ChatOpsの導入にぜひご活用ください。