Condición posible para filtrar dentro del bucle.

Condición posible para filtrar dentro del bucle.

Estoy intentando crear una tarea de Ansible para eliminar discos RDM de una máquina virtual cuando el valor de scsi_controller no es cero. sin embargo, elcuandoLa condición es omitir toda la tarea en lugar de recorrer el ciclo y omitir solo los scsi_controller con valor cero. yo también lo he intentadocon_anidado, que produjo peores resultados.

rdm_info (variables):

"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"
    

Tarea del libro de jugadas:

- 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

Agradecería cualquier ayuda, ya que he invertido más de 20 horas en esta obra.

Respuesta1

2 atributos

Agregar un atributoseleccióna los artículos, por ejemplo

    - 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') }}"

da

  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

Luego, iterarcon_subelementos

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

da

  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'

Opcionalmente, agregue todosunidades

    - 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) }}"

da

  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

Luego, seleccione las unidades en el bucle. La siguiente tarea da el mismo resultado.

    - 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'

Múltiples atributos

Ansible no le proporciona un filtro para comprimir una lista de listas. Pero puedes crear un filtro personalizado muy simple, por ejemplo

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


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

Ahora, cree una lista de los atributos (_llaves),extractolas cuerdas,dividirlos artículos, yunirselos argumentos para el filtrozip2. Luego creaselecciónde todos_llaves. Por ejemplo, dados los datos simplificados para las pruebas.

  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

la tarea a continuación

    - 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') }}"

da

  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

información relacionada