Flush the log of ansible to fluentd

Chef のログを Fluentd に流す I read an article called. Even though Ansible has the function for that, I have not got any more information so I tried it together.

Callback plugin

Ansible has a mechanism called plugin apart from module. For example, "{{lookup('file', '/etc/foo.txt') }}" ', '/etc/foo.txt')}}" * There is a lookup plugin to use and so on. There are other connection and vars plugins, but one of them is the callback plugin.

As the name implies, callback plugin is a plugin for registering callback which is automatically called when various events occur. As an example of the event,

  • At the start of playbook
  • At the start of task
  • When task is successful
  • When task fails
  • At the end of playbook

There are.

Example : send to fluentd plugin

Module is ansible which can be implemented in various languages, but unfortunately the plugin can only be implemented in the current state python.

So, the result of implementing the callback plugin is the following code. You can see that you can implement callback functions.

However, there are too many handlers that can be registered and only some of them are listed here. gist to because I've mentioned, there also visit. Please understand at what time it is called from the function name in the atmosphere. (There is no official document at this time, so I will not read the code)

import json
import urllib
import urllib2

url = 'http://localhost:8888/ansible'

def post(category, data):
    data['category'] = category

    invocation = data.pop('invocation', None)
    if invocation:
        data['module_name'] = invocation['module_name']
        data['module_args'] = invocation['module_args']

    values = {'json': json.dumps(data)}

    data = urllib.urlencode(values)
    req = urllib2.Request(url, data)
    urllib2.urlopen(req)

class CallbackModule(object):
    def on_any(self, *args, **kwargs):
        pass

    def runner_on_failed(self, host, res, ignore_errors=False):
        res["host"] = host
        post(host, 'FAILED', res)

    def runner_on_ok(self, host, res):
        res["host"] = host
        post('OK', res)

    def runner_on_error(self, host, msg):
        post('ERROR', {"host": host, 'error': msg})

    def runner_on_skipped(self, host, item=""):
        post('SKIPPED', {"host": host, "item": item})

This is sent to fluentd via in_http, and the results written out_file are as follows.

2014-02-16T00:18:04+09:00    ansible {"category":"Play_on_start"}
2014-02-16T00:18:05+09:00    ansible {"category":"Play_start"}
2014-02-16T00:18:10+09:00    ansible {"category":"OK","changed":true,"end":"2014-02-1515:18:10.810734","stdout":"Sat Feb 15 15:18:10 UTC 2014","cmd":["date"],"rc":0,"start":"2014-02-1515:18:10.808307","host":"docker","stderr":"","delta":"0:00:00.002427","module_name":"command","module_args":"date"}
2014-02-16T00:18:11+09:00    ansible {"verbose_always":true,"category":"OK","host":"docker","msg":"Sat Feb 15 15:18:10 UTC 2014","module_name":"debug","module_args":"msg=\"Sat Feb 15 15:18:10 UTC 2014\""}

Although it is a bit confusing, the results ("OK") of the task in the third line include start (start time), end (end time), and execution time called delta. If it is in the log, delta is pretty useful, is not it? Of course, stdout standard output is also taken.

Incidentally, the tasks executed are as follows.

tasks:
  - name: get date
    command: date
    register: date
  - name: debug
    debug: msg="{{ date.stdout }}"

Installation method

There are three ways to use the callback plugin.

1. inventory file with the same hierarchy to callback_plugins create a directory named, put the plugin file in it. 2. By default it is under / usr / share / ansible / plugins put under callback_plugin 3. Specify the directory where callback_plugin is placed in ansible.cfg

callback_plugins = /usr/share/ansible_plugins/callback_plugins

Both can be used simply by placing a python file. Conversely, please pay attention to the fact that if you place carelessly it will be executed arbitrarily.

If multiple callback plugins are in the directory, all of them will be executed.

Summary

We introduced the callback plugin which obtains the execution result of ansible and implements the plugin which sends it to fluentd as an example.

I think that it is useful not only for fluentd but also for skipping to nagios and skipping to hipchat when failing, for example.