Вложенный список обновления Ansible

Я работаю над недоступной задачей, которая будет обновлять вложенный список в списке. Вход:

- name: test array of objects
  set_fact:
    list: 
       - name: x1
         surname: y1
         childrens: 
            - children1
            - children2
       - name: x2
         surname: y2
         childrens: 
            - children3
            - children4

Например, я хочу добавить новых дочерних элементов к / удалить существующих дочерних элементов объекта с параметрами

name: x1
surname: y1

Пример вывода (добавлены дети):

- name: test array of objects
  set_fact:
    list: 
       - name: x1
         surname: y1
         childrens: 
            - children1
            - children2
            - children3
       - name: x2
         surname: y2
         childrens: 
            - children3
            - children4

Задача обработает 1000+ записей и должна делать это эффективно.

Спасибо!


person Daniel Kruk    schedule 07.06.2021    source источник
comment
Отвечает ли это на ваш вопрос? Как обновить вложенные переменные в Ansible   -  person mdaniel    schedule 07.06.2021
comment
Привет, Даниэль Крук, добро пожаловать в SO. Вы захотите использовать здесь функцию поиска, потому что количество новых проблем в доступе на самом деле довольно маленький   -  person mdaniel    schedule 07.06.2021
comment
уже ответьте здесь stackoverflow.com/questions/54347555 /   -  person Mirco    schedule 07.06.2021
comment
@Mirco, сколько времени потребовалось, чтобы зациклить и объединить 1000 элементов?   -  person Vladimir Botka    schedule 07.06.2021


Ответы (1)


Добавьте index. Например, полное имя

    - set_fact:
        list: "{{ _list|from_yaml }}"
      vars:
        _list: |
          {% for i in range(3) %}
          - name: x{{ i }}
            surname: y{{ i }}
            fullname: x{{ i }}_y{{ i }}
            index: {{ i }}
            childrens:
              - children1
              - children2
          {% endfor %}

дает

  list:
    - childrens: [children1, children2]
      fullname: x0_y0
      index: 0
      name: x0
      surname: y0
    - childrens: [children1, children2]
      fullname: x1_y1
      index: 1
      name: x1
      surname: y1
    - childrens: [children1, children2]
      fullname: x2_y2
      index: 2
      name: x2
      surname: y2

Затем преобразуйте список в словарь, например

    - set_fact:
        dict: "{{ list|items2dict(key_name='fullname', value_name='childrens') }}"

дает

  dict:
    x0_y0: [children1, children2]
    x1_y1: [children1, children2]
    x2_y2: [children1, children2]

Обновите элементы словаря, например

    - set_fact:
        dict: "{{ dict|combine({item.fullname: _children}) }}"
      loop:
        - {fullname: x1_y1, add: [children3]}
      vars:
        _children: "{{ dict[item.fullname] + item.add }}"

дает

  dict:
    x0_y0: [children1, children2]
    x1_y1: [children1, children2, children3]
    x2_y2: [children1, children2]

Восстановить список из словаря

    - set_fact:
        list2: "{{ dict|dict2items(key_name='fullname', value_name='childrens') }}"

дает

  list2:
    - childrens: [children1, children2]
      fullname: x0_y0
    - childrens: [children1, children2, children3]
      fullname: x1_y1
    - childrens: [children1, children2]
      fullname: x2_y2

Таким образом, создание 1000 элементов и обновление некоторых из них займет всего пару секунд. Например


    - set_fact:
        list: "{{ _list|from_yaml }}"
      vars:
        _list: |
          {% for i in range(1000) %}
      ...

    - set_fact:
        dict: "{{ dict|combine({item.fullname: _children}) }}"
      loop:
        - {fullname: x101_y101, add: [children3]}
        - {fullname: x301_y301, add: [children3]}
        - {fullname: x501_y501, add: [children3]}
      ...

    - debug:
        msg: |
          {{ list2.100 }}
          {{ list2.101 }}
          {{ list2.102 }}
          {{ list2|length }}

дает

  msg: |-
    {'fullname': 'x100_y100', 'childrens': ['children1', 'children2']}
    {'fullname': 'x101_y101', 'childrens': ['children1', 'children2', 'children3']}
    {'fullname': 'x102_y102', 'childrens': ['children1', 'children2']}
    1000

Используйте lists_mergeby, чтобы объединить все элементы, например

    - set_fact:
        list3: "{{ list|
                   community.general.lists_mergeby(list2, 'fullname')|
                   sort(attribute='index') }}"
person Vladimir Botka    schedule 07.06.2021