|
@@ -0,0 +1,172 @@
|
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
|
+
|
|
|
|
+from __future__ import (absolute_import, division, print_function)
|
|
|
|
+__metaclass__ = type
|
|
|
|
+
|
|
|
|
+import sys
|
|
|
|
+from collections import OrderedDict
|
|
|
|
+
|
|
|
|
+from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
|
|
|
|
+from ansible import constants as C
|
|
|
|
+from ansible.utils.color import stringc, hostcolor, colorize
|
|
|
|
+from ansible.module_utils._text import to_bytes, to_text
|
|
|
|
+from ansible.utils.display import Display
|
|
|
|
+
|
|
|
|
+try:
|
|
|
|
+ from __main__ import display as global_display
|
|
|
|
+except ImportError:
|
|
|
|
+ global_display = Display()
|
|
|
|
+
|
|
|
|
+class CallbackModule(CallbackModule_default):
|
|
|
|
+
|
|
|
|
+ '''
|
|
|
|
+ This is the default callback interface, which simply prints messages
|
|
|
|
+ to stdout when new callback events are received.
|
|
|
|
+ '''
|
|
|
|
+
|
|
|
|
+ CALLBACK_VERSION = 2.0
|
|
|
|
+ CALLBACK_TYPE = 'stdout'
|
|
|
|
+ CALLBACK_NAME = 'condensed'
|
|
|
|
+
|
|
|
|
+ _progress = OrderedDict()
|
|
|
|
+
|
|
|
|
+ class CallbackDisplay(Display):
|
|
|
|
+
|
|
|
|
+ def banner(self, msg, color=None, cows=False, newline=True):
|
|
|
|
+ msg = msg.strip()
|
|
|
|
+ if newline:
|
|
|
|
+ msg = u"\n" + msg
|
|
|
|
+ self.display(u"%s" % (msg), color=color)
|
|
|
|
+
|
|
|
|
+ def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False):
|
|
|
|
+ if color:
|
|
|
|
+ msg = stringc(msg, color)
|
|
|
|
+ msg2 = to_bytes(msg, encoding=self._output_encoding(stderr=stderr))
|
|
|
|
+ if sys.version_info >= (3,):
|
|
|
|
+ msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace')
|
|
|
|
+ if not stderr:
|
|
|
|
+ fileobj = sys.stdout
|
|
|
|
+ else:
|
|
|
|
+ fileobj = sys.stderr
|
|
|
|
+ fileobj.write(msg2)
|
|
|
|
+ try:
|
|
|
|
+ fileobj.flush()
|
|
|
|
+ except IOError as e:
|
|
|
|
+ if e.errno != errno.EPIPE:
|
|
|
|
+ raise
|
|
|
|
+
|
|
|
|
+ def clear_line(self):
|
|
|
|
+ sys.stdout.write("\r" + " " * self.columns + "\r")
|
|
|
|
+ sys.stdout.flush()
|
|
|
|
+
|
|
|
|
+ def __init__(self):
|
|
|
|
+ self.super_ref = super(CallbackModule, self)
|
|
|
|
+ self.super_ref.__init__()
|
|
|
|
+ self._display = self.CallbackDisplay(verbosity=global_display.verbosity)
|
|
|
|
+
|
|
|
|
+ def v2_runner_on_skipped(self, result):
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+ def v2_runner_item_on_skipped(self, result):
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+ def _print_task_banner(self, task):
|
|
|
|
+
|
|
|
|
+ newline = True
|
|
|
|
+ while self._progress != {}:
|
|
|
|
+ last = self._progress.keys()[-1]
|
|
|
|
+ if self._progress[last] == None:
|
|
|
|
+ del self._progress[last]
|
|
|
|
+ self._display.clear_line()
|
|
|
|
+ newline = False
|
|
|
|
+ else:
|
|
|
|
+ break
|
|
|
|
+
|
|
|
|
+ self._progress[task._uuid] = None
|
|
|
|
+ args = ''
|
|
|
|
+ if not task.no_log and C.DISPLAY_ARGS_TO_STDOUT:
|
|
|
|
+ args = u', '.join(u'%s=%s' % a for a in task.args.items())
|
|
|
|
+ args = u' %s' % args
|
|
|
|
+
|
|
|
|
+ self._display.banner(u"TASK [%s%s]" % (task.get_name().strip(), args), newline=newline)
|
|
|
|
+ if self._display.verbosity >= 2:
|
|
|
|
+ path = task.get_path()
|
|
|
|
+ if path:
|
|
|
|
+ self._display.display(u"task path: %s" % path, color=C.COLOR_DEBUG)
|
|
|
|
+
|
|
|
|
+ self._last_task_banner = task._uuid
|
|
|
|
+
|
|
|
|
+ def v2_runner_on_ok(self, result):
|
|
|
|
+ self._progress[result._task._uuid] = True
|
|
|
|
+
|
|
|
|
+ if self._play.strategy == 'free' and self._last_task_banner != result._task._uuid:
|
|
|
|
+ self._print_task_banner(result._task)
|
|
|
|
+
|
|
|
|
+ self._clean_results(result._result, result._task.action)
|
|
|
|
+ delegated_vars = result._result.get('_ansible_delegated_vars', None)
|
|
|
|
+ self._clean_results(result._result, result._task.action)
|
|
|
|
+
|
|
|
|
+ msg = u'\n %s' % (result._host.get_name())
|
|
|
|
+ if result._task.action in ('include', 'include_role'):
|
|
|
|
+ return
|
|
|
|
+ elif result._result.get('changed', False):
|
|
|
|
+ color = C.COLOR_CHANGED
|
|
|
|
+ else:
|
|
|
|
+ color = C.COLOR_OK
|
|
|
|
+
|
|
|
|
+ self._handle_warnings(result._result)
|
|
|
|
+
|
|
|
|
+ if result._task.loop and 'results' in result._result:
|
|
|
|
+ self._process_items(result)
|
|
|
|
+ else:
|
|
|
|
+ if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
|
|
|
+ msg += " => %s" % (self._dump_results(result._result),)
|
|
|
|
+ self._display.display(msg, color=color)
|
|
|
|
+
|
|
|
|
+ def v2_runner_item_on_ok(self, result):
|
|
|
|
+ delegated_vars = result._result.get('_ansible_delegated_vars', None)
|
|
|
|
+ msg = "\n "
|
|
|
|
+ if result._task.action in ('include', 'include_role'):
|
|
|
|
+ return
|
|
|
|
+ elif result._result.get('changed', False):
|
|
|
|
+ color = C.COLOR_CHANGED
|
|
|
|
+ else:
|
|
|
|
+ color = C.COLOR_OK
|
|
|
|
+
|
|
|
|
+ if delegated_vars:
|
|
|
|
+ msg += "[%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
|
|
|
|
+ else:
|
|
|
|
+ msg += "%s" % result._host.get_name()
|
|
|
|
+
|
|
|
|
+ msg += " => (item=%s)" % (self._get_item(result._result),)
|
|
|
|
+
|
|
|
|
+ if (self._display.verbosity > 0 or '_ansible_verbose_always' in result._result) and not '_ansible_verbose_override' in result._result:
|
|
|
|
+ msg += " => %s" % self._dump_results(result._result)
|
|
|
|
+ self._display.display(msg, color=color)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def v2_on_file_diff(self, result):
|
|
|
|
+ if result._task.loop and 'results' in result._result:
|
|
|
|
+ for res in result._result['results']:
|
|
|
|
+ if 'diff' in res and res['diff'] and res.get('changed', False):
|
|
|
|
+ diff = self._get_diff(res['diff'])
|
|
|
|
+ if diff:
|
|
|
|
+ self._display.display(u"\n" + diff.strip())
|
|
|
|
+ elif 'diff' in result._result and result._result['diff'] and result._result.get('changed', False):
|
|
|
|
+ diff = self._get_diff(result._result['diff'])
|
|
|
|
+ if diff:
|
|
|
|
+ self._display.display(u"\n" + diff.strip())
|
|
|
|
+
|
|
|
|
+ def v2_playbook_on_stats(self, stats):
|
|
|
|
+ self._display.display("\nPLAY RECAP\n")
|
|
|
|
+ hosts = sorted(stats.processed.keys())
|
|
|
|
+ for h in hosts:
|
|
|
|
+ t = stats.summarize(h)
|
|
|
|
+ self._display.display(u"%s : %s %s %s %s\n" % (
|
|
|
|
+ hostcolor(h, t),
|
|
|
|
+ colorize(u'ok', t['ok'], C.COLOR_OK),
|
|
|
|
+ colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
|
|
|
+ colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
|
|
|
+ colorize(u'failed', t['failures'], C.COLOR_ERROR)),
|
|
|
|
+ screen_only=True
|
|
|
|
+ )
|