default callback - add "show_task_path_on_failure" option (#73260)
When running in verbosity <2, display the file and line number for tasks that fail. This provides useful information without having to run at increased verbosity. * Move _print_task_path to CallbackBase class * Add integration tests * Add color parameter to _print_task_path() * Keep color output consistent for now Currently the path is display with COLOR_DEBUG formatting with verbosity >= 2. Instead of the color of the path changing based on verbosity level, just keep it at the currently behavior of COLOR_DEBUG. Having the color of the same information change based on verbosity level seems incorrect and makes visual parsing of the information more difficult. Co-authored-by: tahar.jegham <jeghamseifeddine@gmail.com>
This commit is contained in:
parent
ca448f7c35
commit
7d18ea5e93
7 changed files with 141 additions and 4 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
minor_changes:
|
||||||
|
- >-
|
||||||
|
default callback - add ``show_task_path_on_failure`` option to display file and
|
||||||
|
line number of tasks only on failed tasks when running at
|
||||||
|
normal verbosity level (https://github.com/ansible/ansible/issues/64625)
|
|
@ -259,6 +259,11 @@ class CallbackBase(AnsiblePlugin):
|
||||||
for hidme in self._hide_in_debug:
|
for hidme in self._hide_in_debug:
|
||||||
result.pop(hidme, None)
|
result.pop(hidme, None)
|
||||||
|
|
||||||
|
def _print_task_path(self, task, color=C.COLOR_DEBUG):
|
||||||
|
path = task.get_path()
|
||||||
|
if path:
|
||||||
|
self._display.display(u"task path: %s" % path, color=color)
|
||||||
|
|
||||||
def set_play_context(self, play_context):
|
def set_play_context(self, play_context):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,14 @@ class CallbackModule(CallbackBase):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if delegated_vars:
|
if delegated_vars:
|
||||||
|
if self._display.verbosity < 2 and self.get_option('show_task_path_on_failure'):
|
||||||
|
self._print_task_path(result._task)
|
||||||
self._display.display("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'],
|
self._display.display("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'],
|
||||||
self._dump_results(result._result)),
|
self._dump_results(result._result)),
|
||||||
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
|
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
|
||||||
else:
|
else:
|
||||||
|
if self._display.verbosity < 2 and self.get_option('show_task_path_on_failure'):
|
||||||
|
self._print_task_path(result._task)
|
||||||
self._display.display("fatal: [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)),
|
self._display.display("fatal: [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)),
|
||||||
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
|
color=C.COLOR_ERROR, stderr=self.display_failed_stderr)
|
||||||
|
|
||||||
|
@ -225,10 +229,9 @@ class CallbackModule(CallbackBase):
|
||||||
else:
|
else:
|
||||||
checkmsg = ""
|
checkmsg = ""
|
||||||
self._display.banner(u"%s [%s%s]%s" % (prefix, task_name, args, checkmsg))
|
self._display.banner(u"%s [%s%s]%s" % (prefix, task_name, args, checkmsg))
|
||||||
|
|
||||||
if self._display.verbosity >= 2:
|
if self._display.verbosity >= 2:
|
||||||
path = task.get_path()
|
self._print_task_path(task)
|
||||||
if path:
|
|
||||||
self._display.display(u"task path: %s" % path, color=C.COLOR_DEBUG)
|
|
||||||
|
|
||||||
self._last_task_banner = task._uuid
|
self._last_task_banner = task._uuid
|
||||||
|
|
||||||
|
|
|
@ -82,4 +82,17 @@ class ModuleDocFragment(object):
|
||||||
ini:
|
ini:
|
||||||
- key: check_mode_markers
|
- key: check_mode_markers
|
||||||
section: defaults
|
section: defaults
|
||||||
|
show_task_path_on_failure:
|
||||||
|
name: Show file path on failed tasks
|
||||||
|
description:
|
||||||
|
When a task fails, display the path to the file containing the failed task and the line number.
|
||||||
|
This information is displayed automatically for every task when running with C(-vv) or greater verbosity.
|
||||||
|
type: bool
|
||||||
|
default: no
|
||||||
|
env:
|
||||||
|
- name: ANSIBLE_SHOW_TASK_PATH_ON_FAILURE
|
||||||
|
ini:
|
||||||
|
- key: show_task_path_on_failure
|
||||||
|
section: defaults
|
||||||
|
version_added: '2.11'
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
+ ansible-playbook -i inventory test.yml
|
||||||
|
++ set +x
|
|
@ -0,0 +1,100 @@
|
||||||
|
|
||||||
|
PLAY [testhost] ****************************************************************
|
||||||
|
|
||||||
|
TASK [Changed task] ************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [Ok task] *****************************************************************
|
||||||
|
ok: [testhost]
|
||||||
|
|
||||||
|
TASK [Failed task] *************************************************************
|
||||||
|
task path: TEST_PATH/test.yml:16
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "no reason"}
|
||||||
|
...ignoring
|
||||||
|
|
||||||
|
TASK [Skipped task] ************************************************************
|
||||||
|
skipping: [testhost]
|
||||||
|
|
||||||
|
TASK [Task with var in name (foo bar)] *****************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [Loop task] ***************************************************************
|
||||||
|
changed: [testhost] => (item=foo-1)
|
||||||
|
changed: [testhost] => (item=foo-2)
|
||||||
|
changed: [testhost] => (item=foo-3)
|
||||||
|
|
||||||
|
TASK [debug loop] **************************************************************
|
||||||
|
changed: [testhost] => (item=debug-1) => {
|
||||||
|
"msg": "debug-1"
|
||||||
|
}
|
||||||
|
failed: [testhost] (item=debug-2) => {
|
||||||
|
"msg": "debug-2"
|
||||||
|
}
|
||||||
|
ok: [testhost] => (item=debug-3) => {
|
||||||
|
"msg": "debug-3"
|
||||||
|
}
|
||||||
|
skipping: [testhost] => (item=debug-4)
|
||||||
|
task path: TEST_PATH/test.yml:38
|
||||||
|
fatal: [testhost]: FAILED! => {"msg": "One or more items failed"}
|
||||||
|
...ignoring
|
||||||
|
|
||||||
|
TASK [EXPECTED FAILURE Failed task to be rescued] ******************************
|
||||||
|
task path: TEST_PATH/test.yml:54
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
|
||||||
|
|
||||||
|
TASK [Rescue task] *************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [include_tasks] ***********************************************************
|
||||||
|
included: .../test/integration/targets/callback_default/include_me.yml for testhost => (item=1)
|
||||||
|
|
||||||
|
TASK [debug] *******************************************************************
|
||||||
|
ok: [testhost] => {
|
||||||
|
"item": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK [copy] ********************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [replace] *****************************************************************
|
||||||
|
--- before: .../test_diff.txt
|
||||||
|
+++ after: .../test_diff.txt
|
||||||
|
@@ -1 +1 @@
|
||||||
|
-foo
|
||||||
|
\ No newline at end of file
|
||||||
|
+bar
|
||||||
|
\ No newline at end of file
|
||||||
|
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [replace] *****************************************************************
|
||||||
|
ok: [testhost]
|
||||||
|
|
||||||
|
RUNNING HANDLER [Test handler 1] ***********************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
RUNNING HANDLER [Test handler 2] ***********************************************
|
||||||
|
ok: [testhost]
|
||||||
|
|
||||||
|
RUNNING HANDLER [Test handler 3] ***********************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
PLAY [testhost] ****************************************************************
|
||||||
|
|
||||||
|
TASK [First free task] *********************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [Second free task] ********************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
|
TASK [Include some tasks] ******************************************************
|
||||||
|
included: .../test/integration/targets/callback_default/include_me.yml for testhost => (item=1)
|
||||||
|
|
||||||
|
TASK [debug] *******************************************************************
|
||||||
|
ok: [testhost] => {
|
||||||
|
"item": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
PLAY RECAP *********************************************************************
|
||||||
|
testhost : ok=19 changed=11 unreachable=0 failed=0 skipped=1 rescued=1 ignored=2
|
||||||
|
|
|
@ -16,7 +16,7 @@ set -eux
|
||||||
run_test() {
|
run_test() {
|
||||||
local testname=$1
|
local testname=$1
|
||||||
|
|
||||||
# outout was recorded w/o cowsay, ensure we reproduce the same
|
# output was recorded w/o cowsay, ensure we reproduce the same
|
||||||
export ANSIBLE_NOCOWS=1
|
export ANSIBLE_NOCOWS=1
|
||||||
|
|
||||||
# The shenanigans with redirection and 'tee' are to capture STDOUT and
|
# The shenanigans with redirection and 'tee' are to capture STDOUT and
|
||||||
|
@ -29,6 +29,7 @@ run_test() {
|
||||||
sed -i -e 's/included: .*\/test\/integration/included: ...\/test\/integration/g' "${OUTFILE}.${testname}.stdout"
|
sed -i -e 's/included: .*\/test\/integration/included: ...\/test\/integration/g' "${OUTFILE}.${testname}.stdout"
|
||||||
sed -i -e 's/@@ -1,1 +1,1 @@/@@ -1 +1 @@/g' "${OUTFILE}.${testname}.stdout"
|
sed -i -e 's/@@ -1,1 +1,1 @@/@@ -1 +1 @@/g' "${OUTFILE}.${testname}.stdout"
|
||||||
sed -i -e 's/: .*\/test_diff\.txt/: ...\/test_diff.txt/g' "${OUTFILE}.${testname}.stdout"
|
sed -i -e 's/: .*\/test_diff\.txt/: ...\/test_diff.txt/g' "${OUTFILE}.${testname}.stdout"
|
||||||
|
sed -i -e "s#${ANSIBLE_PLAYBOOK_DIR}#TEST_PATH#g" "${OUTFILE}.${testname}.stdout"
|
||||||
|
|
||||||
diff -u "${ORIGFILE}.${testname}.stdout" "${OUTFILE}.${testname}.stdout" || diff_failure
|
diff -u "${ORIGFILE}.${testname}.stdout" "${OUTFILE}.${testname}.stdout" || diff_failure
|
||||||
diff -u "${ORIGFILE}.${testname}.stderr" "${OUTFILE}.${testname}.stderr" || diff_failure
|
diff -u "${ORIGFILE}.${testname}.stderr" "${OUTFILE}.${testname}.stderr" || diff_failure
|
||||||
|
@ -147,6 +148,14 @@ export ANSIBLE_DISPLAY_OK_HOSTS=1
|
||||||
export ANSIBLE_DISPLAY_FAILED_STDERR=1
|
export ANSIBLE_DISPLAY_FAILED_STDERR=1
|
||||||
|
|
||||||
run_test failed_to_stderr
|
run_test failed_to_stderr
|
||||||
|
export ANSIBLE_DISPLAY_FAILED_STDERR=0
|
||||||
|
|
||||||
|
|
||||||
|
# Test displaying task path on failure
|
||||||
|
export ANSIBLE_SHOW_TASK_PATH_ON_FAILURE=1
|
||||||
|
run_test display_path_on_failure
|
||||||
|
export ANSIBLE_SHOW_TASK_PATH_ON_FAILURE=0
|
||||||
|
|
||||||
|
|
||||||
# Default settings with unreachable tasks
|
# Default settings with unreachable tasks
|
||||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=1
|
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=1
|
||||||
|
|
Loading…
Reference in a new issue