Recently I was building a few environments in Azure using Ansible, and found this stanza which helped me to speed things up.
- name: "Schedule UDR Creation"
azure_rm_routetable:
resource_group: "{{ resource_group }}"
name: "{{ item.key }}_udr"
loop: "{{ routetables | dict2items }}"
loop_control:
label: "{{ item.key }}_udr"
async: 1000
poll: 0
changed_when: False
register: sleeper
- name: "Check UDRs Created"
async_status:
jid: "{{ item.ansible_job_id }}"
register: sleeper_status
until: sleeper_status.finished
retries: 500
delay: 4
loop: "{{ sleeper.results|flatten(levels=1) }}"
when: item.ansible_job_id is defined
loop_control:
label: "{{ item._ansible_item_label }}"
What we do here is to start an action with an “async” time (to give the Schedule an opportunity to register itself) and a “poll” time of 0 (to prevent the Schedule from waiting to be finished). We then tell it that it’s “never changed” (changed_when: False
) because otherwise it always shows as changed, and to register the scheduled item itself as a “sleeper”.
After all the async jobs get queued, we then check the status of all the scheduled items with the async_status
module, passing it the registered job ID. This lets me spin up a lot more items in parallel, and then “just” confirm afterwards that they’ve been run properly.
It’s not perfect, and it can make for rather messy code. But, it does work, and it’s well worth giving it the once over, particularly if you’ve got some slow-to-run tasks in your playbook!
Featured image is “funfair action” by “Jon Bunting” on Flickr and is released under a CC-BY license.