Rahul Singh
Rahul Singh

Reputation: 21

Ansible : Select inventory file out of multiple hosts.ini for three environments based on the version passed as a variable

I have a task , in which I need to select the target environment/hosts amongst the multiple inventory files placed in different folders under inventories/ directory. The selection is based on the version passed as a variable.

inventories/
           preprod/
                  group_vars/
                  hosts.ini
                  ...
           systest/
                  group_vars/
                  hosts.ini
                  ...
           uat/
                  group_vars/
                  hosts.ini
                  ...

So if the version varaiable is 1.x.x then the hosts.ini under preprod should be selected, if its 2.x.x then the hosts.ini under systest should be selected and if its 3.x.x the hosts.ini under uat should be selected.

---
- name: Select hosts from multiple inventories based on version passed as a variable
  hosts: all
  vars:
    version: '1.0'
  tasks:
  - name: Get hosts from first inventory
    set_fact:
      hosts_1: "{{ groups['inventory_1'] | selectattr('version', 'equalto', version) | map(attribute='hostname') | list }}"
  - name: Get hosts from second inventory
    set_fact:
      hosts_2: "{{ groups['inventory_2'] | selectattr('version', 'equalto', version) | map(attribute='hostname') | list }}"
  - name: Merge hosts from both inventories
    set_fact:
      hosts: "{{ hosts_1 + hosts_2 }}"
  - name: Run tasks with hosts
    debug:
      msg: "{{ item }}"
    loop: "{{ hosts }}"

Upvotes: 1

Views: 1318

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67984

Short answer: Copy the inventory file in the first play, refresh_inventory, and use it in the second play. Unfortunately, this does not refresh group_vars from the directories. As a workaround put the group_vars into the inventory files.

Details: Given the project for testing

shell> tree .
.
├── ansible.cfg
├── hosts.env
├── inventory
│   ├── preprod
│   │   └── hosts.ini
│   ├── systest
│   │   └── hosts.ini
│   └── uat
│       └── hosts.ini
└── pb.yml

4 directories, 6 files

Put the group_vars into the inventory files

shell> cat inventory/preprod/hosts.ini 
[all]
preprod1
preprod2
preprod3

[all:vars]
env_gv=preprod
shell> cat inventory/systest/hosts.ini 
systest1
systest2
systest3

[all:vars]
env_gv=systest
shell> cat inventory/uat/hosts.ini 
[all]
uat1
uat2
uat3

[all:vars]
env_gv=uat

The playbook

shell> cat pb.yml
- hosts: localhost
  vars:
    envs:
      1: preprod
      2: systest
      3: uat
    env: "{{ envs[version.split('.').0|int] }}"
  tasks:
    - debug:
        msg: "Use environment: {{ env }}"
    - copy:
        src: "{{ playbook_dir }}/inventory/{{ env }}/hosts.ini"
        dest: "{{ playbook_dir }}/hosts.env"
    - meta: refresh_inventory

- hosts: all
  tasks:
    - block:
        - debug:
            var: ansible_play_hosts_all
        - debug:
            var: env_gv
      run_once: true

gives

version=1.0 works in the environment preprod

shell> ansible-playbook -i hosts.env -e version=1.0 pb.yml

PLAY [localhost] ****************************************************************************************

TASK [debug] ********************************************************************************************
ok: [localhost] => 
  msg: 'Use environment: preprod'

TASK [copy] *********************************************************************************************
changed: [localhost]

TASK [meta] *********************************************************************************************

PLAY [all] **********************************************************************************************

TASK [debug] ********************************************************************************************
ok: [preprod1] => 
  ansible_play_hosts_all:
  - preprod1
  - preprod2
  - preprod3

TASK [debug] ********************************************************************************************
ok: [preprod1] => 
  env_gv: preprod

PLAY RECAP **********************************************************************************************
localhost: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
preprod1: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

version=2.0 works in the environment systest

shell> ansible-playbook -i hosts.env -e version=2.0 pb.yml

PLAY [localhost] ****************************************************************************************

TASK [debug] ********************************************************************************************
ok: [localhost] => 
  msg: 'Use environment: systest'

TASK [copy] *********************************************************************************************
changed: [localhost]

TASK [meta] *********************************************************************************************

PLAY [all] **********************************************************************************************

