Let's assume my Ansible inventory looks like this:
all:
children:
my_app_hosts:
hosts:
192.168.0.1
dns_servers:
hosts:
192.168.0.2
192.168.0.3
Now, I have a playbook that sets up "my app" to run on my_app_hosts
. The final step is informing the DNS servers, that "my app" is now accessible at 192.168.0.1
. I have a playbook, let's say update_dns_entries
, placed in the dns_severs
role's directory. This playbook works well, given the new DNS data.
The thing is, I need update_dns_entries
to run on 192.168.0.2
and 192.168.0.3
, the dns_servers
defined in my inventory, and not on 192.168.0.1
, the "my app" host. But it needs to be triggered from the "my app" setup playbook. The Ansible controller has access to all three of the servers.
I've been struggling with this for a while and searching around as well. I feel like this is a very basic question, still I didn't find a working way to achieve this.
I tried:
delegate_to
in include_role
. This is not supported.delegate_to
in import_role
. This does not work with loops (like with_items: "{{ group['dns_servers'] }}"
).include_tasks
with the loop. Still no luck.This must be a very typical need in Ansible, but I could not figure it out yet, so sorry for this basic question! I'm sure I'm overlooking something, perhaps my approach or even my understanding of Ansible is completely wrong.
After some more time of trying, I found the following solution, which seems the most reasonable to me:
In my "my app" setup playbook, I have:
- name: Update DNS entries
ansible.builtin.import_role:
name: dns_server
tasks_from: update_dns_entries
vars:
host_names: "{{ my_app_hostnames }}"
ipv4_address: # the new IPv4 address
ipv6_address: # the new IPv6 address
Then, the update_dns_entries.yml
file looks like this:
- name: "Update DNS entries for host {{ host_names }}"
ansible.builtin.include_tasks:
file: "{{ role_path }}/../dns_server/tasks/update_dns_entries_on_single_host.yml"
vars:
dns_server: "{{ dns_server_ip }}"
loop: "{{ groups['dns_servers'] }}"
loop_control:
loop_var: dns_server_ip
And lastly, in my update_dns_entries_on_single_host.yml
, the structure is like this:
- name: "Remove old DNS entries on {{ dns_server }}"
# The actual tasks to update the DNS entries
delegate_to: "{{ dns_server }}"
with_items: "{{ host_names }}"
- name: "Create new DNS entries on {{ dns_server }}"
# The second actual tasks to update the DNS entries
delegate_to: "{{ dns_server }}"
with_items: "{{ host_names }}"
# ...
This way, I can use delegate_to
and loop over all the dns_servers
without getting into trouble and still user another loop variable (host_names
) without interference.