我有一个网络接口(interface)的嵌套结构。
interfaces:
- name: bond0
bonding_xmit_hash_policy: layer3+4
bridge:
name: br0
inet: 12.34.56.78/24
slaves:
- name: eth0
mac: xx:xx:xx:xx:xx:xx
- name: eth1
mac: xx:xx:xx:xx:xx:xx
- name: eth2
mac: xx:xx:xx:xx:xx:xx
- name: eth3
mac: xx:xx:xx:xx:xx:xx
我现在想要生成所有已定义接口(interface)名称的平面列表:
- 债券0
- br0
- eth0
- eth1
- eth2
- eth3
理论上这应该很简单,但我无法提取从属接口(interface)的名称(eth0
- eth3
)
以下是工作部分:
根级别的接口(interface)列表(本例中为
bond0
)interfaces | map(attribute='name') | list
List of bridge interfaces
interfaces | selectattr('bridge', 'mapping') | map(attribute='bridge') | map(attribute='name') | list
Here is my attempt to get all the slave interface names:
interfaces | selectattr('slaves') | map(attribute='slaves') | map(attribute='name') | list
换句话说,首先减少接口(interface)列表,只获取那些具有slaves
属性的接口(interface)。然后使用 map
过滤器获取奴隶。直到这里它才有效,如果我输出结果,它看起来像这样:
[
{
"mac": "xx:xx:xx:xx:xx:xx",
"name": "eth0"
},
{
"mac": "xx:xx:xx:xx:xx:xx",
"name": "eth1"
},
{
"mac": "xx:xx:xx:xx:xx:xx",
"name": "eth2"
},
{
"mac": "xx:xx:xx:xx:xx:xx",
"name": "eth3"
}
]
这显然是一个对象列表。这实际上与结构根级别的接口(interface) (bond0
) 的格式相同。但是,当我再次尝试使用 map
获取所有对象的 name
属性时,它会失败,结果是 [Undefined]
。 (注意[]
,好像是Undefined的列表,不是简单的undefined)
但这正是map过滤器应该做的:
Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.
The basic usage is mapping on an attribute. Imagine you have a list of users but you are only interested in a list of usernames
出于测试目的,我还尝试查看使用 selectattr
时会发生什么:
interfaces | selectattr('slaves') | map(attribute='slaves') | selectattr('name') | list
这应该没有什么区别,因为所有对象都有一个 name
属性,但是 Ansible 失败了:
FAILED! => {"failed": true, "msg": "ERROR! 'list object' has no attribute 'name'"}
不知何故,它似乎在列表中有一个列表,调试任务没有显示它,因为输出似乎是一个对象列表,但从 Jinja 的角度来看,它似乎正在处理一个列表列表?
有没有人知道发生了什么以及如何简单地从该列表中获取接口(interface)名称?
现在我用自定义过滤器插件解决了这个问题,但我不明白为什么它不能立即使用。如果这个问题仍未解决并且有人遇到同样的问题,这是我的插件:
class FilterModule(object):
def filters(self):
return {
'interfaces_flattened': self.interfaces_flattened
}
def interfaces_flattened(*args):
names = []
for interface in args[1]:
names.extend(get_names(interface))
return names
def get_names(interface):
names = []
if "name" in interface:
names.append(interface["name"])
if "bridge" in interface:
names.append(interface["bridge"]["name"])
if "slaves" in interface:
for slave in interface["slaves"]:
names.extend(get_names(slave))
return names
最佳答案
问:“所有已定义接口(interface)名称的平面列表。”
蛮力
- set_fact:
names: "{{ names|d([]) + [item.split(':')|last|trim] }}"
loop: "{{ (interfaces|to_nice_yaml).splitlines() }}"
when: item is match('^.*\\s+name:\\s+.*$')
给予
names:
- br0
- bond0
- eth0
- eth1
- eth2
- eth3
关于ansible - 映射嵌套结构的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37002239/