我有一个字典列表
"tor_vlans": [
{
"switch-ls01": {
"Vlan1": {
"id": "1",
"ip": "unassigned",
"ok": "NO",
"protocol": "down",
"status": "up"
},
"Vlan10": {
"id": "10",
"ip": "10.10.10.2/24",
"ok": "YES",
"protocol": "up",
"status": "up"
},
"Vlan20": {
"id": "20",
"ip": "10.10.20.2/24",
"ok": "YES",
"protocol": "up",
"status": "up"
}
}
}
]
使用 ansible.utils.ipaddr 模块,我从上面提取了 ip 值,并创建了一个新字典,其中包含每个子网的其他详细信息
"subnet_details": {
"10.10.10.2/24": {
"dhcp_scope": "10.10.10.4-10.10.10.254",
"tor_1_ip": "10.10.10.2/24",
"tor_2_ip": "10.10.10.3/24",
"vrrp": "10.10.10.1/24"
},
"10.10.20.2/24": {
"dhcp_scope": "10.10.20.4-10.10.20.254",
"tor_1_ip": "10.10.20.2/24",
"tor_2_ip": "10.10.20.3/24",
"vrrp": "10.10.20.1/24"
}
}
我正在尝试通过将 tor_vlans 列表中的 ip 值与 subnet_details 中的 keys
进行匹配,将两组字典组合成一个新的字典列表。使用下面的 Jinja2 模板
- name: Combine both based on matching ips and keys
ansible.builtin.set_fact:
my_new_dict: |
{% for tor in tor_vlans %}
{% for key,value in tor.items() %}
{% for vlan,facts in value.items() %}
{% for cidr,param in subnet_details.items() %}
{% if cidr in facts %}
{{ key }}:
{{ vlan }}:
{{ facts }}
{{ param }}
{% else %}
{{ key }}:
{{ vlan }}:
{{ facts }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
预期输出为
"my_new_dict": [
{
"switch-ls01": {
"Vlan1": {
"id": "1",
"ip": "unassigned",
"ok": "NO",
"protocol": "down",
"status": "up"
},
"Vlan10": {
"id": "10",
"ip": "10.10.10.2/24",
"ok": "YES",
"protocol": "up",
"status": "up",
"dhcp_scope": "10.10.10.4-10.10.10.254",
"tor_1_tep_ip": "10.10.10.2/24",
"tor_2_tep_ip": "10.10.10.3/24",
"vrrp": "10.10.10.1/24"
},
"Vlan20": {
"id": "20",
"ip": "10.10.20.2/24",
"ok": "YES",
"protocol": "up",
"status": "up",
"dhcp_scope": "10.10.20.4-10.10.20.254",
"tor_1_tep_ip": "10.10.20.2/24",
"tor_2_tep_ip": "10.10.20.3/24",
"vrrp": "10.10.20.1/24"
}
}
}
]
我得到的实际输出是
"my_new_dict|from_yaml": {
"switch-ls01": {
"Vlan20": {
"id": "20",
"ip": "10.10.20.2/24",
"ok": "YES",
"protocol": "up",
"status": "up"
}
}
}
如果除了使用 Jinja 之外还有其他梳理方法,请告诉我。
同样,如果可以使用 ansible.utils.ipaddr 模块直接在 tor_vlans 中创建子网详细信息,我也无法弄清楚。
“Vlan1”、“Vlan10”等...在尝试直接在 tor_vlans 上使用 ipaddr 模块时给我带来了问题,因为这些密钥是动态学习的,所以我不能假设它们总是相同的,即有时它们可能是“Vlan25”、“Vlan55”等...
我找到了一些关于 Python 的帖子,但是似乎找不到任何类似的 Ansible 帖子
创建更新列表
update: |
{% filter from_yaml %}
{% for vlan in tor_vlans %}
{% for sw,vlans in vlan.items() %}
[ {{ sw }}: {
{% for k,v in vlans.items() %}
{% for s,d in subnet_details.items() %}
{% if [v.ip]|ansible.utils.ipaddr(s)|length > 0 %}
{{ k }}: {{ v|combine(d) }},
{% endif %}
{% endfor %}
{% endfor %} },
{% endfor %} ]
{% endfor %}
{% endfilter %}
给予
update:
- switch-ls01:
Vlan10:
dhcp_scope: 10.10.10.4-10.10.10.254
id: '10'
ip: 10.10.10.2/24
ok: 'YES'
protocol: up
status: up
tor_1_ip: 10.10.10.2/24
tor_2_ip: 10.10.10.3/24
vrrp: 10.10.10.1/24
Vlan20:
dhcp_scope: 10.10.20.4-10.10.20.254
id: '20'
ip: 10.10.20.2/24
ok: 'YES'
protocol: up
status: up
tor_1_ip: 10.10.20.2/24
tor_2_ip: 10.10.20.3/24
vrrp: 10.10.20.1/24
压缩列表并合并项目
my_new_dict: "{{ tor_vlans |
zip(update) |
map('combine', recursive=True) }}"
给予
my_new_dict:
- switch-ls01:
Vlan1:
id: '1'
ip: unassigned
ok: 'NO'
protocol: down
status: up
Vlan10:
dhcp_scope: 10.10.10.4-10.10.10.254
id: '10'
ip: 10.10.10.2/24
ok: 'YES'
protocol: up
status: up
tor_1_ip: 10.10.10.2/24
tor_2_ip: 10.10.10.3/24
vrrp: 10.10.10.1/24
Vlan20:
dhcp_scope: 10.10.20.4-10.10.20.254
id: '20'
ip: 10.10.20.2/24
ok: 'YES'
protocol: up
status: up
tor_1_ip: 10.10.20.2/24
tor_2_ip: 10.10.20.3/24
vrrp: 10.10.20.1/24
用于测试的完整剧本示例
- hosts: all
vars:
tor_vlans:
- switch-ls01:
Vlan1:
id: '1'
ip: unassigned
ok: 'NO'
protocol: down
status: up
Vlan10:
id: '10'
ip: 10.10.10.2/24
ok: 'YES'
protocol: up
status: up
Vlan20:
id: '20'
ip: 10.10.20.2/24
ok: 'YES'
protocol: up
status: up
subnet_details:
10.10.10.2/24:
dhcp_scope: 10.10.10.4-10.10.10.254
tor_1_ip: 10.10.10.2/24
tor_2_ip: 10.10.10.3/24
vrrp: 10.10.10.1/24
10.10.20.2/24:
dhcp_scope: 10.10.20.4-10.10.20.254
tor_1_ip: 10.10.20.2/24
tor_2_ip: 10.10.20.3/24
vrrp: 10.10.20.1/24
update: |
{% filter from_yaml %}
{% for vlan in tor_vlans %}
{% for sw,vlans in vlan.items() %}
[ {{ sw }}: {
{% for k,v in vlans.items() %}
{% for s,d in subnet_details.items() %}
{% if [v.ip]|ansible.utils.ipaddr(s)|length > 0 %}
{{ k }}: {{ v|combine(d) }},
{% endif %}
{% endfor %}
{% endfor %} },
{% endfor %} ]
{% endfor %}
{% endfilter %}
my_new_dict: "{{ tor_vlans |
zip(update) |
map('combine', recursive=True) }}"
tasks:
- debug:
var: update
- debug:
var: my_new_dict