ansibleansible-inventory

How to include another playbook and run it in on its role's hosts?


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:

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.


Solution

  • 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.