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

Ansible循环set_fact追加列表仅保留最后一项值如何解决

Ansible循环拼接多YAML文件列表仅保留最后值的解决方法

问题场景

需求为拼接2个及以上YAML文件中的列表内容,示例文件:

  • file1.yml
test:
  - start1
  - begin1
  - middle1
  - end1
  • file2.yml
test:
  - start2
  - begin2
  - middle2
  - end2

目标是调用role时可传入所有文件内test列表的全部值。

异常表现

初始实现代码:

- name: 拼接test列表
  set_fact:
    mytests: "{{ mytests|d([]) + (lookup('file', item)|from_yaml).test }}"
  loop: "{{ query('fileglob', 'test_suites/QS_suite/*.yml') }}"

- name: 输出结果
  debug: var=mytests

运行后mytests始终仅包含最后一个文件的列表值,执行日志显示第一次循环赋值为file1的内容,第二次循环直接覆盖为file2的内容,没有累加。
做最小复现:仅收集匹配到的文件路径到列表,代码如下:

- name: 收集文件路径
  set_fact:
    myfiles: "{{myfiles|d([]) + [item] }}"
  with_fileglob:
    - 'test_suites/QS_suite/*.yml'
- name: 输出文件列表
  debug: var=myfiles

执行后第二个文件路径同样无法追加到列表,仅保留最后一个匹配到的文件路径。

根本原因

Ansible默认在单任务的循环执行过程中,不会将同任务上一轮循环设置的fact值注入下一轮的变量计算上下文。每轮循环计算mytests|d([])时,读取到的都是任务启动前的初始变量状态(即未定义,被默认值过滤器替换为空列表),因此每轮赋值都是覆盖操作,最终仅保留最后一轮循环的结果。

解决方法

方法1:开启set_fact的可缓存参数(Ansible 2.8+适用)

给set_fact添加cacheable: true参数,让每轮循环设置的fact立即写入主机事实缓存,下一轮循环计算时即可读取到之前累加的结果:

- name: 拼接test列表
  set_fact:
    mytests: "{{ mytests|d([]) + (lookup('file', item)|from_yaml).test }}"
    cacheable: true
  loop: "{{ query('fileglob', 'test_suites/QS_suite/*.yml') }}"

方法2:一次性批量合并(全版本兼容,推荐)

不通过循环逐次累加,直接用过滤器链批量完成文件读取、格式转换、字段提取、列表合并全流程,从根源上避免循环上下文的问题:

- name: 一次性合并所有文件的test列表
  set_fact:
    mytests: "{{ query('fileglob', 'test_suites/QS_suite/*.yml') | map('lookup', 'file') | map('from_yaml') | map(attribute='test') | flatten }}"

代码逻辑说明:

  • 先用query('fileglob')获取所有匹配的yml文件路径列表
  • 用map('lookup', 'file')批量读取每个文件的文本内容
  • 用map('from_yaml')把所有文本内容解析为YAML结构化数据
  • 用map(attribute='test')提取每个YAML对象下的test列表
  • 用flatten把嵌套的多层列表拍平为单个一维列表

预期结果

两种方法修改后,执行debug输出的mytests结果为两个文件列表的完整拼接:

mytests:
  - start1
  - begin1
  - middle1
  - end1
  - start2
  - begin2
  - middle2
  - end2

内容的提问来源于stack exchange,提问作者AEngineer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:06:28