Ansible中如何让when条件匹配首个符合项后停止循环?
Ansible循环匹配首个符合条件项避免重复分配磁盘号的解决方法
问题根因
原有实现会遍历jsondata的所有项,只要容量匹配就会赋值disknumber,相同容量的未分配项都会被匹配到,导致重复分配。
解决方法
方案1:直接筛选首个未分配的匹配项(推荐,无需循环)
直接通过Jinja2过滤器筛选出还未分配disknumber、且容量匹配当前磁盘的第一个项,直接赋值即可,不会出现重复匹配的问题。
初始状态下jsondata的值是容量字符串,分配后会变为带disknumber的字典,因此通过
selectattr('value', 'string')即可筛选出所有未分配的项,再取第一个容量匹配的项即可。
- name: Convert 1st disk size info and appending to jsondata vars: disk: '{{ ansible_facts.disks[1] }}' disksize_1_gib: '{{ (disk.size/1024|pow(3))|round|int }}GB' # 筛选未分配、容量匹配的第一个项 matched_item: "{{ jsondata | dict2items | selectattr('value', 'string') | selectattr('value', 'equalto', disksize_1_gib) | first | default([]) }}" set_fact: jsondata: "{{ jsondata | combine({matched_item.key: {'disknumber': '1'}}, recursive=true) }}" when: matched_item | length > 0
方案2:循环匹配到首个项后终止
如果你需要保留循环的写法,可以新增一个匹配标记变量,匹配到第一个符合条件的项后将标记置为真,后续循环会自动跳过:
- name: Convert 1st disk size info and appending to jsondata vars: disk: '{{ ansible_facts.disks[1] }}' disksize_1_gib: '{{ (disk.size/1024|pow(3))|round|int }}GB' matched: false set_fact: jsondata: "{{ jsondata | combine({item.key: {'disknumber': '1'}}, recursive=true) }}" matched: true when: not matched and item.value is string and item.value == disksize_1_gib loop: "{{ jsondata | dict2items }}"
优化建议
不需要为每块磁盘单独写重复任务,可以直接遍历所有磁盘批量处理,减少冗余代码:
- name: 批量为所有磁盘匹配存储项 vars: disksize_gib: '{{ (item.1.size/1024|pow(3))|round|int }}GB' matched_item: "{{ jsondata | dict2items | selectattr('value', 'string') | selectattr('value', 'equalto', disksize_gib) | first | default([]) }}" set_fact: jsondata: "{{ jsondata | combine({matched_item.key: {'disknumber': (item.0 + 1)|string}}, recursive=true) }}" when: matched_item | length > 0 loop: "{{ ansible_facts.disks | enumerate | list }}" loop_control: label: "磁盘{{ item.0 + 1 }}容量:{{ disksize_gib }}"
内容的提问来源于stack exchange,提问作者Fendder
相关产品推荐
相关产品推荐

