Назад | Перейти на главную страницу

ansible / jinja2 отклоняет все элементы из списка dicts с определенным атрибутом

У меня есть список таких слов:

list_of_dicts:
  - name: Item1
  - name: Item2
    type: special
  - name: Item3
  - name: Item4
    type: small

Как видите, не все предметы имеют type атрибут. Контекст: если нет type установлен, это означает, что элемент имеет тип по умолчанию.

Я хотел бы выбрать все предметы, НЕ относящиеся к типу special.

Я пробовал это: list_of_dicts | rejectattr('type', 'equalto', 'special')

К сожалению, это не удается AnsibleUndefinedVariable: 'dict object' has no attribute 'type' ошибка, потому что некоторые элементы не имеют типа.

Как лучше решить эту проблему?

Вы должны использовать rejectattr отклонять предметы, которые type undefined и используйте selectattr для выбора элементов, которые equalto специальный.

{{ list_of_dicts | rejectattr("type", "undefined") | selectattr("type", "equalto", "special") | list }}

редактировать:

Как насчет объединения двух списков, как показано ниже? Не знаю, лучший ли это способ, но он работает.

{{ list_of_dicts | selectattr("type", "undefined") | list }} + {{ list_of_dicts | rejectattr("type", "undefined") | rejectattr("type", "equalto", "special") | list}}

Изменить: на самом деле я не обратил достаточно внимания на последнее изменение существующего ответа от @ranjandas и следующие комментарии. Мое первое решение почти похоже. Думаю, вас больше интересует второй.


Вот 2 разных способа выполнения ваших требований.

  1. Первое решение использует только доступные по умолчанию фильтры: rejectattr вы уже упомянули и его аналог selectattr. Идея состоит в том, чтобы добавить два списка. Первый делается путем выбора всех диктовок, не имеющих type атрибут. Второй делается выбором dict, имеющего type атрибут и отклонение тех, где он равен special.

  2. Для второго решения я использовал json_query фильтр что требует pip install jmespath на контроллере. Как видите ниже, он намного компактнее.

Выбор за вами !

Демо-сценарий:

---
- name: Show not so special items
  hosts: localhost
  gather_facts: false

  vars:
    list_of_dicts:
      - name: Item1
      - name: Item2
        type: special
      - name: Item3
      - name: Item4
        type: small

  tasks:
    - name: Use select/rejectattr
      debug:
        msg: >-
          {{
            (list_of_dicts | selectattr('type', 'undefined') | list)
            +
            (list_of_dicts | selectattr('type', 'defined') | rejectattr('type', 'eq', 'special') | list)
          }}

    - name: Use json_query
      vars:
        query: "[?type != 'special']"
      debug:
        msg: "{{ list_of_dicts | json_query(query) | list }}"

Который дает:

PLAY [Show not so special items] **********************************************************************************************************************************************************************************

TASK [Use select/rejectattr] **************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "name": "Item1"
        },
        {
            "name": "Item3"
        },
        {
            "name": "Item4",
            "type": "small"
        }
    ]
}

TASK [Use json_query] *********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "name": "Item1"
        },
        {
            "name": "Item3"
        },
        {
            "name": "Item4",
            "type": "small"
        }
    ]
}

PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0