使用 Ansible 创建字典过滤不同值的列表
Create list of dict filtering different value with Ansible
我正在寻找一个更好的解决方案来通过键 A 和 return 键 B 的值列表来过滤字典列表。更具体地说 - 每个主机都有一个字典:
infrastructure:
name: "x..."
network:
address: "1..."
存在定义了 network.address
的主机,也存在未定义 network.address
的主机。我现在需要一个所有 infrastructure.name
定义为 network.address
.
的列表
- name: "Define Alias fact"
set_fact:
alias: []
- name: "Add Aliases for all hosts with network.address is defined"
set_fact:
alias: "{{ alias + [hostvars[host].infrastructure.name + '-alias'] }}"
when:
- "hostvars[host].network is defined"
- "hostvars[host].network.address is defined"
with_items: "{{ groups['all'] }}"
loop_control:
loop_var: host
可行,但有点乱,因为我多次调用 set_fact 并将项目添加到列表中。
当我看的时候:
- name: "Define addresses fact"
set_fact:
address: "{{ groups['all'] | map('extract', hostvars) | list | json_query('[*].network.address') }}"
这个要短得多,也许更容易。
我想问一下,在展平列表以“过滤掉”network.address 未定义并使用 json_query 和一些字符串操作来附加“-alias”。有没有类似的简单方法来替换第一个脚本?
以纯 JMESPath 方式,给定 JSON
[
{
"infrastructure": {"name": "x..."},
"network": {"address": "1..."}
},
{
"infrastructure": {"name": "y..."}
},
{
"infrastructure": {"name": "z..."},
"network": {"address": "2..."}
},
{
"infrastructure": {"name": "a..."},
"network": {}
}
]
您可以提取与 -alias
连接的 infrastructure.name
,并以这种方式设置 network.address
:
[?network.address].join('-', [infrastructure.name, 'alias'])
这将产生:
[
"x...-alias",
"z...-alias"
]
函数join
主要用于将数组元素粘合在一起,但也可用于连接字符串。
因此,对于演示这一点的剧本:
- hosts: all
gather_facts: no
tasks:
- debug:
msg: >-
{{
servers | to_json | from_json |
json_query(
'[?network.address].join(`-`, [infrastructure.name, `alias`])'
)
}}
vars:
servers:
- infrastructure:
name: x...
network:
address: 1...
- infrastructure:
name: y...
- infrastructure:
name: z...
network:
address: 2...
- infrastructure:
name: a...
network:
注意奇数构造| from_json | to_json
的解释
这产生:
PLAY [all] ********************************************************************************************************
TASK [debug] ******************************************************************************************************
ok: [localhost] => {
"msg": [
"x...-alias",
"z...-alias"
]
}
PLAY RECAP ********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
我正在寻找一个更好的解决方案来通过键 A 和 return 键 B 的值列表来过滤字典列表。更具体地说 - 每个主机都有一个字典:
infrastructure:
name: "x..."
network:
address: "1..."
存在定义了 network.address
的主机,也存在未定义 network.address
的主机。我现在需要一个所有 infrastructure.name
定义为 network.address
.
- name: "Define Alias fact"
set_fact:
alias: []
- name: "Add Aliases for all hosts with network.address is defined"
set_fact:
alias: "{{ alias + [hostvars[host].infrastructure.name + '-alias'] }}"
when:
- "hostvars[host].network is defined"
- "hostvars[host].network.address is defined"
with_items: "{{ groups['all'] }}"
loop_control:
loop_var: host
可行,但有点乱,因为我多次调用 set_fact 并将项目添加到列表中。
当我看的时候:
- name: "Define addresses fact"
set_fact:
address: "{{ groups['all'] | map('extract', hostvars) | list | json_query('[*].network.address') }}"
这个要短得多,也许更容易。
我想问一下,在展平列表以“过滤掉”network.address 未定义并使用 json_query 和一些字符串操作来附加“-alias”。有没有类似的简单方法来替换第一个脚本?
以纯 JMESPath 方式,给定 JSON
[
{
"infrastructure": {"name": "x..."},
"network": {"address": "1..."}
},
{
"infrastructure": {"name": "y..."}
},
{
"infrastructure": {"name": "z..."},
"network": {"address": "2..."}
},
{
"infrastructure": {"name": "a..."},
"network": {}
}
]
您可以提取与 -alias
连接的 infrastructure.name
,并以这种方式设置 network.address
:
[?network.address].join('-', [infrastructure.name, 'alias'])
这将产生:
[
"x...-alias",
"z...-alias"
]
函数join
主要用于将数组元素粘合在一起,但也可用于连接字符串。
因此,对于演示这一点的剧本:
- hosts: all
gather_facts: no
tasks:
- debug:
msg: >-
{{
servers | to_json | from_json |
json_query(
'[?network.address].join(`-`, [infrastructure.name, `alias`])'
)
}}
vars:
servers:
- infrastructure:
name: x...
network:
address: 1...
- infrastructure:
name: y...
- infrastructure:
name: z...
network:
address: 2...
- infrastructure:
name: a...
network:
注意奇数构造| from_json | to_json
的解释
这产生:
PLAY [all] ********************************************************************************************************
TASK [debug] ******************************************************************************************************
ok: [localhost] => {
"msg": [
"x...-alias",
"z...-alias"
]
}
PLAY RECAP ********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0