Reputation: 57
Weird title, but the question is pretty complex. (Please don't hesitate to change the title if you know a better one)
I need to create a fresh new list with altered keys from other list, substrings from keys to check key name of other list and match these key substrings with another key from list.
I hope it gets clear when I try to clarify what I need.
First list named ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist
outputs this:
{
"ansible_facts": {
"ansible_net_virtual-systems": [
{
"vsys_zonelist": [
"L3_v0123_Zone1",
"L3_v0124_Zone2",
"L3_v0125_Zone3",
"L3_Trans_v0020_Zone4"
]
}
]
}
}
Second list ansible_facts.ansible_net_routing_table
:
{
"ansible_facts": {
"ansible_net_routing_table": [
{
"virtual_router": "Internal",
"destination": "10.12.123.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.123",
"route_table": "unicast"
},
{
"virtual_router": "Internal",
"destination": "10.12.124.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.124",
"route_table": "unicast"
},
{
"virtual_router": "Internal",
"destination": "10.12.125.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.125",
"route_table": "unicast"
},
{
"virtual_router": "Internal",
"destination": "10.12.20.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.20",
"route_table": "unicast"
}
]
}
}
Now I have the substring v0123 from first list and interface:
ae1.123 from second list. That means that they belong together. I now need the destination
from the second list for each matching lists and also alter the name I get from ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist
.
What I need: Create a list that should look like this:
("interface": "ae1.123"
is not needed anymore. Just a helper to match everything)
{
"result_list": [
{
"name": "n-x-123-Zone1",
"destination": "10.12.123.0/24"
},
{
"name": "n-x-124-Zone2",
"destination": "10.12.124.0/24"
},
{
"name": "n-x-125-Zone3",
"destination": "10.12.125.0/24"
},
{
"name": "n-x-20-Zone4",
"destination": "10.12.20.0/24"
}
]
}
I tried many different ways but somehow I cant manage to get it to work as everything I've done, doesn't help me to create my needed list.
Some input for what I've already tried:
- name: DEBUG list with split and loop
ansible.builtin.debug:
# creates
# n-x-01-Name
# but no list(!), just messages, but could be useful to create a loop
msg: "n-x-{% if item.split('_')[1].startswith('Client') %}{{ item[3:100] }}{% else %}{{ item.split('_')[1] | regex_replace('v','') }}-{% endif %}{% if item.split('_')[2] is defined and item.split('_')[2].startswith('Trans') %}{{ item[3:50] }}{% elif item.split('_')[1].startswith('Clients')%}{% else %}{{ item[9:100] | default('') }}{% endif %}"
loop: '{{ ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist }}'
delegate_to: 127.0.0.1
- name: create extract_interface
ansible.builtin.set_fact:
# creates (also see next task)
# {
# {
# "interface": "ae1.123"
# },
# {
# "interface": "ae1.124"
# }
# }
extract_interface: "{{ ansible_facts.ansible_net_routing_table | map(attribute='interface') | map('community.general.dict_kv', 'interface') | list }}"
delegate_to: 127.0.0.1
- name: create map_destination_to_interface
ansible.builtin.set_fact:
# {
# "ae1.123": "10.12.123.0/24",
# "ae1.124": "10.12.124.0/24"
# }
map_destination_to_interface: "{{ ansible_facts.ansible_net_routing_table | zip(extract_interface) | map('combine') | items2dict(key_name='interface', value_name='destination') }}"
delegate_to: 127.0.0.1
Maybe someone can understand what's needed. Thanks to everyone in advance!
Upvotes: 0
Views: 68
Reputation: 68034
Declare the variables. Zip the lists and create the structure
lists: "{{ ansible_facts.ansible_net_routing_table|
zip(ansible_facts['ansible_net_virtual-systems'][0].vsys_zonelist) }}"
result_list_str: |
{% for i in lists %}
{% set arr=i.1|split('_') %}
- destination: {{ i.0.destination }}
name: n-x-{{ arr[-2][1:]|int }}-{{ arr[-1] }}
{% endfor %}
result_list: "{{ result_list_str|from_yaml }}"
gives
result_list:
- destination: 10.12.123.0/24
name: n-x-123-Zone1
- destination: 10.12.124.0/24
name: n-x-124-Zone2
- destination: 10.12.125.0/24
name: n-x-125-Zone3
- destination: 10.12.20.0/24
name: n-x-20-Zone4
Example of a complete playbook for testing
- hosts: localhost
vars:
ansible_facts:
ansible_net_routing_table:
- age: '3924798'
destination: 10.12.123.0/24
flags: ' Oi '
interface: ae1.123
metric: '10'
nexthop: 0.0.0.0
route_table: unicast
virtual_router: Internal
- age: '3924798'
destination: 10.12.124.0/24
flags: ' Oi '
interface: ae1.124
metric: '10'
nexthop: 0.0.0.0
route_table: unicast
virtual_router: Internal
- age: '3924798'
destination: 10.12.125.0/24
flags: ' Oi '
interface: ae1.125
metric: '10'
nexthop: 0.0.0.0
route_table: unicast
virtual_router: Internal
- age: '3924798'
destination: 10.12.20.0/24
flags: ' Oi '
interface: ae1.20
metric: '10'
nexthop: 0.0.0.0
route_table: unicast
virtual_router: Internal
ansible_net_virtual-systems:
- vsys_zonelist:
- L3_v0123_Zone1
- L3_v0124_Zone2
- L3_v0125_Zone3
- L3_Trans_v0020_Zone4
lists: "{{ ansible_facts.ansible_net_routing_table|
zip(ansible_facts['ansible_net_virtual-systems'][0].vsys_zonelist) }}"
result_list_str: |
{% for i in lists %}
{% set arr=i.1|split('_') %}
- destination: {{ i.0.destination }}
name: n-x-{{ arr[-2][1:]|int }}-{{ arr[-1] }}
{% endfor %}
result_list: "{{ result_list_str|from_yaml }}"
tasks:
- debug:
var: result_list
Upvotes: 1
Reputation: 4391
You've tagged this question with python, so I'm going to answer in python.
Some string manipulation and a couple of loops can extract what you need.
# not needed, but nice for printing out the result
import json
ansible_facts = {
"ansible_facts": {
"ansible_net_virtual-systems": [
{
"vsys_zonelist": [
"L3_v0123_Zone1",
"L3_v0124_Zone2",
"L3_v0125_Zone3",
"L3_Trans_v0020_Zone4",
]
}
],
"ansible_net_routing_table": [
{
"virtual_router": "Internal",
"destination": "10.12.123.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.123",
"route_table": "unicast",
},
{
"virtual_router": "Internal",
"destination": "10.12.124.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.124",
"route_table": "unicast",
},
{
"virtual_router": "Internal",
"destination": "10.12.125.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.125",
"route_table": "unicast",
},
{
"virtual_router": "Internal",
"destination": "10.12.20.0/24",
"nexthop": "0.0.0.0",
"metric": "10",
"flags": " Oi ",
"age": "3924798",
"interface": "ae1.20",
"route_table": "unicast",
},
],
}
}
result = {"result_list": []}
for vs in ansible_facts["ansible_facts"]["ansible_net_virtual-systems"][0]["vsys_zonelist"]:
# work from the last element as that's the consistent part
# turn to int to remove leading zeros
vs_vers = int(vs.split("_")[-2].replace("v", ""))
for nrt in ansible_facts["ansible_facts"]["ansible_net_routing_table"]:
nrt_vers = int(nrt["interface"].split(".")[-1])
# note that the 3rd octet of the destination IP address also seems to be the version
# you can use that to compare as well, as such:
# nrt_vers = int(nrt["destination"].split(".")[2])
if nrt_vers == vs_vers:
# work from the last element as that's the consistent part
vs_zone = vs.split("_")[-1]
# f-strings to turn it into the correct name
vs_name = f"n-x-{vs_vers}-{vs_zone}"
nrt_destination = nrt["destination"]
result["result_list"].append({"name": vs_name, "destination": nrt_destination})
# break to stop needless iteration
break
print(json.dumps(result, indent=4))
output
{
"result_list": [
{
"name": "n-x-123-Zone1",
"destination": "10.12.123.0/24"
},
{
"name": "n-x-124-Zone2",
"destination": "10.12.124.0/24"
},
{
"name": "n-x-125-Zone3",
"destination": "10.12.125.0/24"
},
{
"name": "n-x-20-Zone4",
"destination": "10.12.20.0/24"
}
]
}
Upvotes: 1