I'm trying to use a specific collection who gather facts on a server, with a specific structure that I cannot change. I am using Ansible 2.10, but I could use 2.14 if needed (but not preferred).
The structure consists of nested dictionaries and NO lists. Some keys have specific name that are consistent (eg. vtds, device) and some that can change depending on the server (eg. all children of vtds).
My goal is to be able to list all devices in that structure.
Here is a sample playbook I did to examplify my problem. What I cannot find a way to do are the 2 last tasks.
---
- name: Test Dict
host: all
gather_facts: false
vars:
- mapping:
vscsi:
vhost1:
info: azerty
vtds:
AZER_TY_125:
status: UP
device: disk1
AZER_TY_456:
status: UP
device: disk2
vhost2:
info: azerty
vtds:
QWER_TY_123:
status: UP
device: disk2
QWER_TY_456:
status: DOWN
device: disk3
vhost3:
info: azerty
vtds:
QWER_TI_123:
status: DOWN
device: disk4
tasks:
- name: Printing Overarching Dict
ansible.builtin.debug:
msg: 'Type: {{mapping | type debug }}, Value: {{ mapping}}'
- name: Looping Over vhosts
ansible.builtin.debug:
msg: 'VHOST: {{1 item.key }}, type of value: {{item.value | type debug }}'
loop: '{{mapping.vscsi | dict2items }}'
- name: Listing all device
ansible.builtin.debug:
msg: 'Devices: {{ item.value | ? }}'
loop: '{{ mapping.vscsi | dict2items | ??? }}'
- name: Listing all device and their vhosts
ansible.builtin.debug:
msg: 'Vhost: {{ item.key }}, Devices: {{ item.value | #extract the 2nd element of vtds#| map(attribute='device') | list }}'
loop: '{{ mapping.vscsi | dict2items }}'
The first tasks : Generate a list of all devices.
The second tasks : Generate a list of all devices and their associated vhost (or a list of all vhosts with their devices). What I'm missing here, is a way to extract the second element of the vtds dicts as this is an element I cannot know the name of beforehand.
Trying to use the subelements('value.vtds') doesn't work as is to get a list of devices as vtds is a dict and subelements expects a list. Maybe modifying the structure and registering it in a task before looping over it could work but I don't know how to proceed. Most of the similar questions I found on SO don't include the "unknown key" part which bothers me.
Thank you in advance for any leads or answers.
For example,
devices: "{{ mapping|json_query('*.*.vtds.*.device')|
flatten|
unique }}"
gives
devices:
- disk1
- disk2
- disk3
- disk4