Ansibleでプロビジョニング時にMackerelのグラフアノテーションを追加する

相変わらず、忙しいのに仕事と関係ないコード書いたり、ブログ書いたりしたくなって困っているわたなべです。

弊社ではほとんどの案件でサーバーの環境設定にAnsible、デプロイにはCapistranoかAnsistrano、監視にはMackerelを使っています。

で、表題の通りなのですが、デプロイやプロビジョニングしたタイミングを残しておきたいと思いMackerelのグラフアノテーション機能を使うことにしました。

mackerel.io

mackerel.io


Capistranoでデプロイ時にMackerelのグラフアノテーションを追加する方法については、以下のブログでも紹介されている通り簡単に設定できます。

blog.a-know.me

とことが、Ansibleでグラフアノテーションを方法を探っていたのですが良さそうなものが見つかりませんでした。仕方がないので公式のSlack通知モジュールを参考に自作してみました。

[defaults]
transport=ssh
forks=10
library=./ansible/libs
[ssh_connection]
ssh_args=-o ControlMaster=auto -o ControlPersist=30m
scp_if_ssh=True
pipelining=True
view raw ansible.cfg hosted with ❤ by GitHub
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2018, Kaz Watanabe <cyo@mac.com>
ANSIBLE_METADATA = {'status': ['stableinterface'],
'supported_by': 'community',
'version': '1.0'}
DOCUMENTATION = """
module: mackerel
short_description: Send Mackerek graph annotation
version_added: "1.6"
author: "kaz29 (@kaz_29)"
"""
BASE_URL = 'https://api.mackerelio.com/api/v0%s'
html_escape_table = {
'&': "&amp;",
'>': "&gt;",
'<': "&lt;",
'"': "\"",
"'": "\'",
}
def html_escape(text):
'''Produce entities within text.'''
return "".join(html_escape_table.get(c,c) for c in text)
def build_payload_for_mackerel(module, service, title, description, from_time, to_time, roles):
payload = {
'title': title,
'service': service,
'from': from_time,
'to': to_time,
}
if description is not None:
payload['description'] = description
if roles is not None:
payload['roles'] = roles
payload=module.jsonify(payload)
return payload
def do_post_graph_annotation_mackerel(module, apikey, payload):
request_url = BASE_URL % ('/graph-annotations')
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Api-Key': apikey,
}
response, info = fetch_url(module=module, url=request_url, headers=headers, method='POST', data=payload)
if info['status'] != 200:
module.fail_json(msg=" failed to send %s to %s: %s" % (payload, request_url, info['msg']))
def main():
module = AnsibleModule(
argument_spec = dict(
apikey = dict(type='str', required=True, no_log=True),
service = dict(type='str', required=True, default=None),
title = dict(type='str', required=True, default=None),
description = dict(type='str', required=False, default=None),
from_time = dict(type='int', required=True, default=None),
to_time = dict(type='int', required=True, default=None),
roles = dict(type='list', required=False, default=None)
)
)
apikey = module.params['apikey']
service = module.params['service']
title = module.params['title']
description = module.params['description']
from_time = module.params['from_time']
to_time = module.params['to_time']
roles = module.params['roles']
payload = build_payload_for_mackerel(module, service, title, description, from_time, to_time, roles)
do_post_graph_annotation_mackerel(module, apikey, payload)
module.exit_json(msg="OK")
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
if __name__ == '__main__':
main()
view raw mackerel.py hosted with ❤ by GitHub
---
- name: Send graph annotation to Mackerel
local_action:
module: mackerel
title: "{{ inventory_hostname }} provisioning completed!"
apikey: "APIKEY"
service: "SERVICE NAME"
from_time: "{{ lookup('pipe','date +%s') }}"
to_time: "{{ lookup('pipe','date +%s') }}"
become: no
gist.github.com

公式のSlack通知モジュールと同じイメージで使えると思います。なかなかいい感じ。

f:id:kaz_29:20180314064920p:plain

from_time にプロビジョニング開始時刻をセットしたいんだけどうまい方法が見つからなかったので引き続き調査する。