From 72780240fe1484b1abac60dbbec7a21bdf8ee58d Mon Sep 17 00:00:00 2001
From: Tim Bielawa <tbielawa@redhat.com>
Date: Fri, 17 Mar 2017 13:06:03 -0700
Subject: Import the default ansible output callback on_failed methods

---
 callback_plugins/openshift_quick_installer.py | 57 +++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/callback_plugins/openshift_quick_installer.py b/callback_plugins/openshift_quick_installer.py
index b4c7edd38..bf55dc857 100644
--- a/callback_plugins/openshift_quick_installer.py
+++ b/callback_plugins/openshift_quick_installer.py
@@ -236,6 +236,63 @@ The only thing we change here is adding `log_only=True` to the
         """
         self._display.display("skipping: no hosts matched", color=C.COLOR_SKIP, log_only=True)
 
+
+
+    ######################################################################
+    # So we can bubble up errors to the top
+    def v2_runner_on_failed(self, result, ignore_errors=False):
+        """I guess this is when an entire task has failed?"""
+
+        if self._play.strategy == 'free' and self._last_task_banner != result._task._uuid:
+            self._print_task_banner(result._task)
+
+        delegated_vars = result._result.get('_ansible_delegated_vars', None)
+        if 'exception' in result._result:
+            if self._display.verbosity < 3:
+                # extract just the actual error message from the exception text
+                error = result._result['exception'].strip().split('\n')[-1]
+                msg = "An exception occurred during task execution. To see the full traceback, use -vvv. The error was: %s" % error
+            else:
+                msg = "An exception occurred during task execution. The full traceback is:\n" + result._result['exception']
+
+            self._display.display(msg, color=C.COLOR_ERROR)
+
+        if result._task.loop and 'results' in result._result:
+            self._process_items(result)
+
+        else:
+            if delegated_vars:
+                self._display.display("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'], self._dump_results(result._result)), color=C.COLOR_ERROR)
+            else:
+                self._display.display("fatal: [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)), color=C.COLOR_ERROR)
+
+        if ignore_errors:
+            self._display.display("...ignoring", color=C.COLOR_SKIP)
+
+    def v2_runner_item_on_failed(self, result):
+        """When an item in a task fails."""
+        delegated_vars = result._result.get('_ansible_delegated_vars', None)
+        if 'exception' in result._result:
+            if self._display.verbosity < 3:
+                # extract just the actual error message from the exception text
+                error = result._result['exception'].strip().split('\n')[-1]
+                msg = "An exception occurred during task execution. To see the full traceback, use -vvv. The error was: %s" % error
+            else:
+                msg = "An exception occurred during task execution. The full traceback is:\n" + result._result['exception']
+
+            self._display.display(msg, color=C.COLOR_ERROR)
+
+        msg = "failed: "
+        if delegated_vars:
+            msg += "[%s -> %s]" % (result._host.get_name(), delegated_vars['ansible_host'])
+        else:
+            msg += "[%s]" % (result._host.get_name())
+
+        self._display.display(msg + " (item=%s) => %s" % (self._get_item(result._result), self._dump_results(result._result)), color=C.COLOR_ERROR)
+        self._handle_warnings(result._result)
+
+
+    ######################################################################
     def v2_playbook_on_stats(self, stats):
         """Print the final playbook run stats"""
         self._display.display("", screen_only=True)
-- 
cgit v1.2.3


From 7fe79bdc2f322996132aab7db1ba04a6ce4c4ea5 Mon Sep 17 00:00:00 2001
From: Tim Bielawa <tbielawa@redhat.com>
Date: Mon, 20 Mar 2017 08:52:43 -0700
Subject: Update the failure methods and add required variables/functions

---
 callback_plugins/openshift_quick_installer.py | 32 ++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/callback_plugins/openshift_quick_installer.py b/callback_plugins/openshift_quick_installer.py
index bf55dc857..c0fdbc650 100644
--- a/callback_plugins/openshift_quick_installer.py
+++ b/callback_plugins/openshift_quick_installer.py
@@ -54,6 +54,12 @@ class CallbackModule(CallbackBase):
     plays_count = 0
     plays_total_ran = 0
 
+    def __init__(self):
+        """Constructor, ensure standard self.*s are set"""
+        self._play = None
+        self._last_task_banner = None
+        super(CallbackModule, self).__init__()
+
     def banner(self, msg, color=None):
         '''Prints a header-looking line with stars taking up to 80 columns
         of width (3 columns, minimum)
@@ -68,6 +74,29 @@ class CallbackModule(CallbackBase):
         stars = "*" * star_len
         self._display.display("\n%s %s" % (msg, stars), color=color, log_only=True)
 
+    def _print_task_banner(self, task):
+        """Imported from the upstream 'default' callback"""
+        # args can be specified as no_log in several places: in the task or in
+        # the argument spec.  We can check whether the task is no_log but the
+        # argument spec can't be because that is only run on the target
+        # machine and we haven't run it thereyet at this time.
+        #
+        # So we give people a config option to affect display of the args so
+        # that they can secure this if they feel that their stdout is insecure
+        # (shoulder surfing, logging stdout straight to a file, etc).
+        args = ''
+        if not task.no_log and C.DISPLAY_ARGS_TO_STDOUT:
+            args = ', '.join('%s=%s' % a for a in task.args.items())
+            args = ' %s' % args
+
+        self.banner(u"TASK [%s%s]" % (task.get_name().strip(), args))
+        if self._display.verbosity >= 2:
+            path = task.get_path()
+            if path:
+                self._display.display(u"task path: %s" % path, color=C.COLOR_DEBUG, log_only=True)
+
+        self._last_task_banner = task._uuid
+
     def v2_playbook_on_start(self, playbook):
         """This is basically the start of it all"""
         self.plays_count = len(playbook.get_plays())
@@ -236,8 +265,6 @@ The only thing we change here is adding `log_only=True` to the
         """
         self._display.display("skipping: no hosts matched", color=C.COLOR_SKIP, log_only=True)
 
-
-
     ######################################################################
     # So we can bubble up errors to the top
     def v2_runner_on_failed(self, result, ignore_errors=False):
@@ -291,7 +318,6 @@ The only thing we change here is adding `log_only=True` to the
         self._display.display(msg + " (item=%s) => %s" % (self._get_item(result._result), self._dump_results(result._result)), color=C.COLOR_ERROR)
         self._handle_warnings(result._result)
 
-
     ######################################################################
     def v2_playbook_on_stats(self, stats):
         """Print the final playbook run stats"""
-- 
cgit v1.2.3