boomi
boomi

Reputation: 113

Ansible group variable conflict

I'm running into the issue (feature?) described in Ansible group vars priority , presumably because I've gone about structuring my inventory incorrectly.

The idea was to have two tasks, which apply to all 'routers' or 'firewalls' as defined in the inventory. This part works fine -- Ansible correctly parses the inventory and distinguishes between the two.

The problem is that due to the way the inventory is parsed, it's using the same ansible_user and ansible_password for every customer group. Which apparently makes sense based on the documentation:

When groups of the same parent/child level are merged, it is done alphabetically, and the last group loaded overwrites the previous groups. For example, an a_group will be merged with b_group and b_group vars that match will overwrite the ones in a_group.

Can anyone advise how I should correct this? If I change the 'routers' and 'firewalls' subgroups to be unique, e.g., custA_routers, custB_routers, then it behaves as expected. However then I think I have to write tasks scoped to each of those subgroups. Note that all hosts are unique IP addresses.

Playbook:

---
- name: Check routers
  hosts: routers
  tasks:
    - name: Do stuff.
      <commands>
- name: Check firewalls
  hosts: firewalls
  tasks:
    - name: Do stuff.
      <commands>

Inventory:

all:
  vars:
    ansible_connection: network_cli
    ansible_network_os: ios
  children:
    customerOne:
      vars:
        ansible_user: userOne
        ansible_password: <vaulted pass>
      children:
        routers:
          hosts:
            x.x.x.x
            y.y.y.y
        firewalls:
          vars:
            ansible_network_os: asa
          hosts:
            z.z.z.z
    customerTwo:
      vars:
        ansible_user: userTwo
        ansible_password: <vaulted pass>
      children:
        routers:
          hosts:
            x.x.x.x
            y.y.y.y
        firewalls:
          vars:
            ansible_network_os: asa
          hosts:
            z.z.z.z

Upvotes: 1

Views: 1245

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68034

It's possible to simplify the inventory

all:
  vars:
    ansible_connection: network_cli
    ansible_network_os: ios
  children:
    routers:
      hosts:
        x.x.x.x
        y.y.y.y
    firewalls:
      vars:
        ansible_network_os: asa
      hosts:
        z.z.z.z

and put the authentication data into a separate variable. Put it where it fits best. This might be 'all: vars:' section in the inventory, 'vars:' section in a playbook, 'group_vars/all' directory ...

auth:
  customerOne:
    ansible_user: userOne
    ansible_password: <vaulted pass>
  customerTwo:
    ansible_user: userTwo
    ansible_password: <vaulted pass>

Add a play in the top of the playbook and assign the variables according to the external variable customer

- name: Read variables
  gather_facts: false
  hosts: routers
  tasks:
    - set_fact:
        ansible_user: "{{ auth[customer].ansible_user }}"
        ansible_password: "{{ auth[customer].ansible_password }}"
      run_once: true

- name: Check routers
  hosts: routers
  tasks:
    - name: Do stuff.
      <commands>

Run the playbook and specify the customer

ansible-playbook playbook.yml -e "customer=customerTwo"

Upvotes: 2

letthefireflieslive
letthefireflieslive

Reputation: 12674

I thiink it is ideal to create two separate inventory, customerOneInventory.yaml and customerTwo.yaml or router.yaml and firewalls.yaml.. up to your need. You'll just specify the inventory file you need during ansible playbook run.

ansible-playbook heat-check-playbook.yaml -i customerOneInventory.yaml

Upvotes: 0

Related Questions