AWS CDK を使って ランダム選択できる Slack Bot を作ってみた #aws #slack #cdk

f:id:uchimanajet7:20200928112946p:plain

目次

前提

9月に入って時間が取れたので AWS Cloud Development Kit (AWS CDK) を触ってみることにしました。というのも、TypeScriptでの実装例は結構な数見かけるのですがPythonの実装例は探し方が悪いのかあまり見当たらず・・・だったら自分で少し触ってみようかと。

aws.amazon.com

github.com

AWS CDKを利用するシーンを考えると、構築や運用に深く関わる可能性が高いため AWS CDKのroadmapが公開されており、今後も継続して更新が続けられていく様子が確認できるところが非常に素晴らしいです。

aws.amazon.com

github.com

というわけで、触れるタイミングで使ってみたので簡単にですがまとめてみました。

Slack bot を作ることにする

CDKを使ってみると言っても、何か動くもので継続的に使ってアップデートできるものが題材にあるといい感じなので、普段利用しているSlackのbotを作ることにしました。

作るのであれば楽しく作って、実際に使えるものが良いので Amazon API GatewayAWS Lambda の定番構成で、AWS SDK for Go でLambda関数を作成しました。

aws.amazon.com

aws.amazon.com

aws.amazon.com

Slackへのメッセージ送信は次のライブラリを利用しました

github.com

今回一番苦労したのは、このライブラリの利用でした。 SlackのAPI側と別名で定義されているメソッドや、APIで必須指定がないものが 必須になっていたりと、ちゃんと確認しながら進めないとダメな感じでした。

slack.com

qiita.com

作ったbotAWS Chatbot と同様に、botにメンションを行いコマンドを実行する仕様としています。

aws.amazon.com

コマンドの詳細はGitHubのReadmeファイルを確認してください

github.com

github.com

スクリーンショットで利用しているbotアイコンについては以下のサイトから取得しました。

stampo.fun

次項からは簡単にコマンドの紹介を行いたいと思います。

hit コマンドについて

f:id:uchimanajet7:20200928113149p:plain

hit コマンドは、Slackのチャンネルに参加しているメンバーからランダムで指定の人数を選択できます。

想定しているユースケースは、レビューメンバーの選出や会議のファシリテーターの選出になります。

実際に、リモートワークにシフトしてから ランダムに誰かを選択する と言ったことが必要になることも多く、Slackのデフォルトアプリでも良い感じがします。

抽選のために専用チャンネルを作るのが運用としては良さそうな感じですが、既存のチャンネルで使いたい時に抽選対象ではないメンバーを指定できるような仕組みも実装しています。

translate コマンドについて

f:id:uchimanajet7:20200928113226p:plain

translate コマンドは、Amazon Translate を利用して日本語を英語に、日本語意外を日本語に翻訳できます。

想定しているユースケースは、SlackでRSS Feed を確認している場合に手軽に翻訳を行えるようにすることになります。

uchimanajet7.hatenablog.com

実際に、SlackでRSS Feedを確認していると場合によっては大量にステータスが更新されることもあり、手軽に翻訳できれば少しは便利になる感じがします。

以前に作ったSlackの国旗絵文字で翻訳する方法でも対応できるのですが、Slackのイベント発火がワークスペース全体となり、特定のチャンネルや条件で絞れないためワークスペースの参加者が多い、絵文字リアクションの利用が多い場合は、翻訳と関係ないイベントが大半となり Amazon API GatewayAWS Lambda の実行回数が増えることになります。

uchimanajet7.hatenablog.com

link コマンドについて

f:id:uchimanajet7:20200928113301p:plain

link コマンドは、botにメンションする際にSlackに添付したファイルをS3にアップロードして、ファイル取得が可能となる署名付きURL(Pre-Signed URL)を発行します。

f:id:uchimanajet7:20200928113405p:plain

想定しているユースケースは、メールに添付できないサイズのファイルの受け渡しや、ローカル環境からEC2インスタンスへのファイル持ち込みなどです。

実際に、EC2インスタンスにファイルを持ち込む場合は、対象のファイルをS3に一度アップロードして、EC2インスタンスでS3からファイルを取得する方法を取ることが多いのですが、対象ファイルをアップロードする手間がなくなるのは良い感じです。

署名付きURLの期限は指定可能となっていますが、今回はLambdaの実行にIAMロールを利用しているので、最大値はこの制限に依存します。

uchimanajet7.hatenablog.com

また、ファイルの添付は複数可能ですが署名付きURLについては1ファイル1URLとなります。これはS3の署名付きURLがオブジェクトに対して発行されているためです。 複数ファイルで1URLとしたい場合は、ファイル自体を圧縮するなど工夫をお願いします。

short コマンドについて

