基于两个Ansible Facts列表匹配生成目标结构化列表
如何基于两个Ansible Facts列表生成关联后的结构化列表?
需求说明
需要基于两个Ansible Facts列表生成新的结构化列表,通过提取子串进行匹配关联,并修改指定字段的格式。
输入数据
第一个Facts列表:ansible_facts["ansible_net_virtual-systems"][0].vsys_zonelist
{ "ansible_facts": { "ansible_net_virtual-systems": [ { "vsys_zonelist": [ "L3_v0123_Zone1", "L3_v0124_Zone2", "L3_v0125_Zone3", "L3_Trans_v0020_Zone4" ] } ] } }
第二个Facts列表: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" } ] } }
匹配规则与目标格式
匹配规则
- 从第一个列表的Zone名称中提取
v开头的子串(如v0123),去掉开头的v和前导零后得到数字后缀(如123) - 匹配第二个列表中
interface字段的后缀(如ae1.123中的123),关联对应的destination地址 - 将Zone名称修改为指定格式:
L3_v0123_Zone1→n-x-123-Zone1
目标格式
{ "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" } ] }
尝试过的方法
以下Playbook未能成功生成目标列表:
- 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
解决方案
以下Playbook可以实现需求:
- name: 创建接口与目标地址的映射字典 ansible.builtin.set_fact: iface_dest_map: "{{ ansible_facts.ansible_net_routing_table | items2dict(key_name='interface', value_name='destination') }}" delegate_to: 127.0.0.1 - name: 生成目标结构化列表 ansible.builtin.set_fact: result_list: "{{ result_list | default([]) + [ { 'name': new_name, 'destination': iface_dest_map['ae1.' ~ num_suffix] } ] }}" loop: "{{ ansible_facts['ansible_net_virtual-systems'][0].vsys_zonelist }}" vars: # 提取Zone名称中v开头的数字部分,去除前导零 num_suffix: "{{ item | regex_search('v(\\d+)', '\\1') | first | regex_replace('^0+', '') }}" # 提取Zone名称的最后一部分(如Zone1) zone_part: "{{ item.split('_') | last }}" # 拼接成指定格式的name字段 new_name: "n-x-{{ num_suffix }}-{{ zone_part }}" delegate_to: 127.0.0.1 - name: 输出结果列表 ansible.builtin.debug: var: result_list delegate_to: 127.0.0.1
步骤说明
- 创建映射字典:直接使用
items2dict将路由表中的interface作为键,destination作为值,生成一个可快速查找的字典,简化后续匹配逻辑。 - 遍历Zone列表生成结果:
- 用
regex_search提取Zone名称中v后面的数字串,再用regex_replace去掉前导零,得到匹配接口后缀的数字 - 用
split('_') | last提取Zone名称的最后一部分(如Zone1) - 拼接成指定格式的
name字段 - 通过
ae1.{{ num_suffix }}作为键,从映射字典中取出对应的destination,将结构化数据添加到结果列表中
- 用
- 输出结果:通过debug任务查看最终生成的
result_list
内容的提问来源于stack exchange,提问作者marcb4
相关产品推荐
相关产品推荐

