Ansible

在循環內過濾的 Ansible 條件

  • April 12, 2022

當 scsi_controller 值不為零時,我正在嘗試創建一個 Ansible 任務以從 VM 中刪除 RDM 磁碟。但是,when條件是跳過整個任務,而不是遍歷循環並僅跳過值為 0 的 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 多個小時。

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

然後,迭代with_subelements

   - 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,
       }

現在,創建一個屬性列表 ( _keys ),提取字元串,拆分項目,並加入過濾器zip2的參數。然後從所有*_keys創建選擇*。例如,給定用於測試的簡化數據

 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

引用自:https://serverfault.com/questions/1097567