You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题

  1. 有没有更简洁的方式编写第二个任务的with_items,像第一个任务那样结合when条件?
  2. 多个任务用到相同循环时,能不能把它们归到同一个循环下执行?

最终采用的简洁写法

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 23:05:15