Blender Fox
Blender Fox

Reputation: 5625

Running tasks concurrently in ansible (not a loop)

I have three tasks in an ansible playbook that are unique enough that I can't wrap them in a loop. For simplicity, let's assume they are creating three different VM instances in a cloud provider and that each task has a specific configuration

- name: Create VM set A
  cloud_provider.vm:
    {stuff here}

- name: Create VM set B
  cloud_provider.vm:
    {stuff here}

- name: Create VM set C
  cloud_provider.vm:
    {stuff here}

Now this works, and creates the three sets of VM, but I'd like to run them in parallel so I am not waiting as long (the VMs run through several startup processes and it takes a while)

I've looked at

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/async_status_module.html#async-status-module

and

https://docs.ansible.com/ansible/latest/user_guide/playbooks_async.html

but they seem to use loops which I can't do here because the different sets are pretty different.

How/Can I async these tasks?

Upvotes: 1

Views: 2192

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68024

Q: "They seem to use loops which I can't do here because the different sets are pretty different. How/Can I async these tasks?"

A: You can use a loop to wait for the tasks. For example

- hosts: localhost
  tasks:
    - shell: 'sleep 5 && echo VMA created'
      async: 1000
      poll: 0
      register: cmd_result_A
    - shell: 'sleep 9 && echo VMB created'
      async: 1000
      poll: 0
      register: cmd_result_B
    - shell: 'sleep 7 && echo VMC created'
      async: 1000
      poll: 0
      register: cmd_result_C

    - async_status:
        jid: '{{ item }}'
      register: result
      until: result.finished
      retries: 20
      delay: 1
      loop:
        - "{{ cmd_result_A.ansible_job_id }}"
        - "{{ cmd_result_B.ansible_job_id }}"
        - "{{ cmd_result_C.ansible_job_id }}"

    - debug:
        msg: >-
          {{ item.start.split(' ')|last }} -
          {{ item.end.split(' ')|last }} |
          stdout: {{ item.stdout }}
      loop: "{{ result.results }}"

gives (abridged)

  msg: '13:31:13.477444 - 13:31:18.483527 | stdout: VMA created'
  msg: '13:31:13.722892 - 13:31:22.728505 | stdout: VMB created'
  msg: '13:31:14.001067 - 13:31:21.008131 | stdout: VMC created'

To simplify the code you might want to try and loop the tasks too. For example

    - shell: "{{ item }}"
      async: 1000
      poll: 0
      register: cmd_result
      loop:
        - 'sleep 5 && echo VMA created'
        - 'sleep 9 && echo VMB created'
        - 'sleep 7 && echo VMC created'

    - async_status:
        jid: '{{ item }}'
      register: result
      until: result.finished
      retries: 20
      delay: 1
      loop: "{{ cmd_result.results|map(attribute='ansible_job_id')|list }}"

Upvotes: 4

Related Questions