Given the file for testing
shell> cat commands.yml
commands:
- group: vm1
commands:
- echo command 1
- echo command 2
- group: vm2
commands:
- echo command 3
- echo command 4
Q: "On vm1 run command 1 and command 2. On vm2 run command 3 and command 4."
Short answer: Convert the list to a dictionary and select the list of commands in the loop
- command: "{{ item }}"
loop: "{{ commands_dict[inventory_hostname] }}"
vars:
commands_dict: "{{ commands|
items2dict(key_name='group',
value_name='commands') }}"
A: There are more options:
- Select the host and map the list(s) of commands
- command: "{{ item }}"
loop: "{{ commands|
selectattr('group', 'eq', inventory_hostname)|
map(attribute='commands')|flatten }}"
- Instead of attribute mapping, filter subelements
- command: "{{ item.1 }}"
loop: "{{ commands|
selectattr('group', 'eq', inventory_hostname)|
subelements('commands') }}"
- Convert the lists of commands to a dictionary
commands_dict: "{{ commands|
items2dict(key_name='group',
value_name='commands') }}"
gives
commands_dict:
vm1:
- echo command 1
- echo command 2
vm2:
- echo command 3
- echo command 4
Use the dictionary in the loop
- command: "{{ item }}"
loop: "{{ commands_dict[inventory_hostname] }}"
Details:
- Select the host and map the list(s) of commands
shell> cat pb.yml
- hosts: all
vars_files:
- commands.yml
tasks:
- command: "{{ item }}"
register: out
loop: "{{ commands|
selectattr('group', 'eq', inventory_hostname)|
map(attribute='commands')|flatten }}"
- debug:
msg: "{{ out.results|map(attribute='stdout') }}"
gives
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [command] ********************************************************************************
changed: [vm1] => (item=echo command 1)
changed: [vm2] => (item=echo command 3)
changed: [vm2] => (item=echo command 4)
changed: [vm1] => (item=echo command 2)
TASK [debug] **********************************************************************************
ok: [vm2] =>
msg:
- command 3
- command 4
ok: [vm1] =>
msg:
- command 1
- command 2
PLAY RECAP ************************************************************************************
vm1: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
vm2: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- Iterate commands with subelements
shell> cat pb.yml
- hosts: all
vars_files:
- commands.yml
tasks:
- command: "{{ item.1 }}"
register: out
loop: "{{ commands|
selectattr('group', 'eq', inventory_hostname)|
subelements('commands') }}"
loop_control:
label: "{{ item.1 }}"
- debug:
msg: "{{ out.results|map(attribute='stdout') }}"
gives
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [command] ********************************************************************************
changed: [vm2] => (item=echo command 3)
changed: [vm1] => (item=echo command 1)
changed: [vm1] => (item=echo command 2)
changed: [vm2] => (item=echo command 4)
TASK [debug] **********************************************************************************
ok: [vm1] =>
msg:
- command 1
- command 2
ok: [vm2] =>
msg:
- command 3
- command 4
PLAY RECAP ************************************************************************************
vm1: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
vm2: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- Create a dictionary with the lists of the commands
shell> cat pb.yml
- hosts: all
vars_files:
- commands.yml
vars:
commands_dict: "{{ commands|
items2dict(key_name='group',
value_name='commands') }}"
tasks:
- debug:
var: commands_dict
run_once: true
- command: "{{ item }}"
register: out
loop: "{{ commands_dict[inventory_hostname] }}"
- debug:
msg: "{{ out.results|map(attribute='stdout') }}"
gives
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [debug] **********************************************************************************
ok: [vm1] =>
commands_dict:
vm1:
- echo command 1
- echo command 2
vm2:
- echo command 3
- echo command 4
TASK [command] ********************************************************************************
changed: [vm2] => (item=echo command 3)
changed: [vm1] => (item=echo command 1)
changed: [vm1] => (item=echo command 2)
changed: [vm2] => (item=echo command 4)
TASK [debug] **********************************************************************************
ok: [vm1] =>
msg:
- command 1
- command 2
ok: [vm2] =>
msg:
- command 3
- command 4
PLAY RECAP ************************************************************************************
vm1: ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
vm2: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0