Search code examples
ansibleansible-inventory

Inventory precedences


I am working with Ansible variables. I have this

all.yml

---
port: 9001

inventory.yml

---
group1:
  hosts:
    server1:
      ansible_host: www.server1.com
    server2:
      ansible_host: www.server2.com
  vars:
    port: 9002

   
group2:
  hosts:
    server5:
      ansible_host: www.server5.com

group3:
  hosts:
    server7:
      ansible_host: www.server7.com

I built a playbook, my-playbook.yml

- hosts: localhost
  gather_facts: no
  tasks:
    - name: Netcat server 5
      shell: nc -zv {{ hostvars[item].ansible_host }} {{ port }}
      with_items: "{{ groups['group2'] }}"

    - name: Netcat server 1 only
      shell: nc -zv {{ hostvars['server1']['ansible_host'] }} {{ hostvars[item].port }}
      with_items: "{{ groups['group1'] }}"

When I run my ansible playbook:

ansible-playbook -i inventory/inventory.yml playbook.yml

I am expecting to do use port 9001 for server5 (which is in all.yml) and port 9002 for server1 (which is in the inventory).
However, I can see it's grabbing port 9001 for both.

What am I doing wrong?


Solution

  • You are hitting a group precedence problem. Globally, precedence problems in Ansible can get really tricky especially when you are trying to define variables in different places. This is exactly why the documentation states:

    We suggest that you define each variable in one place: figure out where to define a variable, and keep it simple. For examples, see Tips on where to set variables.

    In the current case, this is one way to solve the problem:

    1. decide there will be a default port for all servers. Modify your all file with default_port: 9001
    2. decide port will only be present at specific group level (so never put it back inside your all file) and only defined for groups overriding the default port.
    3. modify your task(s) as follows:
      - name: Netcat server 5
        shell: nc -zv {{ hostvars[item].ansible_host }} {{ port | d(default_port) }}
        with_items: "{{ groups['group2'] }}"
      
      - name: Netcat server 1 only
        shell: nc -zv {{ hostvars['server1']['ansible_host'] }} {{ hostvars[item].port | d(default_port) }}
        with_items: "{{ groups['group1'] }}"
      

    Note if necessary: d is an alias to default