# How to execute a loop of actions on differents hosts?

**URL:** <https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522>\
**Category:** Get Help\
**Tags:** loop, playbook\
**Created:** [March 22, 2024, 8:05pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522 "2024-03-22T20:05:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![romainquere](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@romainquere](https://forum.ansible.com/u/romainquere)\
**Post date:** [March 22, 2024, 8:05pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/1 "2024-03-22T20:05:16Z")

</div>

I would like to loop on a set of tasks which are executed on different hosts.  
For example:

- action 1 on host A
- action 2 on host B
- action 3 on host C  
repeated for each element of my variable _TestName_

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 24, 2024, 8:03pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/2 "2024-03-24T20:03:40Z")

</div>

Please, tell us more about `TestName`. Is it:

- a list of lists,
- a list of dicts,
- a list of actions you want to execute on a fixed set of hosts A, B, and C,
- a list of hosts you want to execute a fixed set of actions 1, 2, and 3, on…

It can be difficult to see how many ways other people might interpret a statement made when you’re thinking of a particular scenario. In this case there are too many nuances left out, and `community.general.read_my_mind` is still not even on the roadmap.

A more complete description (or better, actual example(s)) of `TestName` would get you better responses.

---

<div class="post-metadata">

**Author:** ![romainquere](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@romainquere](https://forum.ansible.com/u/romainquere)\
**Post date:** [March 25, 2024, 7:48am UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/3 "2024-03-25T07:48:23Z")

</div>

Hi @utoddl,

_TestName_ is a list of string in my case.

Best Regards

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 25, 2024, 11:07am UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/4 "2024-03-25T11:07:58Z")

</div>

> [@romainquere](#):
>
> _TestName_ is a list of string in my case.

… and those strings are names of actions? or hosts?

---

<div class="post-metadata">

**Author:** ![romainquere](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@romainquere](https://forum.ansible.com/u/romainquere)\
**Post date:** [March 25, 2024, 5:11pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/5 "2024-03-25T17:11:50Z")

</div>

These strings are labels which are used by action1/action2/action3 as functional parameters.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 25, 2024, 6:12pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/6 "2024-03-25T18:12:08Z")

</div>

Can you _please_ show examples?  
Can you show us what you’ve tried that hasn’t worked?

It’s really hard to give specific answers to vaguely general problem descriptions, and bringing in even more general terms doesn’t add clarity. Ansible supports action plugins: somehow I don’t think that’s what you mean by “actions”. Ansible doesn’t support functional programming (except in a few accidental cases via Jinja2), and I don’t think that’s what you mean by “functional parameters” either.

Sorry to sound impatient in a public forum. We _really do want to help you_ solve your problem, but you’ve got to help us help you.

---

<div class="post-metadata">

**Author:** ![romainquere](https://avatars.discourse-cdn.com/v4/letter/r/e9bcb4/32.png) [@romainquere](https://forum.ansible.com/u/romainquere)\
**Post date:** [March 26, 2024, 5:20pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/7 "2024-03-26T17:20:59Z")

</div>

Hi @utoddl ,  
My variable is defined in group\_vars/all as below:

```auto
test_format: 
  - svsGlissando_10000
  - svsGlissando_20000
  - svsGlissando_30000
  - svsGlissando_40000

```

I currently have a central playbook wich imports another playbook multiple times with different values of `test_name`.

```auto
- import_playbook: ../common/launch_test_retrieve_logs.yml
  vars:
    var_file: "{{ var_file }}"
    test_name: "svsGlissando_10000"
  when: test_name in test_format

- import_playbook: ../common/launch_test_retrieve_logs.yml
  vars:
    var_file: "{{ var_file }}"
    test_name: "svsGlissando_20000"
  when: test_name in test_format

- import_playbook: ../common/launch_test_retrieve_logs.yml
  vars:
    var_file: "{{ var_file }}"
    test_name: "svsGlissando_30000"
  when: test_name in test_format

```

I have this same block hundrerds of time in my main playbook which I would like to avoid ☹  
Playbook `launch_test_retrieve_logs.yml` also uses import\_playbook but on different playbooks which are executed on different hosts

```auto
- import_playbook: launch_test.yml

- import_playbook: retrieve_apache_logs.yml
  when: webserver == 'apache'

- import_playbook: restart_jmeter_worker.yml

```

`launch_test.yml` has for hosts `jmeter-controller` and launch jmeter based on configuration files which use `test_name`  
`retrieve_apache_logs.yml` has for hosts `web-apache` retrieves logs files and store them in a path which use `test_name`  
`restart_jmeter_worker.yml` has for hosts `jmeter-workers`

This behavior is working fine but is not very elegant as for each new value of test\_format I add in the variable I also must create a new block in my main playbook.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 26, 2024, 9:02pm UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/8 "2024-03-26T21:02:25Z")

</div>

Now you’re talkin’! This is beautiful.

Well, as a request for help, it’s beautiful compared to your first attempt. 🙂 I wouldn’t have guessed this structure in a million years based on the initial description.

As an example of “How To Ansible”, it’s not so beautiful. The big problem — and understand, I’ve only been looking at this for a little while so I could be missing some subtleties — everything seems to be “up a level” above where it ought to be. I’m guessing that your playbooks should probably be roles, and your roles (if you have any) should probably be task files within those roles. Because what you _want_ to do is something like this:

```yaml
# N.B. This won't work!
- import_playbook: ../common/launch_test_retrieve_logs.yml
  vars:
    var_file: "{{ var_file }}"
  loop: '{{ test_format }}'
  loop_control:
    loop_var: test_name

```

But that won’t work, because you can’t loop over “PlaybookInclude” – an internal name apparently for what `import_playbook` is/does. At least, that’s in the error message. I tried it anyway.

Rather, what might accomplish your goal is more like:

```yaml
---
# tests-playbook.yml
- name: Tests playbook
  hosts: localhost
  gather_facts: false
  vars:
    test_format:
      - svsGlissando_10000
      - svsGlissando_20000
      - svsGlissando_30000
      - svsGlissando_40000
      - svsTremolo_10000
      - svsTremolo_20000
  tasks:
    - name: Include the glissando test roles
      ansible.builtin.include_role:
        name: glissando_tests
        tasks_from: main.yml
      loop: '{{ test_format }}'
      when: test_name is search("Glissando")
      loop_control:
        loop_var: test_name

    - name: Include the tremolo test roles
      ansible.builtin.include_role:
        name: tremolo_tests
        tasks_from: main.yml
      loop: '{{ test_format }}'
      when: test_name is search("Tremolo")
      loop_control:
        loop_var: test_name

```

You’ve got more going on than this example solves, but I’m pretty sure your playbooks should be roles. Restructuring everything is not going to be trivial, but I expect it will be worth it. You’re basically shifting from a code-driven flow to a data-driven flow. That’s not trivial, but it is possible with roles; with playbooks – not so much.

Feel free to follow-up with additional questions, which I’m sure will pop up as you dig into the details.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 27, 2024, 1:25am UTC](https://forum.ansible.com/t/how-to-execute-a-loop-of-actions-on-differents-hosts/4522/9 "2024-03-27T01:25:46Z")

</div>

Picking up on the “Glissando” part and totally overlooking the whole medical imaging, `.svs` thing, I naively extended your `test_format` list in a musical direction. It was only an example anyway, but I feel kind of silly. 😊
