Ansible: фильтрующие элементы, содержащие строку с JMESPath

Я хочу получить список адресов определенного типа интерфейса.
Я нашел кое-какую информацию здесь.

Вот моя инструкция:

- 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

Я бы хотел получить:

[
  "10.112.171.81/28",
  "10.112.171.65/28",
  "10.112.171.97/28"
]

Он работает на веб-сайте 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

Может кто-нибудь объяснить мне, почему?


person mooky    schedule 01.12.2020    source источник


Ответы (2)


Здесь объясняется проблема JMESPath, которую вы видите:

Проблема связана с тем, что Ansible использует собственные типы для строк: AnsibleUnicode и AnsibleUnsafeText. И поскольку библиотека jmespath имеет очень строгую проверку типов, она не может принимать эти типы как строковые литералы.

Источник: https://github.com/ansible/ansible/issues/27299#issuecomment-331068246


Уловка, чтобы заставить его работать, как объясняется в той же проблеме, заключается в использовании пары фильтров to_json | from_json, чтобы принудительно вернуть правильный тип.

Итак, пьеса:

- 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

Дает ожидаемое:

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   
person β.εηοιτ.βε    schedule 01.12.2020

фильтры Jinja могут использовать тесты регулярных выражений Python. Это делает их более надежным инструментом по сравнению с JMESPath содержит функцию, которая только < em> возвращает истину, если строка содержит предоставленный аргумент $ search.

Задачи ниже

    - set_fact:
        result: "{{ interfaces|
                    selectattr('name', 'search', 'bge')|
                    map(attribute='address')|
                    list }}"
    - debug:
        var: result

давать

    "result": [
        "10.112.171.81/28",
        "10.112.171.65/28",
        "10.112.171.97/28"
    ]
person Vladimir Botka    schedule 01.12.2020
comment
хорошо, вы также можете использовать атрибут match для selectattr: `` {{interfaces | selectattr ('имя', 'совпадение', '^ bge') | карта (атрибут = 'адрес') | список}} `` ` - person idriss Eliguene; 01.12.2020
comment
Спасибо, может пригодиться - person mooky; 02.12.2020