如何将 jinja2 变量传递给 json_query
How to pass jinja2 variable to json_query
我有以下 jinja2 模板
[
{% for items in hosts %}
{
"name":"{{ items.name }}",
"display_name":"{{ items.display_name }}",
"services": {{ host_group | from_json | json_query('[*].services[0]') | to_json }},
}
{% endfor %}
]
我需要用变量 {{ loop.index0 }} 替换 services[0],我试过这个语法
"services": {{ host_group | from_json | json_query('[*].services[loop.index0]') | to_json }}
但我遇到了一个错误:
AnsibleFilterError: JMESPathError in json_query filter plugin:
Expecting: star, got: unquoted_identifier: Parse error at column 13, token "loop" (UNQUOTED_IDENTIFIER), for expression:
"[*].services[loop.index0]"
我尝试了另一种语法:
"services": {{ host_group | from_json | json_query('[*].services[' + {{ loop.index0 }} +']') | to_json }},
它也给出了一个错误:
AnsibleError: template error while templating string: expected token ':', got '}'. String: [
使用 Jinja 时需要注意两点:
- 您永远不会嵌套
{{...}}
模板标记。
- 如果你把一些东西放在引号里,它就是一个文字字符串。
所以当你写的时候:
json_query('[*].services[loop.index0]')
您正在传递 json_query
文字字符串 [*].services[loop.index0]
,这不是有效的 JMESPath 查询。如果要替换字符串中变量的值,则需要通过连接构建字符串,或使用字符串格式化逻辑。
串联
使用串联可能如下所示:
json_query('[*].services[' ~ loop.index0 ` ']')
这里,~
是字符串连接运算符——它类似于 +
,但它确保将所有内容都转换为字符串。比较这个:
ansible localhost -m debug -a 'msg={{ "there are " + 4 + " lights" }}'
为此:
ansible localhost -m debug -a 'msg={{ "there are " ~ 4 ~ " lights" }}'
字符串格式
使用字符串格式可能如下所示:
json_query('[*].services[%s]' % (loop.index0))
或:
json_query('[*].services[{}]'.format(loop.index0))
这是 Python 中可用的两种字符串格式;更多详情,开始here.
使用 Ansible 2.9.23
.
对于字符串占位符 {}
和 %s
我必须使用反引号,否则它不起作用:
json_query('results[?name==`{}`].version'.format(query))
json_query('results[?name==`%s`].version' % (query))
举个例子json:
{
(...)
"results": [
{
"envra": "0:ntp-4.2.6p5-29.el7_8.2.x86_64",
"name": "ntp",
"repo": "installed",
"epoch": "0",
"version": "4.2.6p5",
"release": "29.el7_8.2",
"yumstate": "installed",
"arch": "x86_64"
},
(...)
],
(...)
}
创建者:
- name: list installed packages
yum:
list: installed
register: installed_list
使用定义的变量query: ntp
,通过两种方式将此变量传递给json_query
:
- name: pass var to json_query - string formatting (1)
debug:
msg: "{{ installed_list|json_query('results[?name==`{}`].version'.format(query))|first }}"
- name: pass var to json_query - string formatting (2)
debug:
msg: "{{ installed_list|json_query('results[?name==`%s`].version' % (query))|first }}"
结果:
TASK [pass var to json_query - string formatting (1)] *****************************************************************************************************
ok: [host] => {
"msg": "4.2.6p5"
}
TASK [pass var to json_query - string formatting (2)] *****************************************************************************************************
ok: [host] => {
"msg": "4.2.6p5"
}
我有以下 jinja2 模板
[
{% for items in hosts %}
{
"name":"{{ items.name }}",
"display_name":"{{ items.display_name }}",
"services": {{ host_group | from_json | json_query('[*].services[0]') | to_json }},
}
{% endfor %}
]
我需要用变量 {{ loop.index0 }} 替换 services[0],我试过这个语法
"services": {{ host_group | from_json | json_query('[*].services[loop.index0]') | to_json }}
但我遇到了一个错误:
AnsibleFilterError: JMESPathError in json_query filter plugin:
Expecting: star, got: unquoted_identifier: Parse error at column 13, token "loop" (UNQUOTED_IDENTIFIER), for expression:
"[*].services[loop.index0]"
我尝试了另一种语法:
"services": {{ host_group | from_json | json_query('[*].services[' + {{ loop.index0 }} +']') | to_json }},
它也给出了一个错误:
AnsibleError: template error while templating string: expected token ':', got '}'. String: [
使用 Jinja 时需要注意两点:
- 您永远不会嵌套
{{...}}
模板标记。 - 如果你把一些东西放在引号里,它就是一个文字字符串。
所以当你写的时候:
json_query('[*].services[loop.index0]')
您正在传递 json_query
文字字符串 [*].services[loop.index0]
,这不是有效的 JMESPath 查询。如果要替换字符串中变量的值,则需要通过连接构建字符串,或使用字符串格式化逻辑。
串联
使用串联可能如下所示:
json_query('[*].services[' ~ loop.index0 ` ']')
这里,~
是字符串连接运算符——它类似于 +
,但它确保将所有内容都转换为字符串。比较这个:
ansible localhost -m debug -a 'msg={{ "there are " + 4 + " lights" }}'
为此:
ansible localhost -m debug -a 'msg={{ "there are " ~ 4 ~ " lights" }}'
字符串格式
使用字符串格式可能如下所示:
json_query('[*].services[%s]' % (loop.index0))
或:
json_query('[*].services[{}]'.format(loop.index0))
这是 Python 中可用的两种字符串格式;更多详情,开始here.
使用 Ansible 2.9.23
.
对于字符串占位符 {}
和 %s
我必须使用反引号,否则它不起作用:
json_query('results[?name==`{}`].version'.format(query))
json_query('results[?name==`%s`].version' % (query))
举个例子json:
{
(...)
"results": [
{
"envra": "0:ntp-4.2.6p5-29.el7_8.2.x86_64",
"name": "ntp",
"repo": "installed",
"epoch": "0",
"version": "4.2.6p5",
"release": "29.el7_8.2",
"yumstate": "installed",
"arch": "x86_64"
},
(...)
],
(...)
}
创建者:
- name: list installed packages
yum:
list: installed
register: installed_list
使用定义的变量query: ntp
,通过两种方式将此变量传递给json_query
:
- name: pass var to json_query - string formatting (1)
debug:
msg: "{{ installed_list|json_query('results[?name==`{}`].version'.format(query))|first }}"
- name: pass var to json_query - string formatting (2)
debug:
msg: "{{ installed_list|json_query('results[?name==`%s`].version' % (query))|first }}"
结果:
TASK [pass var to json_query - string formatting (1)] *****************************************************************************************************
ok: [host] => {
"msg": "4.2.6p5"
}
TASK [pass var to json_query - string formatting (2)] *****************************************************************************************************
ok: [host] => {
"msg": "4.2.6p5"
}