使用 JMESPath 过滤包含字符串的元素

moo*_*oky 5 ansible jmespath json-query

我想获取已定义接口类型的地址列表。我在这里
找到了一些信息。

这是我的剧本:

- 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
Run Code Online (Sandbox Code Playgroud)

我想得到:

[
  "10.112.171.81/28",
  "10.112.171.65/28",
  "10.112.171.97/28"
]
Run Code Online (Sandbox Code Playgroud)

它可以在 JMESPath 网站上运行,但我的剧本失败了:

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
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下为什么吗?

β.ε*_*.βε 4

对于您遇到的 JMESPath 问题,此处进行了解释:

该问题与 Ansible 使用自己的字符串类型有关:AnsibleUnicodeAnsibleUnsafeText。只要 jmespath 库具有非常严格的类型检查,它就无法接受这种类型作为字符串文字。

来源:https ://github.com/ansible/ansible/issues/27299#issuecomment-331068246


正如同一期中所解释的,使其工作的技巧是使用to_json | from_json过滤器对,以强制返回正确的类型。

所以,任务:

- 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
Run Code Online (Sandbox Code Playgroud)

给出预期的:

ok: [localhost] => 
  msg:
  - 10.112.171.81/28
  - 10.112.171.65/28
  - 10.112.171.97/28
Run Code Online (Sandbox Code Playgroud)