相変わらず、忙しいのに仕事と関係ないコード書いたり、ブログ書いたりしたくなって困っているわたなべです。
弊社ではほとんどの案件でサーバーの環境設定にAnsible、デプロイにはCapistranoかAnsistrano、監視にはMackerelを使っています。
で、表題の通りなのですが、デプロイやプロビジョニングしたタイミングを残しておきたいと思いMackerelのグラフアノテーション機能を使うことにしました。
Capistranoでデプロイ時にMackerelのグラフアノテーションを追加する方法については、以下のブログでも紹介されている通り簡単に設定できます。
とことが、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 |
| #!/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 = { | |
| '&': "&", | |
| '>': ">", | |
| '<': "<", | |
| '"': "\"", | |
| "'": "\'", | |
| } | |
| 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() |
| --- | |
| - 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 |
公式のSlack通知モジュールと同じイメージで使えると思います。なかなかいい感じ。
from_time にプロビジョニング開始時刻をセットしたいんだけどうまい方法が見つからなかったので引き続き調査する。