Ansible:迭代字典中的列表作为条件

Ansible: iterate over a list in dictionary as condition

我创建了一个角色来创建 LVM VG(s) 并使其完全幂等和故障证明我想验证 PV(s) 存在并且 VG 尚未定义。

roles/lvm/vars/main.yml

---
lvm_vgs:
  - vg_name: drbdpool
    vg_pvs: "{{ vg_drbdpool_pvs }}"

host_vars/hostname

---
vg_drbdpool_pvs: ['sdc1', 'sdd1']

roles/lvm/tasks/main.yml

- name: Create LVM VG(s)
  lvg:
    vg: "{{ item.vg_name }}"
    pvs: "{% for disk in item.vg_pvs %}/dev/{{ disk }}{% if not loop.last %},{% endif %}{% endfor %}"
    state: present
  when:
    - item.vg_name not in ansible_lvm.vgs
    - "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}"
  with_items: "{{ lvm_vgs }}"

为了实现这一点,我添加了条件 "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}",但它不起作用,而且我总是收到以下错误:

TASK [lvm : Create LVM VG(s)] **************************************************
fatal: [hostname]: FAILED! => {"failed": true, "msg": "The conditional check '{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}' failed. The error was: unexpected '.'\n line 1\n\nThe error appears to have been in '/etc/ansible/roles/lvm/tasks/main.yml': line 80, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Create LVM VG(s)\n ^ here\n"}

如何验证 PV(分区)是否存在?

Ansible 假设 when 的参数是一个简单的 Jinja2 表达式(它隐式地添加了 {{ }} 大括号),所以你不能在里面使用语句 {% ... %} .

解决方法是在任务中定义一个变量,并使用变量名作为条件:

- name: Create LVM VG(s)
  lvg:
    vg: "{{ item.vg_name }}"
    pvs: "{% for disk in item.vg_pvs %}/dev/{{ disk }}{% if not loop.last %},{% endif %}{% endfor %}"
    state: present
  when:
    - item.vg_name not in ansible_lvm.vgs
    - partition_exists
  with_items: "{{ lvm_vgs }}"
  vars:
    partition_exists: "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% endfor %}"

我没法测试你的实际情况,所以我原封不动。

techraf's 把我带到了解决方案。

- name: Create LVM VG(s)
  lvg:
    vg: "{{ item.vg_name }}"
    pvs: "{% for disk in item.vg_pvs %}/dev/{{ disk }}{% if not loop.last %},{% endif %}{% endfor %}"
    state: present
  when:
    - item.vg_name not in ansible_lvm.vgs
    - partition_exists.split(';')
  with_items: "{{ lvm_vgs }}"
  vars:
    partition_exists: "{% for disk in item.vg_pvs %}ansible_devices[{{ disk | truncate(-1) }}]['partitions']{{ disk }} is defined{% if not loop.last %};{% endif %}{% endfor %}"
  tags: ['storage', 'lvm']

由于item.vg_pvs可能有多个元素,变量partition_exists需要创建为列表。