やったこと
きっかけ
以前からこの手の話はチーム内でチョイチョイしてたんですけど、仲間が何やら面白そうな事を
しようとしてたので、俺も俺も!
と言うのがきっかけです。
- Stackdriverはslack通知機能がある
- slack botで遊んだ事があった
- ansibleを実務で使っていた
⇒この思考プロセスでシンプルで簡単に自動起動できそうじゃね
と脳汁が出たのがきっかけです。
因みに、仲間の記事はこちらです。
https://qiita.com/HirokiSakonju/items/7f0084ad9a7df777de95
stackdriverの設定やansibleの環境設定等は↑の記事にお任せするとして
slackbotを中心に書いていこうと思います。
bot起動
<環境>
python3.6
slackbot pip3 install slackbot
基本的な設定は割愛します。以下の記事が分かりやすいです。
PythonのslackbotライブラリでSlackボットを作る
以前に参考にさせて頂きました
bot召喚
my_mention.py
# coding: utf-8
from slackbot.bot import respond_to
from slackbot.bot import listen_to
from slackbot.bot import default_reply
@default_reply()
def default_func(message):
message.reply("もあぁぁぁい")
と…とりあえず成功(ウチのワンコとモアイが……シュ・・シュール…)
Stack driverからの通知
GCPのGCEのプロセス(nginx)を監視してて、downするとslackdriverに以下の様に通知が来ます。
どうやって拾えるか
ここがちょいとハマりました…普通のテキストなら難なく拾えるのですが、リッチなattachmentsの中身を拾う必要があります。
my_mention.py
@listen_to(r'[\s\S]*')
def listen_func(message):
msg = message.body
print(msg)
if 'attachments' in msg:
if "web001_nginx" in msg["attachments"][0]["fallback"]:
if "Process count for xxxxx-xxxxx-xxxxx web001 is below the threshold of 1 with a value of 0." in msg["attachments"][0]["text"]:
message.send("落ちたもあぁぁぃ、ansible起動もぁぁぃ!")
elif "Process count for xxxxx-xxxxx-xxxxx web001 has returned to normal with a value of 1.000." in msg["attachments"][0]["text"]:
message.send("起動したもぁぁぃ")
else:
print("for add host")
else:
print("no attachment")
3,4行目でbody全体を取得して表示するとこんな感じでした。(down時)
{'text': 'Incident <https://app.google.stackdriver.com/incidents/0.xxxxxxxxxxxxxproject=xxxxx-xxxxx-xxxxx|#0.xxxxxxxx> started', 'username': 'Google Cloud Monitoring', 'icons': {'image_48': 'https://s3-us-west-2.amazonaws.com/slack-files2/bot_icons/2017-01-21/130004243825_48.png'}, 'bot_id': 'XXXXXXXX', 'attachments': [{'fallback': 'web001_nginx', 'text': 'Process count for xxxxx-xxxxx-xxxxx web001 is below the threshold of 1 with a value of 0.', 'pretext': 'Process Health on Instance (GCE) web001_nginx', 'title': 'web001_nginx', 'id': 1, 'title_link': 'https://app.google.stackdriver.com/policy-advanced/xxxxxxxxxxxxxxxxxxxxproject=xxxxx-xxxxx-xxxxxx', 'color': 'a30200'}], 'type': 'message', 'subtype': 'bot_message', 'team': 'XXXXXXXX', 'channel': 'XXXXXXXXX', 'event_ts': 'XXXXXXXXXXXXX', 'ts': 'XXXXXXXXXXXXX'}
up時
{'text': 'Incident <https://app.google.stackdriver.com/incidents/xxxxxxxxxproject=xxxxxx-xxxxxx-xxxxx|#0.xxxxxxx> stopped', 'username': 'Google Cloud Monitoring', 'icons': {'image_48': 'https://s3-us-west-2.amazonaws.com/slack-files2/bot_icons/2017-01-21/130004243825_48.png'}, 'bot_id': 'XXXXXXXX', 'attachments': [{'fallback': 'web001_nginx', 'text': 'Process count for xxxxx-xxxxxx-xxxxxx web001 has returned to normal with a value of 1.000.', 'pretext': 'Process Health on Instance (GCE) web001_nginx', 'title': 'web001_nginx', 'id': 1, 'title_link': 'https://app.google.stackdriver.com/policy-advanced/xxxxxxxxxxxxxxxxxxxxxxxxxproject=xxxxx-xxxxxx-xxxxxx', 'color': '2eb886'}], 'type': 'message', 'subtype': 'bot_message', 'team': 'XXXXXXXX', 'channel': 'XXXXXXXXX', 'event_ts': 'xxxxxxxxxxxx', 'ts': 'xxxxxxxxxxxxxxxxx'}
取得出来るのが分かれば後はご自由に。
後は適当にコマンドを叩ける様にして完成です。
def cmd(path, command):
os.chdir(path)
result = subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = result.communicate()
return (stdout, stderr)
起動もあい
ansible起動もぁぁぃ!してくれました。