Implement async callbacks (#74953)
* add changelog and output from default callback * add test * add comments about TE task
This commit is contained in:
parent
ca6123e0ee
commit
703cb79442
6 changed files with 59 additions and 4 deletions
4
changelogs/fragments/74953-implement-async-callbacks.yml
Normal file
4
changelogs/fragments/74953-implement-async-callbacks.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
minor_changes:
|
||||
- callback API - implemented ``v2_runner_on_async_ok`` and ``v2_runner_on_async_failed`` callbacks
|
||||
(https://github.com/ansible/ansible/pull/74953).
|
||||
- default callback plugin - displays output for ``v2_runner_on_async_ok`` and ``v2_runner_on_async_failed`` callbacks.
|
|
@ -617,6 +617,20 @@ class TaskExecutor:
|
|||
if self._task.async_val > 0:
|
||||
if self._task.poll > 0 and not result.get('skipped') and not result.get('failed'):
|
||||
result = self._poll_async_result(result=result, templar=templar, task_vars=vars_copy)
|
||||
if result.get('failed'):
|
||||
self._final_q.send_callback(
|
||||
'v2_runner_on_async_failed',
|
||||
TaskResult(self._host.name,
|
||||
self._task, # We send the full task here, because the controller knows nothing about it, the TE created it
|
||||
result,
|
||||
task_fields=self._task.dump_attrs()))
|
||||
else:
|
||||
self._final_q.send_callback(
|
||||
'v2_runner_on_async_ok',
|
||||
TaskResult(self._host.name,
|
||||
self._task, # We send the full task here, because the controller knows nothing about it, the TE created it
|
||||
result,
|
||||
task_fields=self._task.dump_attrs()))
|
||||
|
||||
# ensure no log is preserved
|
||||
result["_ansible_no_log"] = self._play_context.no_log
|
||||
|
@ -831,7 +845,7 @@ class TaskExecutor:
|
|||
|
||||
if int(async_result.get('finished', 0)) != 1:
|
||||
if async_result.get('_ansible_parsed'):
|
||||
return dict(failed=True, msg="async task did not complete within the requested time - %ss" % self._task.async_val)
|
||||
return dict(failed=True, msg="async task did not complete within the requested time - %ss" % self._task.async_val, async_result=async_result)
|
||||
else:
|
||||
return dict(failed=True, msg="async task produced unparseable results", async_result=async_result)
|
||||
else:
|
||||
|
|
|
@ -364,7 +364,6 @@ class CallbackBase(AnsiblePlugin):
|
|||
host = result._host.get_name()
|
||||
self.runner_on_unreachable(host, result._result)
|
||||
|
||||
# FIXME: not called
|
||||
def v2_runner_on_async_poll(self, result):
|
||||
host = result._host.get_name()
|
||||
jid = result._result.get('ansible_job_id')
|
||||
|
@ -372,16 +371,18 @@ class CallbackBase(AnsiblePlugin):
|
|||
clock = 0
|
||||
self.runner_on_async_poll(host, result._result, jid, clock)
|
||||
|
||||
# FIXME: not called
|
||||
def v2_runner_on_async_ok(self, result):
|
||||
host = result._host.get_name()
|
||||
jid = result._result.get('ansible_job_id')
|
||||
self.runner_on_async_ok(host, result._result, jid)
|
||||
|
||||
# FIXME: not called
|
||||
def v2_runner_on_async_failed(self, result):
|
||||
host = result._host.get_name()
|
||||
# Attempt to get the async job ID. If the job does not finish before the
|
||||
# async timeout value, the ID may be within the unparsed 'async_result' dict.
|
||||
jid = result._result.get('ansible_job_id')
|
||||
if not jid and 'async_result' in result._result:
|
||||
jid = result._result['async_result'].get('ansible_job_id')
|
||||
self.runner_on_async_failed(host, result._result, jid)
|
||||
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
|
|
|
@ -413,6 +413,21 @@ class CallbackModule(CallbackBase):
|
|||
color=C.COLOR_DEBUG
|
||||
)
|
||||
|
||||
def v2_runner_on_async_ok(self, result):
|
||||
host = result._host.get_name()
|
||||
jid = result._result.get('ansible_job_id')
|
||||
self._display.display("ASYNC OK on %s: jid=%s" % (host, jid), color=C.COLOR_DEBUG)
|
||||
|
||||
def v2_runner_on_async_failed(self, result):
|
||||
host = result._host.get_name()
|
||||
|
||||
# Attempt to get the async job ID. If the job does not finish before the
|
||||
# async timeout value, the ID may be within the unparsed 'async_result' dict.
|
||||
jid = result._result.get('ansible_job_id')
|
||||
if not jid and 'async_result' in result._result:
|
||||
jid = result._result['async_result'].get('ansible_job_id')
|
||||
self._display.display("ASYNC FAILED on %s: jid=%s" % (host, jid), color=C.COLOR_DEBUG)
|
||||
|
||||
def v2_playbook_on_notify(self, handler, host):
|
||||
if self._display.verbosity > 1:
|
||||
self._display.display("NOTIFIED HANDLER %s for %s" % (handler.get_name(), host), color=C.COLOR_VERBOSE, screen_only=True)
|
||||
|
|
|
@ -125,6 +125,13 @@ export ANSIBLE_CHECK_MODE_MARKERS=0
|
|||
|
||||
run_test default
|
||||
|
||||
# Check for async output
|
||||
# NOTE: regex to match 1 or more digits works for both BSD and GNU grep
|
||||
ansible-playbook -i inventory test_async.yml 2>&1 | tee async_test.out
|
||||
grep "ASYNC OK .* jid=[0-9]\{1,\}" async_test.out
|
||||
grep "ASYNC FAILED .* jid=[0-9]\{1,\}" async_test.out
|
||||
rm -f async_test.out
|
||||
|
||||
# Hide skipped
|
||||
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=0
|
||||
|
||||
|
|
14
test/integration/targets/callback_default/test_async.yml
Normal file
14
test/integration/targets/callback_default/test_async.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
- hosts: testhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: test success async output
|
||||
command: sleep 1
|
||||
async: 10
|
||||
poll: 1
|
||||
|
||||
- name: test failure async output
|
||||
command: sleep 10
|
||||
async: 1
|
||||
poll: 1
|
||||
ignore_errors: yes
|
Loading…
Reference in a new issue