Create a tree-like structure with ansible
Solution 1:
I guess what you're looking for is combine
with recursive=True
in a set_fact
task:
This playboook, for example, gathers hostname => ip
relations for each of my nodes which helps me to ensure /etc/hosts or dns configurations are consistent accross my cluster.
- hosts: all
tasks:
- name: Gather hosts ips
shell: "dig {{ item }} +short"
register: hosts_ips
loop: "{{ ansible_play_batch }}"
- name: dbg
ansible.builtin.debug:
var: hosts_ips
- name: Storing ips as fact
set_fact:
hosts_status:
"{{ hosts_status|default([]) | combine({
item.item : {
'ip': item.stdout,
}
}, recursive=True)
}}"
loop: "{{ hosts_ips.results | default([]) }}"
- name: dbg hosts_status
ansible.builtin.debug:
var: hosts_status
Result on each server (They're the same so i'm good):
ok: [amsh-1] => {
"hosts_status": {
"amsh-1": {
"ip": "192.168.121.28"
},
"amsh-2": {
"ip": "192.168.121.109"
},
"amsh-3": {
"ip": "192.168.121.229"
},
"amsh-4": {
"ip": "192.168.121.92"
}
}
}
ok: [amsh-2] => {
"hosts_status": {
"amsh-1": {
"ip": "192.168.121.28"
},
"amsh-2": {
"ip": "192.168.121.109"
},
"amsh-3": {
"ip": "192.168.121.229"
},
"amsh-4": {
"ip": "192.168.121.92"
}
}
}
ok: [amsh-3] => {
"hosts_status": {
"amsh-1": {
"ip": "192.168.121.28"
},
"amsh-2": {
"ip": "192.168.121.109"
},
"amsh-3": {
"ip": "192.168.121.229"
},
"amsh-4": {
"ip": "192.168.121.92"
}
}
}
ok: [amsh-4] => {
"hosts_status": {
"amsh-1": {
"ip": "192.168.121.28"
},
"amsh-2": {
"ip": "192.168.121.109"
},
"amsh-3": {
"ip": "192.168.121.229"
},
"amsh-4": {
"ip": "192.168.121.92"
}
}
}
I guess you'll be able to make your data structure with it.
PS: btw, this script inline in an Ansible playbook is written in jinja2 if you look for docs: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-and-selecting-data