I have an Inventory file with this format.
group_host:
hosts:
d1:
ansible_host: address-server
d2:
ansible_host: address-server
d3:
ansible_host: address-server
The server address is the same for all host variables (d1, d2, d3). When I run the playbook, the task will be executed on each variable in this case three times on the same server. How can we make it a condition that the task is only executed once if the addresses-servers in the host group are the same? And how can I make the task run once for every unique server address?
Create a new inventory group in the first play and use it in the second.
For example, get a list of variables ansible_host
ansible_hosts: "{{ ansible_play_hosts_all|
map('extract', hostvars, 'ansible_host')|
list }}"
gives
ansible_hosts:
- address-server
- address-server
- address-server
Create a dictionary
ansible_hosts_dict: "{{ dict(ansible_play_hosts_all|zip(ansible_hosts)) }}"
gives
ansible_hosts_dict:
d1: address-server
d2: address-server
d3: address-server
Create a new group. Convert the dictionary to a list and iterate it using the groupby filter
- add_host:
groups: group_host_unique
host: "{{ item.1.0.key }}"
ansible_host: "{{ item.0 }}"
loop: "{{ ansible_hosts_dict|dict2items|groupby('value') }}"
This creates the new inventory group group_host_unique with unique values of ansible_host. The first host is taken if there are more hosts with the same value of ansible_host. As a result, the tasks in the play below are executed only once for hosts with the same server address
- hosts: group_host_unique
gather_facts: false
tasks:
- debug:
var: inventory_hostname
gives
ok: [d1] =>
inventory_hostname: d1
Example of a complete playbook
- hosts: group_host
gather_facts: false
vars:
ansible_hosts: "{{ ansible_play_hosts_all|
map('extract', hostvars, 'ansible_host')|
list }}"
ansible_hosts_dict: "{{ dict(ansible_play_hosts_all|zip(ansible_hosts)) }}"
tasks:
- add_host:
groups: group_host_unique
host: "{{ item.1.0.key }}"
ansible_host: "{{ item.0 }}"
loop: "{{ ansible_hosts_dict|dict2items|groupby('value') }}"
run_once: true
- hosts: group_host_unique
gather_facts: false
tasks:
- debug:
var: inventory_hostname
Test it with various values of ansible_host. For example,
shell> cat hosts
group_host:
hosts:
d1:
ansible_host: address-server1
d2:
ansible_host: address-server1
d3:
ansible_host: address-server2
gives (abridged)
ok: [d1] =>
inventory_hostname: d1
ok: [d3] =>
inventory_hostname: d3