There are more options. For example, given the data
orgs:
o1:
n1:
d1:
license: k1
d2:
license: k2
n2:
d3:
license: k3
o2:
n3:
d4:
license: k4
d5:
license: k5
- Use to_paths lookup
orgs_paths: "{{ lookup('ansible.utils.to_paths', orgs) }}"
gives
orgs_paths:
o1.n1.d1.license: k1
o1.n1.d2.license: k2
o1.n2.d3.license: k3
o2.n3.d4.license: k4
o2.n3.d5.license: k5
Then, declare the lists
_key: "{{ orgs_paths.keys()|list }}"
_dev: "{{ _key|map('splitext')|map('first')|unique }}"
_net: "{{ _dev|map('splitext')|map('first')|unique }}"
_org: "{{ _net|map('splitext')|map('first')|unique }}"
_arr: "{{ item.split('.') }}"
and delete the tree
- debug:
msg: "Delete license: {{ orgs_paths[item] }} for {{ _arr[0:3] }}"
loop: "{{ _key }}"
- debug:
msg: "Delete device: {{ _arr.2 }} for {{ _arr[0:2] }}"
loop: "{{ _dev }}"
- debug:
msg: "Delete network: {{ _arr.1 }} for {{ _arr[0:1] }}"
loop: "{{ _net }}"
- debug:
msg: "Delete org: {{ item }}"
loop: "{{ _org }}"
- debug:
msg: "Delete orgs"
gives (abridged)
msg: 'Delete license: k1 for [''o1'', ''n1'', ''d1'']'
msg: 'Delete license: k2 for [''o1'', ''n1'', ''d2'']'
msg: 'Delete license: k3 for [''o1'', ''n2'', ''d3'']'
msg: 'Delete license: k4 for [''o2'', ''n3'', ''d4'']'
msg: 'Delete license: k5 for [''o2'', ''n3'', ''d5'']'
msg: 'Delete device: d1 for [''o1'', ''n1'']'
msg: 'Delete device: d2 for [''o1'', ''n1'']'
msg: 'Delete device: d3 for [''o1'', ''n2'']'
msg: 'Delete device: d4 for [''o2'', ''n3'']'
msg: 'Delete device: d5 for [''o2'', ''n3'']'
msg: 'Delete network: n1 for [''o1'']'
msg: 'Delete network: n2 for [''o1'']'
msg: 'Delete network: n3 for [''o2'']'
msg: 'Delete org: o1'
msg: 'Delete org: o2'
msg: Delete orgs
Example of a complete playbook
- hosts: localhost
vars:
orgs:
o1:
n1:
d1: {license: k1}
d2: {license: k2}
n2:
d3: {license: k3}
o2:
n3:
d4: {license: k4}
d5: {license: k5}
orgs_paths: "{{ lookup('ansible.utils.to_paths', orgs) }}"
_key: "{{ orgs_paths.keys()|list }}"
_dev: "{{ _key|map('splitext')|map('first')|unique }}"
_net: "{{ _dev|map('splitext')|map('first')|unique }}"
_org: "{{ _net|map('splitext')|map('first')|unique }}"
_arr: "{{ item.split('.') }}"
tasks:
- debug:
msg: "Delete license: {{ orgs_paths[item] }} for {{ _arr[0:3] }}"
loop: "{{ _key }}"
- debug:
msg: "Delete device: {{ _arr.2 }} for {{ _arr[0:2] }}"
loop: "{{ _dev }}"
- debug:
msg: "Delete network: {{ _arr.1 }} for {{ _arr[0:1] }}"
loop: "{{ _net }}"
- debug:
msg: "Delete org: {{ item }}"
loop: "{{ _org }}"
- debug:
msg: "Delete orgs"
- The next option is the inclusion of tasks in loops. For example, create files
shell> cat del_dev.yml
- block:
- debug:
msg: >-
Delete license {{ item.value }} for
[{{ item_org.key }}, {{ item_net.key }}, {{ item_dev.key }}]
loop: "{{ item_dev.value|dict2items }}"
- debug:
msg: >-
Delete device {{ item_dev.key }} for
[{{ item_org.key }}, {{ item_net.key }}]
shell> cat del_net.yml
- block:
- include_tasks: del_dev.yml
loop: "{{ item_net.value|dict2items }}"
loop_control:
loop_var: item_dev
- debug:
msg: >-
Delete network {{ item_net.key }} for
[{{ item_org.key }}]
shell> cat del_org.yml
- block:
- include_tasks: del_net.yml
loop: "{{ item_org.value|dict2items }}"
loop_control:
loop_var: item_net
- debug:
msg: >-
Delete org {{ item_org.key }}
Recursively include the tasks in a playbook
- hosts: localhost
vars:
orgs:
o1:
n1:
d1: {license: k1}
d2: {license: k2}
n2:
d3: {license: k3}
o2:
n3:
d4: {license: k4}
d5: {license: k5}
tasks:
- block:
- include_tasks: del_org.yml
loop: "{{ orgs|dict2items }}"
loop_control:
loop_var: item_org
- debug:
msg: Delete orgs
gives (abridged)
msg: Delete license k1 for [o1, n1, d1]
msg: Delete device d1 for [o1, n1]
msg: Delete license k2 for [o1, n1, d2]
msg: Delete device d2 for [o1, n1]
msg: Delete network n1 for [o1]
msg: Delete license k3 for [o1, n2, d3]
msg: Delete device d3 for [o1, n2]
msg: Delete network n2 for [o1]
msg: Delete org o1
msg: Delete license k4 for [o2, n3, d4]
msg: Delete device d4 for [o2, n3]
msg: Delete license k5 for [o2, n3, d5]
msg: Delete device d5 for [o2, n3]
msg: Delete network n3 for [o2]
msg: Delete org o2
msg: Delete orgs
- Getting the structure on the fly makes the code simpler. For example, let's imagine the structure is the same as before. As the first step in each loop, we find the list of org, their networks, and devices. This is the meaning of the argument in the loop statement. In real life, you would probably get the lists in a separate task before the loop. Create files
shell> cat del_dev.yml
- block:
- debug:
msg: >-
Delete license {{ _item }} for
[{{ item_org }}, {{ item_net }}, {{ item_dev }}]
vars:
_item: "{{ orgs[item_org][item_net][item_dev]['license'] }}"
- debug:
msg: >-
Delete device {{ item_dev }} for
[{{ item_org }}, {{ item_net }}]
shell> cat del_net.yml
- block:
- include_tasks: del_dev.yml
loop: "{{ orgs[item_org][item_net].keys()|list }}"
loop_control:
loop_var: item_dev
- debug:
msg: >-
Delete network {{ item_net }} for
[{{ item_org }}]
shell> cat del_org.yml
- block:
- include_tasks: del_net.yml
loop: "{{ orgs[item_org].keys()|list }}"
loop_control:
loop_var: item_net
- debug:
msg: >-
Delete org {{ item_org }}
The playbook below gives the same results
- hosts: localhost
vars:
orgs:
o1:
n1:
d1: {license: k1}
d2: {license: k2}
n2:
d3: {license: k3}
o2:
n3:
d4: {license: k4}
d5: {license: k5}
tasks:
- block:
- include_tasks: del_org.yml
loop: "{{ orgs.keys()|list }}"
loop_control:
loop_var: item_org
- debug:
msg: Delete orgs
Q: "How to propagate the org_id due to only a single item?"
A: Simply put this single item into the list. For example
- hosts: localhost
vars:
orgs:
o1:
n1:
d1: {license: k1}
d2: {license: k2}
n2:
d3: {license: k3}
o2:
n3:
d4: {license: k4}
d5: {license: k5}
tasks:
- block:
- include_tasks: del_org.yml
loop:
- o2
loop_control:
loop_var: item_org
- debug:
msg: Delete orgs
gives
msg: Delete license k4 for [o2, n3, d4]
msg: Delete device d4 for [o2, n3]
msg: Delete license k5 for [o2, n3, d5]
msg: Delete device d5 for [o2, n3]
msg: Delete network n3 for [o2]
msg: Delete org o2
msg: Delete orgs