ansible - 合并多个字典列表
问题描述
我有一个简单的角色,将模板推入/etc/sysconfig/network-scripts/route-<interface>
.
我们的一些路线是相同的,所以我想在角色变量和组/主机变量的帮助下分解路线。
我尝试应用此解决方案,但它需要一个 dict 并且我有一个 dict 列表,而且我目前对 jinja 过滤器还不是很满意。
这是我的数据结构:
management_default_gateway: '192.168.128.254'
management_interface: eth1
routes:
- interface: "{{management_interface}}"
route_array:
- gateway: "{{management_default_gateway}}"
network: 10.0.0.1/24
- gateway: "{{management_default_gateway}}"
network: 10.0.0.5/24
它可以工作,即使有其他接口,因为模板循环路由列表(见下文),并按预期为每个接口创建一个文件。
roles/routing/tasks/main.yml
:
- name: Template
template:
src: route.j2
dest: "{{'-'.join((route_script_file,item.interface))}}"
owner: root
group: root
mode: 0640
notify: networking restart
with_list: "{{routes}}"
roles/routing/templates/route.j2
:
{% for i in item.route_array %}
{{i.network ~ ' via ' ~ i.gateway ~ '\n'}}
{%- endfor %}
我想在角色 vars 文件夹(或group_vars/all
)上有“标准”路由,并在组或主机级别添加路由。
所以我试着去:
roles/routing/vars/main.yml
:
default_routes:
- interface: "{{management_interface}}"
route_array:
- gateway: "{{management_default_gateway}}"
network: 10.0.0.1/24
- gateway: "{{management_default_gateway}}"
network: 10.0.0.5/24
routes_merged: "{{ default_routes + specific_routes }}"
inventories/prod/group_vars/XXX.yml
:
specific_routes:
- interface: "{{management_interface}}"
route_array:
- gateway: "{{management_default_gateway}}"
network: 10.8.0.1/24
然后我用调试变量得到了这个结果:
ok: [hostname] => {
"routes": [
{
"interface": "eth1",
"route_array": [
{
"gateway": "192.168.128.254",
"network": "10.0.0.1/24"
},
{
"gateway": "192.168.128.254",
"network": "10.0.0.5/24"
}
]
},
{
"interface": "eth1",
"route_array": [
{
"gateway": "192.168.128.254",
"network": "10.8.0.1/24"
}
]
}
]
}
我想要:
ok: [hostname] => {
"routes": [
{
"interface": "eth1",
"route_array": [
{
"gateway": "192.168.128.254",
"network": "10.0.0.1/24"
},
{
"gateway": "192.168.128.254",
"network": "10.0.0.5/24"
},
{
"gateway": "192.168.128.254",
"network": "10.8.0.1/24"
}
]
}
]
}
我想通过接口合并route_array,以便只有一个由接口生成的模板文件。
解决方案
groupby的循环完成了这项工作
- set_fact:
routes: "{{ default_routes + specific_routes }}"
- set_fact:
routes2: "{{ routes2|default([]) +
[{'interface': item.1|map(attribute='interface')|list|first,
'route_array': item.1|map(attribute='route_array')|list|flatten}] }}"
loop: "{{ routes| groupby('interface') }}"
- debug:
var: routes2
给
"routes2": [
{
"interface": "eth1",
"route_array": [
{
"gateway": "192.168.128.254",
"network": "10.0.0.1/24"
},
{
"gateway": "192.168.128.254",
"network": "10.0.0.5/24"
},
{
"gateway": "192.168.128.254",
"network": "10.8.0.1/24"
}
]
}
]
推荐阅读
- console - 我可以为两个独立的 Python 代码提供两个独立的 Spyder 控制台吗?
- visual-studio - Can Visual Studio use an .editorconfig not in the directory hierarchy?
- javascript - 如何使用 es6 的动态导入从静态导入模块?
- c - Unix(Mac OS)终端不将 Ctrl+D 视为 EOF
- time-complexity - 以下代码循环的时间复杂度?
- c# - Linq 在运行时根据列表中的属性名称选择属性
- angular - 使用 Nativescript cli 创建组件时出错
- containers - Openshift + Tomcat9 + JSF -> jsf.application.resource.unable_to_create_compression_directory
- android - 如何通过在 AnimatedBuilder 中点击来关闭带有 Dismissible 小部件的项目?
- mysql - mysqldump 在失败时给出退出代码 0,例如因为数据库不存在