json 变量的 Ansible 过滤器
Ansible filter for json variable
一些背景信息。我正在使用 netbox 作为我们网络自动化的真实来源,我目前正在做一些测试以自动化瞻博网络配置。 Netbox 目前用作我的 ansible 库存并提供 host_vars.
我想完成一个简单的任务,即根据主机变量在我的 Juniper 配置中设置一个“值”。
问题
我最明确地使用了错误的 map/filter 组合来实现循环遍历字典“dns”中的值的目标,但我已经尝试了无数次但没有任何成功,所以将我的问题提交给社区征求意见。
我有以下 host_vars:
{
"ansible_host": "192.168.1.1",
"config_context": [
{
"_utility": {
"dns": [
"10.10.10.10",
"10.10.10.20"
]
}
}
],
"device_roles": [
"leaf"
],
"device_types": [
"qfx5120-48y"
]
}
我的任务目前看起来像:
- name: Set DNS server
juniper.device.config:
config_mode: 'exclusive'
load: 'set'
lines:
- 'set system name-server "{{ item }}"'
loop: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
发出错误信息
尝试调试它注册一个变量并使用调试消息打印它:
调试
- name: Print var
vars:
- nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
debug:
msg:
- "{{ nameservers }}"
结果
ok: [poc-spine01-re] => {
"msg": [
[
"10.10.10.10",
"10.10.10.20"
]
]
}
但是,当尝试使用结果循环遍历值时,我得到另一个错误
调试
- name: Print var loop
vars:
- nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
debug:
msg:
- "{{ item }}"
loop: nameservers
结果
fatal: [poc-leaf03-re]: FAILED! => {
"msg": "Invalid data passed to 'loop', it requires a list, got this instead: nameservers. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."
}
fatal: [poc-spine01-re]: FAILED! => {
"msg": "Invalid data passed to 'loop', it requires a list, got this instead: nameservers. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."
}
更新
嗨,它适用于循环!。我已经调整了我的变量,现在正在考虑是否应该只获取密钥 dns1 或 dns2 的值(不在循环中)
主机变量
{
"ansible_host": "192.168.1.1",
"config_context": [
{
"_utility": {
"dns": {
"dns1": "10.10.10.10",
"dns2": "10.10.10.20"
}
}
}
],
"device_roles": [
"leaf"
],
"device_types": [
"qfx5120-48y"
]
}
但无法让地图过滤器正确显示一个值
任务
- name: Set DNS server
vars:
ns1: "{{ config_context | map(attribute='_utility.dns.dns1') | flatten }}"
juniper.device.config:
config_mode: 'exclusive'
load: 'set'
lines:
- 'set system name-server "{{ ns1 }}"'
结果
如您所见,10.10.10.10 的值用方括号和双引号引起来,而不仅仅是 10.10.10.10
的值字符串
fatal: [poc-spine01-re]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"lines": [
"set system name-server \"['10.10.10.10']\""
],
你的循环应该修复如下:
loop: "{{ config_context | map(attribute='_utility.dns') | flatten }}"
此外,我会添加一些额外的过滤器以确保:
- 如果在多个
config_context
条目(即 unique
)中声明同一个 dns,则您不会循环两次
- 你总是以相同的顺序去其他列表(即
sort
)
loop: "{{ config_context | map(attribute='_utility.dns') | flatten | unique | sort }}"
旁注
- name: Print var loop
vars:
- nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
debug:
msg:
- "{{ item }}"
loop: nameservers
这个任务中的三个问题。
- 虽然它实际上与列表“一起工作”(ansible 会自动转换),但您的
vars
声明应该是一个映射:
vars:
nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
- 您正在遍历 字符串
"nameservers"
。您想要遍历具有该名称的变量的内容:
loop: "{{ nameservers }}"
- 在您的调试消息中,您要求打印一个列表,其中第一个元素内容是
item
变量中的任何值。您真正想要的是直接打印该变量的内容,这可以通过
debug:
msg: "{{ item }}"
或者因为您没有通过直接寻址 var 对内容进行任何处理
debug:
var: item
把它们放在一起并整合我上面的修复,这是你问题的核心:
- name: Print var loop
vars:
nameservers: "{{ config_context | map(attribute='_utility.dns') | flatten | unique | sort }}"
debug:
var: item
loop: "{{ nameservers }}"
一些背景信息。我正在使用 netbox 作为我们网络自动化的真实来源,我目前正在做一些测试以自动化瞻博网络配置。 Netbox 目前用作我的 ansible 库存并提供 host_vars.
我想完成一个简单的任务,即根据主机变量在我的 Juniper 配置中设置一个“值”。
问题
我最明确地使用了错误的 map/filter 组合来实现循环遍历字典“dns”中的值的目标,但我已经尝试了无数次但没有任何成功,所以将我的问题提交给社区征求意见。
我有以下 host_vars:
{
"ansible_host": "192.168.1.1",
"config_context": [
{
"_utility": {
"dns": [
"10.10.10.10",
"10.10.10.20"
]
}
}
],
"device_roles": [
"leaf"
],
"device_types": [
"qfx5120-48y"
]
}
我的任务目前看起来像:
- name: Set DNS server
juniper.device.config:
config_mode: 'exclusive'
load: 'set'
lines:
- 'set system name-server "{{ item }}"'
loop: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
发出错误信息
尝试调试它注册一个变量并使用调试消息打印它:
调试
- name: Print var
vars:
- nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
debug:
msg:
- "{{ nameservers }}"
结果
ok: [poc-spine01-re] => {
"msg": [
[
"10.10.10.10",
"10.10.10.20"
]
]
}
但是,当尝试使用结果循环遍历值时,我得到另一个错误
调试
- name: Print var loop
vars:
- nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
debug:
msg:
- "{{ item }}"
loop: nameservers
结果
fatal: [poc-leaf03-re]: FAILED! => {
"msg": "Invalid data passed to 'loop', it requires a list, got this instead: nameservers. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."
}
fatal: [poc-spine01-re]: FAILED! => {
"msg": "Invalid data passed to 'loop', it requires a list, got this instead: nameservers. Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."
}
更新
嗨,它适用于循环!。我已经调整了我的变量,现在正在考虑是否应该只获取密钥 dns1 或 dns2 的值(不在循环中)
主机变量
{
"ansible_host": "192.168.1.1",
"config_context": [
{
"_utility": {
"dns": {
"dns1": "10.10.10.10",
"dns2": "10.10.10.20"
}
}
}
],
"device_roles": [
"leaf"
],
"device_types": [
"qfx5120-48y"
]
}
但无法让地图过滤器正确显示一个值
任务
- name: Set DNS server
vars:
ns1: "{{ config_context | map(attribute='_utility.dns.dns1') | flatten }}"
juniper.device.config:
config_mode: 'exclusive'
load: 'set'
lines:
- 'set system name-server "{{ ns1 }}"'
结果
如您所见,10.10.10.10 的值用方括号和双引号引起来,而不仅仅是 10.10.10.10
的值字符串fatal: [poc-spine01-re]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"lines": [
"set system name-server \"['10.10.10.10']\""
],
你的循环应该修复如下:
loop: "{{ config_context | map(attribute='_utility.dns') | flatten }}"
此外,我会添加一些额外的过滤器以确保:
- 如果在多个
config_context
条目(即unique
)中声明同一个 dns,则您不会循环两次 - 你总是以相同的顺序去其他列表(即
sort
)
loop: "{{ config_context | map(attribute='_utility.dns') | flatten | unique | sort }}"
旁注
- name: Print var loop vars: - nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}" debug: msg: - "{{ item }}" loop: nameservers
这个任务中的三个问题。
- 虽然它实际上与列表“一起工作”(ansible 会自动转换),但您的
vars
声明应该是一个映射:vars: nameservers: "{{ config_context | map(attribute='_utility') | flatten | map(attribute='dns') | flatten }}"
- 您正在遍历 字符串
"nameservers"
。您想要遍历具有该名称的变量的内容:loop: "{{ nameservers }}"
- 在您的调试消息中,您要求打印一个列表,其中第一个元素内容是
item
变量中的任何值。您真正想要的是直接打印该变量的内容,这可以通过
或者因为您没有通过直接寻址 var 对内容进行任何处理debug: msg: "{{ item }}"
debug: var: item
把它们放在一起并整合我上面的修复,这是你问题的核心:
- name: Print var loop
vars:
nameservers: "{{ config_context | map(attribute='_utility.dns') | flatten | unique | sort }}"
debug:
var: item
loop: "{{ nameservers }}"