Ansible async_status task - error: ansible_job_id "undefined variable"
Solution 1:
You get an undefined error for your job id because:
- You use
poll: X
on your initial task, so ansible connects every X seconds to check if the task is finished - When ansible exists that task and enters your next
async_status
task, the job is done. And since you used a non-zero value topoll
the async status cache is automatically cleared. - since the cache was cleared, the job id does not exist anymore.
Your above scenario is meant to be used to avoid timeouts with your target on long running tasks, not to run tasks concurrently and have a later checkpoint on their status. For this second requirement, you need to run the async task with poll: 0
and clean-up the cache by yourself
See the documentation for more explanation on the above concepts:
- ansible async guide
- ansible
async_status
module
I made an example with your above task and fixed it to use the dedicated module apt
(note that you could add a name
option to the module with one or a list of packages and ansible would do both the cache update and install in a single step). Also, retries * delay
on the async_status task should be equal or greater than async
on the initial task if you want to make sure that you won't miss the end.
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
async: 2000
poll: 0
register: output
- name: check progress
ansible.builtin.async_status:
jid: "{{ output.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 400
delay: 5
- name: clean async job cache
ansible.builtin.async_status:
jid: "{{ output.ansible_job_id }}"
mode: cleanup
This is more useful to launch a bunch of long lasting tasks in parallel. Here is a useless yet functional example:
- name: launch some loooooong tasks
shell: "{{ item }}"
loop:
- sleep 30
- sleep 20
- sleep 35
async: 100
poll: 0
register: long_cmd
- name: wait until all commands are done
async_status:
jid: "{{ item.ansible_job_id }}"
register: async_poll_result
until: async_poll_result.finished
retries: 50
delay: 2
loop: "{{ long_cmd.results }}"
- name: clean async job cache
async_status:
jid: "{{ item.ansible_job_id }}"
mode: cleanup
loop: "{{ long_cmd.results }}"
Solution 2:
You have poll: 2
on your task, which tells Ansible to internally poll the async job every 2 seconds and return the final status in the registered variable. In order to use async_status
you should set poll: 0
so that the task does not wait for the job to finish.