Ansible:如何更简洁使用with_items及复用循环逻辑?
关于Ansible Playbook循环优化的问题
测试用Playbook
--- - name: Playbook hosts: localhost become: false gather_facts: false vars: plugins: - name: diff enabled: true dependencies: - python3-jsonpatch - python3-kubernetes repository: name: helm-diff org: databus23 version: v3.9.6 - name: git enabled: false repository: name: helm-git org: aslafy-z version: v0.16.0 tasks: - name: Loop block: - name: 列出插件名称 ansible.builtin.debug: msg: '{{ item.name }}' when: item.enabled with_items: '{{ plugins }}' - name: 列出依赖项 ansible.builtin.debug: msg: '{{ item }}' with_items: "{{ plugins | selectattr('enabled', 'eq', true) | selectattr('dependencies', 'defined') | map(attribute='dependencies') }}"
预期执行结果
TASK [列出插件名称] *** ok: [localhost] => (item={'name': 'diff', 'enabled': True, 'dependencies': ['python3-jsonpatch', 'python3-kubernetes'], 'repository': {'name': 'helm-diff', 'org': 'databus23'}, 'version': 'v3.9.6'}) => msg: diff TASK [列出依赖项] *** ok: [localhost] => (item=python3-jsonpatch) => msg: python3-jsonpatch ok: [localhost] => (item=python3-kubernetes) => msg: python3-kubernetes
问题
- 有没有更简洁的方式编写第二个任务的
with_items,像第一个任务那样结合when条件? - 多个任务用到相同循环时,能不能把它们归到同一个循环下执行?
最终采用的简洁写法
tasks: - name: Loop block: - name: 列出插件名称 ansible.builtin.debug: msg: '{{ item.name }}' loop: "{{ plugins }}" when: item.enabled - name: 列出依赖项 ansible.builtin.debug: msg: '{{ item.dependencies }}' loop: '{{ plugins }}' when: - item.enabled - item.dependencies is defined
解答
第二个任务的简化写法
完全可以采用你最终的写法:用loop遍历所有plugins,再通过when条件过滤出已启用且包含依赖项的插件。这种写法比原有的过滤器链更直观易读,还和第一个任务的逻辑保持一致,后续维护更方便。
如果需要和原执行结果一样逐个输出依赖项,可以在任务里嵌套一层循环:
- name: 列出依赖项 ansible.builtin.debug: msg: '{{ dep }}' loop: "{{ plugins }}" when: - item.enabled - item.dependencies is defined loop_control: loop_var: item with_subelements: - "{{ plugins | selectattr('enabled', 'eq', true) | selectattr('dependencies', 'defined') }}" - dependencies
不过你最终的写法已经足够简洁,能覆盖大多数场景。
多个任务归到同一循环
可以把多个任务放到同一个loop下的block中,这样只需要遍历一次plugins,就能对每个符合条件的插件执行多步操作,示例如下:
- name: 处理已启用的插件 loop: "{{ plugins }}" when: item.enabled block: - name: 打印插件名称 ansible.builtin.debug: msg: '{{ item.name }}' - name: 打印插件依赖项 ansible.builtin.debug: msg: '{{ dep }}' loop: "{{ item.dependencies | default([]) }}" loop_control: loop_var: dep when: item.dependencies is defined
这种写法的好处是减少遍历次数,当plugins数量较多时能提升效率,同时逻辑更连贯,所有针对单个插件的操作都集中在一起。
内容的提问来源于stack exchange,提问作者Floren
相关产品推荐
相关产品推荐

