Условие Ansible для фильтрации внутри цикла

Условие Ansible для фильтрации внутри цикла

Я пытаюсь создать задачу Ansible для удаления RDM-дисков из виртуальной машины, когда значение scsi_controller не равно нулю. Однакокогдаусловие пропускает всю задачу, а не проходит по циклу и пропускает только scsi_controller(s) со значением ноль. Я также пробовалwith_nested, что дало худшие результаты.

rdm_info (переменные):

"scsi_controller": "0,0,1,1,1,2,2,3,3,3,3",
"unit_number": "0,1,2,0,1,0,1,0,1,14,15",
"vm_name": "test_vm"
    

Задание по учебнику:

- name: Remove rdm disks
  community.vmware.vmware_guest_disk:
    validate_certs: false
    hostname: '{{ vc_server }}'
    username: '{{ vc_user }}'
    password: '{{ vc_pass }}'
    datacenter: '{{ datacenter_name }}'
    name: '{{ item.0 }}'
    disk:
      - state: absent
        scsi_controller: "{{ item.1 | int }}"
        unit_number: "{{ item.2 | int }}"
        destroy: no     
  loop: "{{ rdm_info | json_query('[*].vm_name') | zip( rdm_info | json_query('[*].scsi_controller') | map('split',','), rdm_info | json_query('[*].unit_number') | map('split',',')) }}"         
  when: item.1 | int != 0  
  delegate_to: localhost
  register: rdms_unmounted

Буду признателен за любую помощь, так как я уже потратил более 20 часов на эту пьесу.

решение1

2 атрибута

Добавить атрибутвыборк пунктам, например

    - set_fact:
        rdm_sel: "{{ rdm_sel|d([]) + [item|combine({'selection': selection})] }}"
      loop: "{{ rdm_info }}"
      vars:
        scsi_controller: "{{ item.scsi_controller.split(',') }}"
        unit_number: "{{ item.unit_number.split(',') }}"
        selection: "{{ scsi_controller|
                       zip(unit_number)|
                       rejectattr('0', 'eq', '0') }}"

дает

  rdm_sel:
    - scsi_controller: 0,0,1,1,1,2,2,3,3,3,3
      selection:
      - ['1', '2']
      - ['1', '0']
      - ['1', '1']
      - ['2', '0']
      - ['2', '1']
      - ['3', '0']
      - ['3', '1']
      - ['3', '14']
      - ['3', '15']
      unit_number: 0,1,2,0,1,0,1,0,1,14,15
      vm_name: test_vm

Затем повторитес_подэлементами

    - debug:
        msg: >-
          name: {{ item.0.vm_name }}
          scsi_controller: {{ item.1.0 }}
          unit_number: {{ item.1.1 }}
      with_subelements:
        - "{{ rdm_sel }}"
        - selection

дает

  msg: 'name: test_vm scsi_controller: 1 unit_number: 2'
  msg: 'name: test_vm scsi_controller: 1 unit_number: 0'
  msg: 'name: test_vm scsi_controller: 1 unit_number: 1'
  msg: 'name: test_vm scsi_controller: 2 unit_number: 0'
  msg: 'name: test_vm scsi_controller: 2 unit_number: 1'
  msg: 'name: test_vm scsi_controller: 3 unit_number: 0'
  msg: 'name: test_vm scsi_controller: 3 unit_number: 1'
  msg: 'name: test_vm scsi_controller: 3 unit_number: 14'
  msg: 'name: test_vm scsi_controller: 3 unit_number: 15'

При желании можно добавить всеединицы

    - set_fact:
        rdm_units: "{{ rdm_units|d([]) + [item|combine({'units': units})] }}"
      loop: "{{ rdm_info }}"
      loop_control:
        label: "{{ item.vm_name }}"
      vars:
        scsi_controller: "{{ item.scsi_controller.split(',') }}"
        unit_number: "{{ item.unit_number.split(',') }}"
        units: "{{ scsi_controller|zip(unit_number) }}"

дает

  rdm_units:
    - scsi_controller: 0,0,1,1,1,2,2,3,3,3,3
      unit_number: 0,1,2,0,1,0,1,0,1,14,15
      units:
      - ['0', '0']
      - ['0', '1']
      - ['1', '2']
      - ['1', '0']
      - ['1', '1']
      - ['2', '0']
      - ['2', '1']
      - ['3', '0']
      - ['3', '1']
      - ['3', '14']
      - ['3', '15']
      vm_name: test_vm

Затем выберите единицы в цикле. Задача ниже дает тот же результат.

    - debug:
        msg: >-
          name: {{ item.0.vm_name }}
          scsi_controller: {{ item.1.0 }}
          unit_number: {{ item.1.1 }}
      with_subelements:
        - "{{ rdm_units }}"
        - units
      when: item.1.0 != '0'

Множественные атрибуты

Ansible не предоставляет вам фильтр для сжатия списка списков. Но вы можете создать очень простой пользовательский фильтр, например

shell> cat filter_plugins/zip2.py
def zip2(l):
    return zip(*l)


class FilterModule(object):
    def filters(self):
        return {
            'zip2': zip2,
        }

Теперь создайте список атрибутов (_ключи),извлекатьструны,расколотьпредметы, иприсоединитьсяаргументы в пользу фильтраzip2. Затем создайтевыборОт всех_ключи. Например, учитывая упрощенные данные для тестирования

  rdm_info:
    - x: 0,2,3
      y: 4,5,6
      z: 7,8,9
      n: A
    - x: 1,0,3
      y: 4,5,6
      z: 7,8,9
      n: B
    - x: 1,2,0
      y: 4,5,6
      z: 7,8,9
      n: C

задача ниже

    - set_fact:
        rdm_sel: "{{ rdm_sel|d([]) + [item|combine({'selection': selection})] }}"
      loop: "{{ rdm_info }}"
      vars:
        _keys: [x, y, z]
        _args: "{{ _keys|map('extract', item)|map('split', ',')|join(',') }}"
        selection: "{{ _args|zip2|rejectattr('0', 'eq', '0') }}"

дает

  rdm_sel:
    - n: A
      selection:
      - ['2', '5', '8']
      - ['3', '6', '9']
      x: 0,2,3
      y: 4,5,6
      z: 7,8,9
    - n: B
      selection:
      - ['1', '4', '7']
      - ['3', '6', '9']
      x: 1,0,3
      y: 4,5,6
      z: 7,8,9
    - n: C
      selection:
      - ['1', '4', '7']
      - ['2', '5', '8']
      x: 1,2,0
      y: 4,5,6
      z: 7,8,9

Связанный контент