This is your current inventory (as I understand it) "dumped" into a static inventory. This can be replaced with your current dynamic inventory. I placed this in inventories/default/0-hosts.yml
---
all:
hosts:
host_a: {
"os_type": "linux",
"datacenter": "REM",
"location": "IND"
}
host_b: {
"os_type": "linux",
"datacenter": "REM",
"location": "USA",
"status": "success"
}
host_c: {
"os_type": "linux",
"datacenter": "REM",
"location": "IND",
"status": "success"
}
Lets add a new ansible.builtin.constructed source where we create dynamically all the necessary groups from your variables. This goes in inventories/default/1-constructed.yml
---
plugin: ansible.builtin.constructed
strict: false
keyed_groups:
- prefix: os_type
key: os_type
- prefix: datacenter
key: datacenter
- prefix: location
key: location
We can already explore the result from theansible-inventory -i inventories/default/ --list
command:
{
"_meta": {
"hostvars": {
"host_a": {
"datacenter": "REM",
"location": "IND",
"os_type": "linux"
},
"host_b": {
"datacenter": "REM",
"location": "USA",
"os_type": "linux",
"status": "success"
},
"host_c": {
"datacenter": "REM",
"location": "IND",
"os_type": "linux",
"status": "success"
}
}
},
"all": {
"children": [
"ungrouped",
"os_type_linux",
"datacenter_REM",
"location_IND",
"location_USA"
]
},
"datacenter_REM": {
"hosts": [
"host_a",
"host_b",
"host_c"
]
},
"location_IND": {
"hosts": [
"host_a",
"host_c"
]
},
"location_USA": {
"hosts": [
"host_b"
]
},
"os_type_linux": {
"hosts": [
"host_a",
"host_b",
"host_c"
]
}
}
From there it is quite easy to write a playbook which will take advantage of this multi-source inventory taking into account your user variables. As a pure example, this is what I tried in playbook.yml
. I passed your user filters as extra vars for the example but they can come from any source.
---
- name: Process user vars
hosts: localhost
gather_facts: false
tasks:
- name: Create a pattern from filter (defaulting to all if filter is empty)
vars:
filter_data: "{{ user_filter | d({}) }}"
ansible.builtin.set_fact:
filter_pattern: "{{
filter_data.keys() | zip(filter_data.values())
| map('join', '_') | join(':&') | d('all', true)
}}"
- name: Show the constructed pattern
ansible.builtin.debug:
var: hostvars.localhost.filter_pattern
- name: We can now use that pattern in a lookup in any play to get a list
ansible.builtin.debug:
var: "q(
'ansible.builtin.inventory_hostnames',
hostvars.localhost.filter_pattern
)"
- name: We can also use the pattern to target hosts in an other play
hosts: "{{ hostvars.localhost.filter_pattern }}"
gather_facts: false
# Note that you could play a role here
tasks:
- name: Show inventory hostname we would run on
ansible.builtin.debug:
var: inventory_hostname
Demo runs:
- With your original filter
$ ansible-playbook -i inventories/default/ -e '{"user_filter":{"os_type":"linux", "datacenter":"REM", "location":"IND"}}' playbook.yml
PLAY [Process user vars] ******************************************************************************************************************************************************************************************
TASK [Create a pattern from filter (defaulting to all if filter is empty)] ****************************************************************************************************************************************
ok: [localhost]
TASK [Show the constructed pattern] *******************************************************************************************************************************************************************************
ok: [localhost] => {
"hostvars.localhost.filter_pattern": "os_type_linux:&datacenter_REM:&location_IND"
}
TASK [We can now use that pattern in a lookup in any play to get a list] ******************************************************************************************************************************************
ok: [localhost] => {
"q( 'ansible.builtin.inventory_hostnames', hostvars.localhost.filter_pattern )": [
"host_a",
"host_c"
]
}
PLAY [We can also use the pattern to target hosts in an other play] ***********************************************************************************************************************************************
TASK [Show inventory hostname we would run on] ********************************************************************************************************************************************************************
ok: [host_a] => {
"inventory_hostname": "host_a"
}
ok: [host_c] => {
"inventory_hostname": "host_c"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
host_a : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_c : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook -i inventories/default/ -e '{"user_filter":{"os_type":"linux", "datacenter":"REM", "location":"USA"}}' playbook.yml
PLAY [Process user vars] ******************************************************************************************************************************************************************************************
TASK [Create a pattern from filter (defaulting to all if filter is empty)] ****************************************************************************************************************************************
ok: [localhost]
TASK [Show the constructed pattern] *******************************************************************************************************************************************************************************
ok: [localhost] => {
"hostvars.localhost.filter_pattern": "os_type_linux:&datacenter_REM:&location_USA"
}
TASK [We can now use that pattern in a lookup in any play to get a list] ******************************************************************************************************************************************
ok: [localhost] => {
"q( 'ansible.builtin.inventory_hostnames', hostvars.localhost.filter_pattern )": [
"host_b"
]
}
PLAY [We can also use the pattern to target hosts in an other play] ***********************************************************************************************************************************************
TASK [Show inventory hostname we would run on] ********************************************************************************************************************************************************************
ok: [host_b] => {
"inventory_hostname": "host_b"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
host_b : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- Defaults to all hosts if no filter is provided
$ ansible-playbook -i inventories/default/ playbook.yml
PLAY [Process user vars] ******************************************************************************************************************************************************************************************
TASK [Create a pattern from filter (defaulting to all if filter is empty)] ****************************************************************************************************************************************
ok: [localhost]
TASK [Show the constructed pattern] *******************************************************************************************************************************************************************************
ok: [localhost] => {
"hostvars.localhost.filter_pattern": "all"
}
TASK [We can now use that pattern in a lookup in any play to get a list] ******************************************************************************************************************************************
ok: [localhost] => {
"q( 'ansible.builtin.inventory_hostnames', hostvars.localhost.filter_pattern )": [
"host_a",
"host_b",
"host_c"
]
}
PLAY [We can also use the pattern to target hosts in an other play] ***********************************************************************************************************************************************
TASK [Show inventory hostname we would run on] ********************************************************************************************************************************************************************
ok: [host_a] => {
"inventory_hostname": "host_a"
}
ok: [host_b] => {
"inventory_hostname": "host_b"
}
ok: [host_c] => {
"inventory_hostname": "host_c"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
host_a : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_b : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_c : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0