Ansible:使用 JMESPath 过滤包含字符串的元素 [英] Ansible : filter elements containing string with JMESPath

查看:28
本文介绍了Ansible:使用 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 使用自己的字符串类型这一事实有关:AnsibleUnicodeAnsibleUnsafeText.而且只要 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 and AnsibleUnsafeText. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