f:id:uchimanajet7:20200928113447p:plain

short コマンドは、短縮URLを発行することができます。

想定しているユースケースは、前述の link コマンドで発行した署名付きURLを短縮URLで短いURLに変換することになります。

実際に、署名付きURLはかなりの長さがあり、コピーミスで表示できない問題が起こったりしてました。短いURLにすることにより、単純なミスが減るのは良いか感じです。

署名付きURLに有効期限はあるのですが、短縮URLでも有効期限を指定することができます。

この短縮URLを発行する仕組みについては、以下のワークショップを参考にしています。 AWS CDKのワークショップとなるためCDK側のコードも非常に参考になります。

youtu.be

github.com

cdkworkshop.com

作成中に悩んだ部分

セキュリテイについて

Lambdaレイヤーの利用

Slackからのリクエスト処理

  • Slackからイベント内容が投げ込まれるが、3秒以内に応答しないと再送される
  • 対応するためには、Slackからイベントを受け取ったらすぐに応答するか、1度投げ込まれたイベントには反応しないようにする
  • API Gateway + Lambdaが同期処理されているため、今回は後者を採用した

Lambdaの非同期呼び出し

Slack APIについて

  • Slackに参加しているメンバーを取得しようとすると、先に見つかるのがワークスペースに参加する全員を対象としたAPI
  • このAPIだとSlack利用者が多い場合には時間がかかることが想定される
  • 調べてみると会話の単位(チャンネル・DMなど)に参加しているメンバーが取得できるAPIがあった
  • しかし、上記のAPIで取得できるのはユーザーIDだけ
  • 加えてbotやワークフロー実行ユーザーが一覧に入っている模様
  • ユーザー情報の詳細が取得できるので、その情報で人なのかを判別できる
  • 今回はユーザーIDだけ必要だったので、一覧取得の時にbotユーザーをフィルタできる機能が欲しかった

テストコードについて

  • LambdaとAWS CDKのテストコードをどうするか
  • Lambdaの方はgoogle先生に聞いてみるといろいろ出てくるしMockでの対応でもなんとかできる
  • CDKの部分はどうするばいいのか悩む
  • と思ってたら、ちゃんと公式ドキュメントに記載があった
  • 現状はどちらもテストコードがない状態なので対応が必要

利用する場合に注意する部分

今回は所属するチーム内での利用を想定し、チームで管理されてAWSアカウントに対してデプロイを行っています。そのため仕様上で考慮する部分などは共有できている前提で利用を想定しています。

もし、ご自身の環境で利用していただける場合には以下の部分に注意をお願いします。

AWS Lambdaの仕様に依存

docs.aws.amazon.com

メモリ容量に依存

実行時間に依存

  • Lambdaの現時点での最大実行時間は15分
  • 現在の実行時間設定も15分
  • Slackチャンネルの参加メンバーが多数の場合は実行時間をオーバーする可能性がある
  • 添付ファイルが極端に大きい場合は実行時間をオーバーする可能性がある
  • 実行時間はこれ以上延長はできないので、内部の仕組みを改善して対応する必要がある

Amazon DynamoDBの仕様に依存

docs.aws.amazon.com

キャパシティユニットに依存

TTLの仕様に依存

その他

構築について

  • AWSリソースはAWS CDKで構築される
  • 事前にRoute 53ドメインと利用するゾーンは作成する必要がある
  • CDKで構築を実行する際にはゾーン名とゾーンIDを環境変数に設定する必要がある

削除について

  • AWSリソースはAWS CDKで削除される
  • 事前に作成したRoute 53ドメインのゾーンは削除されない
  • CloudWatch Logsに出力されたログは削除されない
  • S3はbucketが空でないと削除できないため、削除を行わない
  • その他の関連リソースは自動削除される
  • データを保持する必要がある場合には、事前にバックアップを取得するころ
  • 完全に削除するには。上記の削除されないリソースを手動で削除する必要がある

まとめ

  • AWS Cloud Development Kit (AWS CDK) を使ってみたかった
  • せっかくだから普段使っているSlackのbotを作った
  • 作ったbotは普段使えて、ちょっと便利になる感じを目標にした
  • ランダム選択はそこそこ出番がある感じ
  • CDKはとても便利で楽しい
  • CDKの実装例はTypeScriptが多い気がする
  • 個人的にはPythonで書きたいのでもう少し実装例を増やして欲しい
  • CDKで書いたコードをどうテストするか悩んだ
  • CDKを利用することで、今回のようなSlack bot開発もほとんどマネジメントコンソールにアクセスせずに進められて捗る
  • 今後も機会があれば積極的にCDKは使っていきたいと思った
  • やっぱり手を動かしているのは楽しいです

以上になります。


Following is in English

medium.com