こんにちは。tacckです。
前回 に引き続き、今回も Ansible を使った記事です。
今回は少し視点を変えて、 Playbook で実行したタスクの「通知」をやってみたいと思います。
例えば Slack
や Google Hangouts Chat
といったチャットシステムへの通知ができると、「ビルドに失敗した」や「デプロイが終わった」といったステータスを簡単にチームで共有できるようになります。
今回は、 Ansible のモジュールが存在している Slack
と、モジュールを自作した Google Hangouts Chat
を例に見ていきます。
基本的な準備事項は、こちらの記事を確認お願いします。
また、 Slack
や Google Hangouts Chat
自体を利用できる状態である前提とします。
Slack
は Ansible の公式モジュールがあるので、簡単に利用できます。
https://docs.ansible.com/ansible/latest/modules/slack_module.html
設定項目は色々ありますが、 Webhook で利用するトークン (token
) と、表示したいメッセージ (msg
) さえ設定すれば利用できます。
タスクとしては、下記のような感じです。
- name: Send message to Slack
slack:
token: thetoken/generatedby/slack
msg: Message from Ansible
Slack
のアプリ作成ページからアプリを作成し、 "Incoming Webhooks" を有効にすると Webhook URL
が発行されます。
このURLの https://hooks.slack.com/services/
以降の部分が token
になります。
Slack
を利用されている方は、上記のタスクを追加して試してみてください。下記のような通知を受け取れるはずです。
さて、次は Google Hangouts Chat
です。こちらは、残念ながら公式モジュールが存在していないので、自分でローカルモジュールを作って対応してみたいと思います。
公式モジュールの Typetalk
のコードをベースに作ってみます。
https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/notification/typetalk.py
ファイルは、 library/hangouts_chat.py
という名前で作成しましょう。
( hangouts_chat
がそのままモジュール名となります。)
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
from __future__ import absolute_import, division, print_function
from ansible.module_utils.urls import fetch_url, ConnectionError
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.basic import AnsibleModule
import json
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: hangouts_chat
version_added: "2.9"
short_description: Send a message to Hangouts Chat
description:
- Send a message to Hangouts Chat using Hangouts Chat API
options:
space_id:
description:
- Path parameter parent space id
required: true
key:
description:
- Query parameter key
required: true
token:
description:
- Query parameter token
required: true
thread_key:
description:
- Query parameter threadKey
required: false
msg:
description:
- message
required: true
requirements: [ json ]
author: "Kihara, Takuya (@tacck)"
'''
EXAMPLES = '''
- hangouts_chat:
space_id: SPACE_ID
key: WEBHOOK_KEY
token: WEBHOOK_TOKEN
thread_key: THREAD_KEY
msg: install completed
'''
HANGOUTS_CHAT_ENDPOINT = 'https://chat.googleapis.com/v1/spaces'
def do_request(module, url, text, headers=None):
data = json.dumps(text)
if headers is None:
headers = dict()
headers = dict(headers, **{
'User-Agent': 'Ansible/hangouts_chat module',
})
r, info = fetch_url(module, url, data=data, headers=headers)
if info['status'] != 200:
exc = ConnectionError(info['msg'])
exc.code = info['status']
raise exc
return r
def send_message(module, space_id, key, token, thread_key, msg):
"""
send message to hangouts_chat
"""
try:
url = f'{HANGOUTS_CHAT_ENDPOINT}/{space_id}/messages?key={key}&token={token}&threadKey={thread_key}'
headers = {
'Content-Type': 'application/json; charset=UTF-8'
}
do_request(module, url, {'text': msg}, headers)
return True, ''
except ConnectionError as e:
return False, e
def main():
module = AnsibleModule(
argument_spec=dict(
space_id=dict(required=True),
key=dict(required=True),
token=dict(required=True),
thread_key=dict(),
msg=dict(required=True),
),
supports_check_mode=False
)
if not json:
module.fail_json(msg="json module is required")
space_id = module.params["space_id"]
key = module.params["key"]
token = module.params["token"]
thread_key = module.params["thread_key"]
msg = module.params["msg"]
res, error = send_message(module, space_id, key, token, thread_key, msg)
if not res:
module.fail_json(
msg='fail to send message with response code %s' % error.code)
module.exit_json(changed=True, thread_key=thread_key, msg=msg)
if __name__ == '__main__':
main()
色々とありますが、必要なのはパラメータに何が使えるかなので、そちらを紹介していきます。
パラメータ名 | 必須 | 意味 |
---|---|---|
space_id | ○ | Hangouts Chat の「チャットルーム」を表すID |
key | ○ | チャットルームで作成した 着信 Webhook の固有キー |
token | ○ | チャットルームで作成した 着信 Webhook の固有トークン |
thread_key | チャットルーム内のスレッドを表す名前 (ユーザーが自由に定義可能) | |
msg | ○ | 送信したいテキストメッセージ |
Google Hangouts Chat
のチャットルームで "Webhook を設定" から Webhook を自由に追加することができます。
追加すると、下記のような URL が発行されるので、こちらを上記のパラメータに当てはめていきます。
https://chat.googleapis.com/v1/spaces/[space_id]/messages?key=[key]&token=[token]
Google Hangouts Chat
のチャットルームにはスレッドという概念があるのですが、 thread_key
に名前を設定しておくと、通知をすべて同じスレッドにまとめてくれるようになります。
(逆に、設定しない場合には常に新しくスレッドが作られてしまうので、とても読みにくい状態になります。)
Hangouts Chat API の仕様については、 Google のドキュメントを参照してください。
https://developers.google.com/hangouts/chat/quickstart/incoming-bot-python
https://developers.google.com/hangouts/chat/reference/rest/v1/spaces.messages/create
では、こちらのモジュールを使って通知を送ってみましょう。
下記のようにタスクを追加します。
- name: Send message to Slack
hangouts_chat:
space_id: [space_id]
key: [key]
token: [token]
thread_key: SAMPLE
msg: Message from Ansible
こちらを実行すると、下記のような通知を受け取れるはずです。
このような感じで、チャットシステムへの通知モジュールは比較的簡単に作ることができます。
API連携のできるものなら同じ仕組みでデータを送れるので、色々と活用できるかもしれません。
ぜひみなさんも試してみてください。