TASK [debug] ********************************************************************************************
ok: [systest1] => 
  ansible_play_hosts_all:
  - systest1
  - systest2
  - systest3

TASK [debug] ********************************************************************************************
ok: [systest1] => 
  env_gv: systest

PLAY RECAP **********************************************************************************************
localhost: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
systest1: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

version=3.0 works in the environment uat

shell> ansible-playbook -i hosts.env -e version=3.0 pb.yml

PLAY [localhost] ****************************************************************************************

TASK [debug] ********************************************************************************************
ok: [localhost] => 
  msg: 'Use environment: uat'

TASK [copy] *********************************************************************************************
changed: [localhost]

TASK [meta] *********************************************************************************************

PLAY [all] **********************************************************************************************

TASK [debug] ********************************************************************************************
ok: [uat1] => 
  ansible_play_hosts_all:
  - uat1
  - uat2
  - uat3

TASK [debug] ********************************************************************************************
ok: [uat1] => 
  env_gv: uat

PLAY RECAP **********************************************************************************************
localhost: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
uat1: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Example. Precedence of group_vars. YAML format.

shell> tree .
.
├── ansible.cfg
├── group_vars
│   └── all.yml
├── hosts
├── inventories
│   ├── preprod
│   │   └── hosts
│   ├── systest
│   │   └── hosts
│   └── uat
│       └── hosts
├── inventory
│   ├── group_vars
│   │   └── all.yml
│   └── hosts
└── pb.yml

7 directories, 9 files
shell> cat group_vars/all.yml 
env_gv3: playbook group_vars/all
shell> cat inventory/group_vars/all.yml 
env_gv2: inventory group_vars/all
shell> cat inventories/preprod/hosts 
all:
  hosts:
    preprod1:
    preprod2:
    preprod3:
  vars:
    env_gv1: preprod1 inventory file group_vars
    env_gv2: preprod2 inventory file group_vars
    env_gv3: preprod3 inventory file group_vars
shell> cat inventories/systest/hosts 
all:
  hosts:
    systest1:
    systest2:
    systest3:
  vars:
    env_gv1: systest1 inventory file group_vars
    env_gv2: systest2 inventory file group_vars
    env_gv3: systest3 inventory file group_vars
shell> cat inventories/uat/hosts 
all:
  hosts:
    uat1:
    uat2:
    uat3:
  vars:
    env_gv1: uat1 inventory file group_vars
    env_gv2: uat2 inventory file group_vars
    env_gv3: uat3 inventory file group_vars
shell> cat pb.yml 
- hosts: localhost
  vars:
    envs:
      1: preprod
      2: systest
      3: uat
    env: "{{ envs[version.split('.').0|int] }}"
  tasks:
    - debug:
        msg: "Use environment: {{ env }}"
    - copy:
        src: "{{ playbook_dir }}/inventories/{{ env }}/hosts"
        dest: "{{ playbook_dir }}/inventory/hosts"
    - meta: refresh_inventory

- hosts: all
  tasks:
    - block:
        - debug:
            var: ansible_play_hosts_all
        - debug:
            msg: |
              env_gv1: {{ env_gv1 }}
              env_gv2: {{ env_gv2 }}
              env_gv3: {{ env_gv3 }}
      run_once: true
shell> ansible-playbook -i inventory/hosts -e version=2.0 pb.yml

shows that variable precedence:

  1. inventory file or script group vars
  2. inventory group_vars/all
  3. playbook group_vars/all

works as expected

PLAY [localhost] ****************************************************************************************

TASK [debug] ********************************************************************************************
ok: [localhost] => 
  msg: 'Use environment: systest'

TASK [copy] *********************************************************************************************
changed: [localhost]

TASK [meta] *********************************************************************************************

PLAY [all] **********************************************************************************************

TASK [debug] ********************************************************************************************
ok: [systest1] => 
  ansible_play_hosts_all:
  - systest1
  - systest2
  - systest3

TASK [debug] ********************************************************************************************
ok: [systest1] => 
  msg: |-
    env_gv1: systest1 inventory file group_vars
    env_gv2: inventory group_vars/all
    env_gv3: playbook group_vars/all

PLAY RECAP **********************************************************************************************
localhost: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
systest1: ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Upvotes: 2

Related Questions