mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add stats on rescued/ignored tasks (#48418)
* Adding rescued/ignored tasks to stats gathering Fixes #31245 * Amend integration tests to pass * callback/dense.py: fix too-many-format-args * Add changelog * Amend counter_enabled and unixy callbacks * Fix syntax error * Fix typo in the changelog * Remove not needed comment * Re-add skipped * Add test for rescued * Fix colors... * Fix unstable tests? * Add a note to the porting guide * Re-word the note in the porting guide Fixes #20346 Fixes #24525 Fixes #14393 Co-authored-by: James Cammarata <jimi@sngx.net> Co-authored-by: Martin Krizek <martin.krizek@gmail.com>
This commit is contained in:
parent
b1a9e7b8c8
commit
be9f07279e
17 changed files with 107 additions and 41 deletions
2
changelogs/fragments/improved_stats.yaml
Normal file
2
changelogs/fragments/improved_stats.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- Add stats on rescued/ignored tasks to play recap (https://github.com/ansible/ansible/pull/48418)
|
|
@ -230,6 +230,7 @@ Plugins
|
||||||
``CLIARGS.get('tags')`` and ``CLIARGS['tags']`` work as expected but you won't be able to modify
|
``CLIARGS.get('tags')`` and ``CLIARGS['tags']`` work as expected but you won't be able to modify
|
||||||
the cli arguments at all.
|
the cli arguments at all.
|
||||||
|
|
||||||
|
* Play recap now counts ``ignored`` and ``rescued`` tasks as well as ``ok``, ``changed``, ``unreachable``, ``failed`` and ``skipped`` tasks, thanks to two additional stat counters in the ``default`` callback plugin. Tasks that fail and have ``ignore_errors: yes`` set are listed as ``ignored``. Tasks that fail and then execute a rescue section are listed as ``rescued``. Note that ``rescued`` tasks are no longer counted as ``failed`` as in Ansible 2.7 (and earlier).
|
||||||
|
|
||||||
Porting custom scripts
|
Porting custom scripts
|
||||||
======================
|
======================
|
||||||
|
|
|
@ -34,6 +34,8 @@ class AggregateStats:
|
||||||
self.dark = {}
|
self.dark = {}
|
||||||
self.changed = {}
|
self.changed = {}
|
||||||
self.skipped = {}
|
self.skipped = {}
|
||||||
|
self.rescued = {}
|
||||||
|
self.ignored = {}
|
||||||
|
|
||||||
# user defined stats, which can be per host or global
|
# user defined stats, which can be per host or global
|
||||||
self.custom = {}
|
self.custom = {}
|
||||||
|
@ -63,7 +65,9 @@ class AggregateStats:
|
||||||
failures=self.failures.get(host, 0),
|
failures=self.failures.get(host, 0),
|
||||||
unreachable=self.dark.get(host, 0),
|
unreachable=self.dark.get(host, 0),
|
||||||
changed=self.changed.get(host, 0),
|
changed=self.changed.get(host, 0),
|
||||||
skipped=self.skipped.get(host, 0)
|
skipped=self.skipped.get(host, 0),
|
||||||
|
rescued=self.rescued.get(host, 0),
|
||||||
|
ignored=self.ignored.get(host, 0),
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_custom_stats(self, which, what, host=None):
|
def set_custom_stats(self, which, what, host=None):
|
||||||
|
|
|
@ -85,21 +85,25 @@ class CallbackModule(CallbackBase):
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
stat = stats.summarize(host)
|
stat = stats.summarize(host)
|
||||||
|
|
||||||
self._display.display(u"%s : %s %s %s %s" % (
|
self._display.display(u"%s : %s %s %s %s %s %s" % (
|
||||||
hostcolor(host, stat),
|
hostcolor(host, stat),
|
||||||
colorize(u'ok', stat['ok'], C.COLOR_OK),
|
colorize(u'ok', stat['ok'], C.COLOR_OK),
|
||||||
colorize(u'changed', stat['changed'], C.COLOR_CHANGED),
|
colorize(u'changed', stat['changed'], C.COLOR_CHANGED),
|
||||||
colorize(u'unreachable', stat['unreachable'], C.COLOR_UNREACHABLE),
|
colorize(u'unreachable', stat['unreachable'], C.COLOR_UNREACHABLE),
|
||||||
colorize(u'failed', stat['failures'], C.COLOR_ERROR)),
|
colorize(u'failed', stat['failures'], C.COLOR_ERROR),
|
||||||
|
colorize(u'rescued', stat['rescued'], C.COLOR_OK),
|
||||||
|
colorize(u'ignored', stat['ignored'], C.COLOR_WARN)),
|
||||||
screen_only=True
|
screen_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self._display.display(u"%s : %s %s %s %s" % (
|
self._display.display(u"%s : %s %s %s %s %s %s" % (
|
||||||
hostcolor(host, stat, False),
|
hostcolor(host, stat, False),
|
||||||
colorize(u'ok', stat['ok'], None),
|
colorize(u'ok', stat['ok'], None),
|
||||||
colorize(u'changed', stat['changed'], None),
|
colorize(u'changed', stat['changed'], None),
|
||||||
colorize(u'unreachable', stat['unreachable'], None),
|
colorize(u'unreachable', stat['unreachable'], None),
|
||||||
colorize(u'failed', stat['failures'], None)),
|
colorize(u'failed', stat['failures'], None),
|
||||||
|
colorize(u'rescued', stat['rescued'], None),
|
||||||
|
colorize(u'ignored', stat['ignored'], None)),
|
||||||
log_only=True
|
log_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -327,23 +327,31 @@ class CallbackModule(CallbackBase):
|
||||||
for h in hosts:
|
for h in hosts:
|
||||||
t = stats.summarize(h)
|
t = stats.summarize(h)
|
||||||
|
|
||||||
self._display.display(u"%s : %s %s %s %s %s" % (
|
self._display.display(
|
||||||
|
u"%s : %s %s %s %s %s %s %s" % (
|
||||||
hostcolor(h, t),
|
hostcolor(h, t),
|
||||||
colorize(u'ok', t['ok'], C.COLOR_OK),
|
colorize(u'ok', t['ok'], C.COLOR_OK),
|
||||||
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
||||||
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
||||||
colorize(u'failed', t['failures'], C.COLOR_ERROR),
|
colorize(u'failed', t['failures'], C.COLOR_ERROR),
|
||||||
colorize(u'skipped', t['skipped'], C.COLOR_SKIP)),
|
colorize(u'skipped', t['skipped'], C.COLOR_SKIP),
|
||||||
|
colorize(u'rescued', t['rescued'], C.COLOR_OK),
|
||||||
|
colorize(u'ignored', t['ignored'], C.COLOR_WARN),
|
||||||
|
),
|
||||||
screen_only=True
|
screen_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self._display.display(u"%s : %s %s %s %s %s" % (
|
self._display.display(
|
||||||
|
u"%s : %s %s %s %s %s %s %s" % (
|
||||||
hostcolor(h, t, False),
|
hostcolor(h, t, False),
|
||||||
colorize(u'ok', t['ok'], None),
|
colorize(u'ok', t['ok'], None),
|
||||||
colorize(u'changed', t['changed'], None),
|
colorize(u'changed', t['changed'], None),
|
||||||
colorize(u'unreachable', t['unreachable'], None),
|
colorize(u'unreachable', t['unreachable'], None),
|
||||||
colorize(u'failed', t['failures'], None),
|
colorize(u'failed', t['failures'], None),
|
||||||
colorize(u'skipped', t['skipped'], None)),
|
colorize(u'skipped', t['skipped'], None),
|
||||||
|
colorize(u'rescued', t['rescued'], None),
|
||||||
|
colorize(u'ignored', t['ignored'], None),
|
||||||
|
),
|
||||||
log_only=True
|
log_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -481,12 +481,16 @@ class CallbackModule_dense(CallbackModule_default):
|
||||||
hosts = sorted(stats.processed.keys())
|
hosts = sorted(stats.processed.keys())
|
||||||
for h in hosts:
|
for h in hosts:
|
||||||
t = stats.summarize(h)
|
t = stats.summarize(h)
|
||||||
self._display.display(u"%s : %s %s %s %s" % (
|
self._display.display(
|
||||||
|
u"%s : %s %s %s %s %s %s" % (
|
||||||
hostcolor(h, t),
|
hostcolor(h, t),
|
||||||
colorize(u'ok', t['ok'], C.COLOR_OK),
|
colorize(u'ok', t['ok'], C.COLOR_OK),
|
||||||
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
||||||
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
||||||
colorize(u'failed', t['failures'], C.COLOR_ERROR)),
|
colorize(u'failed', t['failures'], C.COLOR_ERROR),
|
||||||
|
colorize(u'rescued', t['rescued'], C.COLOR_OK),
|
||||||
|
colorize(u'ignored', t['ignored'], C.COLOR_WARN),
|
||||||
|
),
|
||||||
screen_only=True
|
screen_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -237,8 +237,8 @@ class CallbackModule(CallbackBase):
|
||||||
else:
|
else:
|
||||||
color = 'ok'
|
color = 'ok'
|
||||||
|
|
||||||
msg = '{0} : ok={1}\tchanged={2}\tfailed={3}\tunreachable={4}'.format(
|
msg = '{0} : ok={1}\tchanged={2}\tfailed={3}\tunreachable={4}\trescued={5}\tignored={6}'.format(
|
||||||
host, s['ok'], s['changed'], s['failures'], s['unreachable'])
|
host, s['ok'], s['changed'], s['failures'], s['unreachable'], s['rescued'], s['ignored'])
|
||||||
print(colorize(msg, color))
|
print(colorize(msg, color))
|
||||||
|
|
||||||
def v2_runner_on_skipped(self, result, **kwargs):
|
def v2_runner_on_skipped(self, result, **kwargs):
|
||||||
|
|
|
@ -207,7 +207,7 @@ class CallbackModule(CallbackBase):
|
||||||
hosts = sorted(stats.processed.keys())
|
hosts = sorted(stats.processed.keys())
|
||||||
|
|
||||||
t = prettytable.PrettyTable(['Host', 'Ok', 'Changed', 'Unreachable',
|
t = prettytable.PrettyTable(['Host', 'Ok', 'Changed', 'Unreachable',
|
||||||
'Failures'])
|
'Failures', 'Rescued', 'Ignored'])
|
||||||
|
|
||||||
failures = False
|
failures = False
|
||||||
unreachable = False
|
unreachable = False
|
||||||
|
@ -221,7 +221,7 @@ class CallbackModule(CallbackBase):
|
||||||
unreachable = True
|
unreachable = True
|
||||||
|
|
||||||
t.add_row([h] + [s[k] for k in ['ok', 'changed', 'unreachable',
|
t.add_row([h] + [s[k] for k in ['ok', 'changed', 'unreachable',
|
||||||
'failures']])
|
'failures', 'rescued', 'ignored']])
|
||||||
|
|
||||||
attachments = []
|
attachments = []
|
||||||
msg_items = [
|
msg_items = [
|
||||||
|
|
|
@ -173,21 +173,25 @@ class CallbackModule(CallbackBase):
|
||||||
# TODO how else can we display these?
|
# TODO how else can we display these?
|
||||||
t = stats.summarize(h)
|
t = stats.summarize(h)
|
||||||
|
|
||||||
self._display.display(u" %s : %s %s %s %s" % (
|
self._display.display(u" %s : %s %s %s %s %s %s" % (
|
||||||
hostcolor(h, t),
|
hostcolor(h, t),
|
||||||
colorize(u'ok', t['ok'], C.COLOR_OK),
|
colorize(u'ok', t['ok'], C.COLOR_OK),
|
||||||
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
|
||||||
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
|
||||||
colorize(u'failed', t['failures'], C.COLOR_ERROR)),
|
colorize(u'failed', t['failures'], C.COLOR_ERROR),
|
||||||
|
colorize(u'rescued', t['rescued'], C.COLOR_OK),
|
||||||
|
colorize(u'ignored', t['ignored'], C.COLOR_WARN)),
|
||||||
screen_only=True
|
screen_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self._display.display(u" %s : %s %s %s %s" % (
|
self._display.display(u" %s : %s %s %s %s %s %s" % (
|
||||||
hostcolor(h, t, False),
|
hostcolor(h, t, False),
|
||||||
colorize(u'ok', t['ok'], None),
|
colorize(u'ok', t['ok'], None),
|
||||||
colorize(u'changed', t['changed'], None),
|
colorize(u'changed', t['changed'], None),
|
||||||
colorize(u'unreachable', t['unreachable'], None),
|
colorize(u'unreachable', t['unreachable'], None),
|
||||||
colorize(u'failed', t['failures'], None)),
|
colorize(u'failed', t['failures'], None),
|
||||||
|
colorize(u'rescued', t['rescued'], None),
|
||||||
|
colorize(u'ignored', t['ignored'], None)),
|
||||||
log_only=True
|
log_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -458,9 +458,6 @@ class StrategyBase:
|
||||||
else:
|
else:
|
||||||
iterator.mark_host_failed(original_host)
|
iterator.mark_host_failed(original_host)
|
||||||
|
|
||||||
# increment the failed count for this host
|
|
||||||
self._tqm._stats.increment('failures', original_host.name)
|
|
||||||
|
|
||||||
# grab the current state and if we're iterating on the rescue portion
|
# grab the current state and if we're iterating on the rescue portion
|
||||||
# of a block then we save the failed task in a special var for use
|
# of a block then we save the failed task in a special var for use
|
||||||
# within the rescue/always
|
# within the rescue/always
|
||||||
|
@ -470,6 +467,7 @@ class StrategyBase:
|
||||||
self._tqm._failed_hosts[original_host.name] = True
|
self._tqm._failed_hosts[original_host.name] = True
|
||||||
|
|
||||||
if state and iterator.get_active_state(state).run_state == iterator.ITERATING_RESCUE:
|
if state and iterator.get_active_state(state).run_state == iterator.ITERATING_RESCUE:
|
||||||
|
self._tqm._stats.increment('rescued', original_host.name)
|
||||||
self._variable_manager.set_nonpersistent_facts(
|
self._variable_manager.set_nonpersistent_facts(
|
||||||
original_host,
|
original_host,
|
||||||
dict(
|
dict(
|
||||||
|
@ -477,8 +475,11 @@ class StrategyBase:
|
||||||
ansible_failed_result=task_result._result,
|
ansible_failed_result=task_result._result,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
self._tqm._stats.increment('failures', original_host.name)
|
||||||
else:
|
else:
|
||||||
self._tqm._stats.increment('ok', original_host.name)
|
self._tqm._stats.increment('ok', original_host.name)
|
||||||
|
self._tqm._stats.increment('ignored', original_host.name)
|
||||||
if 'changed' in task_result._result and task_result._result['changed']:
|
if 'changed' in task_result._result and task_result._result['changed']:
|
||||||
self._tqm._stats.increment('changed', original_host.name)
|
self._tqm._stats.increment('changed', original_host.name)
|
||||||
self._tqm.send_callback('v2_runner_on_failed', task_result, ignore_errors=ignore_errors)
|
self._tqm.send_callback('v2_runner_on_failed', task_result, ignore_errors=ignore_errors)
|
||||||
|
|
|
@ -22,6 +22,12 @@ changed: [testhost] => (item=foo-1)
|
||||||
changed: [testhost] => (item=foo-2)
|
changed: [testhost] => (item=foo-2)
|
||||||
changed: [testhost] => (item=foo-3)
|
changed: [testhost] => (item=foo-3)
|
||||||
|
|
||||||
|
TASK [EXPECTED FAILURE Failed task to be rescued] ******************************
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
|
||||||
|
|
||||||
|
TASK [Rescue task] *************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
RUNNING HANDLER [Test handler 1] ***********************************************
|
RUNNING HANDLER [Test handler 1] ***********************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
|
@ -40,5 +46,5 @@ TASK [Second free task] ********************************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
PLAY RECAP *********************************************************************
|
PLAY RECAP *********************************************************************
|
||||||
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=1
|
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=1 rescued=1 ignored=1
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
+ ansible-playbook -i inventory test.yml
|
+ ansible-playbook -i inventory test.yml
|
||||||
++ set +x
|
++ set +x
|
||||||
fatal: [testhost]: FAILED! => {"changed": false, "msg": "no reason"}
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "no reason"}
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
|
||||||
|
|
|
@ -21,6 +21,11 @@ changed: [testhost] => (item=foo-1)
|
||||||
changed: [testhost] => (item=foo-2)
|
changed: [testhost] => (item=foo-2)
|
||||||
changed: [testhost] => (item=foo-3)
|
changed: [testhost] => (item=foo-3)
|
||||||
|
|
||||||
|
TASK [EXPECTED FAILURE Failed task to be rescued] ******************************
|
||||||
|
|
||||||
|
TASK [Rescue task] *************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
RUNNING HANDLER [Test handler 1] ***********************************************
|
RUNNING HANDLER [Test handler 1] ***********************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
|
@ -39,5 +44,5 @@ TASK [Second free task] ********************************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
PLAY RECAP *********************************************************************
|
PLAY RECAP *********************************************************************
|
||||||
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=1
|
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=1 rescued=1 ignored=1
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,12 @@ changed: [testhost] => (item=foo-1)
|
||||||
changed: [testhost] => (item=foo-2)
|
changed: [testhost] => (item=foo-2)
|
||||||
changed: [testhost] => (item=foo-3)
|
changed: [testhost] => (item=foo-3)
|
||||||
|
|
||||||
|
TASK [EXPECTED FAILURE Failed task to be rescued] ******************************
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
|
||||||
|
|
||||||
|
TASK [Rescue task] *************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
RUNNING HANDLER [Test handler 1] ***********************************************
|
RUNNING HANDLER [Test handler 1] ***********************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
|
@ -34,5 +40,5 @@ TASK [Second free task] ********************************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
PLAY RECAP *********************************************************************
|
PLAY RECAP *********************************************************************
|
||||||
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=1
|
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=1 rescued=1 ignored=1
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,12 @@ changed: [testhost] => (item=foo-1)
|
||||||
changed: [testhost] => (item=foo-2)
|
changed: [testhost] => (item=foo-2)
|
||||||
changed: [testhost] => (item=foo-3)
|
changed: [testhost] => (item=foo-3)
|
||||||
|
|
||||||
|
TASK [EXPECTED FAILURE Failed task to be rescued] ******************************
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
|
||||||
|
|
||||||
|
TASK [Rescue task] *************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
RUNNING HANDLER [Test handler 1] ***********************************************
|
RUNNING HANDLER [Test handler 1] ***********************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
|
@ -37,5 +43,5 @@ TASK [Second free task] ********************************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
PLAY RECAP *********************************************************************
|
PLAY RECAP *********************************************************************
|
||||||
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=1
|
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=1 rescued=1 ignored=1
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,12 @@ changed: [testhost] => (item=foo-1)
|
||||||
changed: [testhost] => (item=foo-2)
|
changed: [testhost] => (item=foo-2)
|
||||||
changed: [testhost] => (item=foo-3)
|
changed: [testhost] => (item=foo-3)
|
||||||
|
|
||||||
|
TASK [EXPECTED FAILURE Failed task to be rescued] ******************************
|
||||||
|
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}
|
||||||
|
|
||||||
|
TASK [Rescue task] *************************************************************
|
||||||
|
changed: [testhost]
|
||||||
|
|
||||||
RUNNING HANDLER [Test handler 1] ***********************************************
|
RUNNING HANDLER [Test handler 1] ***********************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
|
@ -31,5 +37,5 @@ TASK [Second free task] ********************************************************
|
||||||
changed: [testhost]
|
changed: [testhost]
|
||||||
|
|
||||||
PLAY RECAP *********************************************************************
|
PLAY RECAP *********************************************************************
|
||||||
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=1
|
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=1 rescued=1 ignored=1
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,14 @@
|
||||||
- 3
|
- 3
|
||||||
loop_control:
|
loop_control:
|
||||||
label: foo-{{ item }}
|
label: foo-{{ item }}
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: EXPECTED FAILURE Failed task to be rescued
|
||||||
|
fail:
|
||||||
|
rescue:
|
||||||
|
- name: Rescue task
|
||||||
|
command: echo rescued
|
||||||
|
|
||||||
handlers:
|
handlers:
|
||||||
- name: Test handler 1
|
- name: Test handler 1
|
||||||
command: echo foo
|
command: echo foo
|
||||||
|
|
Loading…
Reference in a new issue