Ansible:使用 JMESPath 过滤包含字符串的元素 [英] Ansible : filter elements containing string with JMESPath
问题描述
我想获取已定义接口类型的地址列表.
我在这里找到了一些信息.
这是我的剧本:
- 名称:测试 JMESPath主机:本地主机收集事实:没有变量:接口:- 名称:em0地址:10.127.37.89/29- 名称:bge0地址:10.112.171.81/28- 名称:bge1地址:10.112.171.65/28- 名称:bge2地址:10.112.171.97/28任务:- 名称:JMESPath 查询设置事实:结果:"{{接口|json_query(query) }}"变量:查询:[?name.contains(@, 'bge')].address";- 调试:变量:结果
我想得到:
[10.112.171.81/28",10.112.171.65/28",10.112.171.97/28"]
它适用于 JMESPath 网站,但我的剧本失败了:
<块引用>ansible-playbook play-testJMESPath.yml [警告]:提供的主机列表为空,只有 localhost 可用.注意隐式本地主机与全部"不匹配播放 [测试 JMESPath]******************************************************************************************************************************************************************************************************************任务 [JMESPath 查询]************************************************************************************************************************************************************************************************************** 致命:[本地主机]:失败!=>{msg":json_query 中的 JMESPathError过滤器插件:\n在函数 contains() 中,值的类型无效:外部,预期之一:['array', 'string'],收到:\"未知\""}播放回顾**************************************************************************************************************************************************************************************************************************** 本地主机:ok=0 已更改=0 无法访问=0失败=1 跳过=0 获救=0 忽略=0
谁能解释一下为什么?
对于您看到的 JMESPath 问题,这里解释如下:
<块引用>问题与 Ansible 使用自己的字符串类型这一事实有关:AnsibleUnicode
和 AnsibleUnsafeText
.而且只要 jmespath 库有非常严格的类型检查,它就无法接受这种类型作为字符串文字.
来源:https://github.com/ansible/ansible/issues/27299#issuecomment-331068246
使其工作的技巧,如同一问题中所述,是使用 to_json |from_json
过滤器对,以强制返回正确的类型.
所以,剧本:
- 主机:本地主机收集事实:没有任务:- 调试:msg: "{{ 接口 |to_json |from_json |json_query(query) }}"变量:查询:[?name.contains(@, 'bge')].address";接口:- 名称:em0地址:10.127.37.89/29- 名称:bge0地址:10.112.171.81/28- 名称:bge1地址:10.112.171.65/28- 名称:bge2地址:10.112.171.97/28
给出预期:
TASK [debug] **************************************************************************************************************好的:[本地主机] =>{味精":[10.112.171.81/28",10.112.171.65/28",10.112.171.97/28"]}播放回顾 ***************************************************************************************************************本地主机:ok=1已更改=0无法访问=0失败=0已跳过=0已获救=0已忽略=0
I want to get a list of addresses of a defined interface type.
I found some info here.
Here is my playbook:
- name: Test JMESPath
hosts: localhost
gather_facts: no
vars:
interfaces:
- name: em0
address: 10.127.37.89/29
- name: bge0
address: 10.112.171.81/28
- name: bge1
address: 10.112.171.65/28
- name: bge2
address: 10.112.171.97/28
tasks:
- name: JMESPath query
set_fact:
result: "{{ interfaces | json_query(query) }}"
vars:
query: "[?name.contains(@, 'bge')].address"
- debug:
var: result
I'd like to get:
[
"10.112.171.81/28",
"10.112.171.65/28",
"10.112.171.97/28"
]
It works on JMESPath website, but my playbook fails :
ansible-playbook play-testJMESPath.yml [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [Test JMESPath] ************************************************************************************************************************************************************************************************** TASK [JMESPath query] ************************************************************************************************************************************************************************************************* fatal: [localhost]: FAILED! => {"msg": "JMESPathError in json_query filter plugin:\nIn function contains(), invalid type for value: external, expected one of: ['array', 'string'], received: \"unknown\""} PLAY RECAP ************************************************************************************************************************************************************************************************************ localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Could someone explain me why?
For the JMESPath issue you are seeing, this is explained here:
The problem is related to the fact that Ansible uses own types for strings:
AnsibleUnicode
andAnsibleUnsafeText
. And as long as jmespath library has very strict type-checking, it fails to accept this types as string literals.
Source: https://github.com/ansible/ansible/issues/27299#issuecomment-331068246
The trick to make it work, as explained in the same issue, is to use a to_json | from_json
filter pair, in order to force back the right type.
So, the playbook:
- hosts: localhost
gather_facts: no
tasks:
- debug:
msg: "{{ interfaces | to_json | from_json | json_query(query) }}"
vars:
query: "[?name.contains(@, 'bge')].address"
interfaces:
- name: em0
address: 10.127.37.89/29
- name: bge0
address: 10.112.171.81/28
- name: bge1
address: 10.112.171.65/28
- name: bge2
address: 10.112.171.97/28
Gives the expected:
TASK [debug] *****************************************************************************************************
ok: [localhost] => {
"msg": [
"10.112.171.81/28",
"10.112.171.65/28",
"10.112.171.97/28"
]
}
PLAY RECAP *******************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这篇关于Ansible:使用 JMESPath 过滤包含字符串的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!