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

能否在Ansible的defaults/main.yml中循环生成值列表?

问题

我有自定义的inventory数据结构和角色输入参数,想从inventory数据结构填充这些输入参数,请问能不能通过循环生成列表?

示例inventory结构如下:

---
install_disk:
  vtbd0:
    scheme: GPT
    target: bsdinstall
    partitions:
      1:
        size: 512k
        type: freebsd-boot
        gptlabel: CSMBOOT
      2:
        size: 55m
        type: efi
        gptlabel: EFIBOOT
        fslabel: efiprtn
      3:
        size: 3g
        type: freebsd-ufs
        gptlabel: UFSBOOT
        fslabel: ufsprtn
      4:
        type: freebsd-zfs
        gptlabel: ZFSMAIN
        poolname: zpool
        ashift: 12
        swapsize: 6G
        mountdir: /tmp/newbsd
        geli:
          algo: AES-XTS
          length: 256
          sector: 4096
          keyfile: zpool.key
          keydir: geli
          keypath: /usr/local
          keycount: 3

我当前手动生成列表第一个元素的写法如下:

---
target_dsk:
  dev_name: "{{ install_disk.keys() | first }}"
  prt_scheme: "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','scheme') | map(attribute='value') | first }}"
  prt_list:
    - index:  "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute='value') | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute='key') | first }}"
      type: "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute='value') | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute='value.type') | first }}"
      gptlabel:  "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute='value') | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute='value.gptlabel') | first }}"
      size:  "{{ install_disk.values() | first | dict2items | selectattr('key', 'equalto','partitions') | map(attribute='value') | first | dict2items | selectattr('key', 'equalto',1) |  map(attribute='value.size') | first }}"

我觉得当前写法不够优化,想找更优的列表推导方式,同时想知道能不能通过循环生成列表元素,避免在defaults/main.yml中硬编码列表元素数量。我试过直接用字典,但不符合我的数据抽象需求。

优化方案

完全可以通过循环自动生成列表元素,无需硬编码分区数量。用Ansible的Jinja2循环语法就能实现,以下是两种优化写法:

写法一:原生YAML列表生成

直接在变量中通过Jinja2循环遍历分区,生成符合要求的列表结构:

---
target_dsk:
  # 简化磁盘名称获取
  dev_name: "{{ install_disk.keys() | first }}"
  # 直接访问磁盘的scheme属性,替代冗长过滤链
  prt_scheme: "{{ install_disk[dev_name].scheme }}"
  # 自动遍历所有分区生成列表
  prt_list:
    {% set disk = install_disk[dev_name] %}
    {% set partitions = disk.partitions | dict2items | sort(attribute='key') %}
    {%- for part in partitions %}
    - index: "{{ part.key }}"
      type: "{{ part.value.type }}"
      gptlabel: "{{ part.value.gptlabel | default('') }}"
      size: "{{ part.value.size | default('') }}"
    {%- endfor %}

写法二:模板字符串转YAML(适合复杂场景)

如果分区逻辑更复杂,可以用模板字符串生成后转成YAML列表:

---
target_dsk:
  dev_name: "{{ install_disk.keys() | first }}"
  prt_scheme: "{{ install_disk[dev_name].scheme }}"
  prt_list: "{{ lookup('template', 'partitions.j2') | from_yaml }}"

对应的partitions.j2模板内容:

{% set disk = install_disk[install_disk.keys() | first] %}
{% set partitions = disk.partitions | dict2items | sort(attribute='key') %}
[
{%- for part in partitions %}
  {
    "index": "{{ part.key }}",
    "type": "{{ part.value.type }}",
    "gptlabel": "{{ part.value.gptlabel | default('') }}",
    "size": "{{ part.value.size | default('') }}"
  }{%- if not loop.last %},{% endif %}
{%- endfor %}
]

优化亮点

  • 简化属性访问:直接通过install_disk[dev_name].scheme获取分区方案,可读性大幅提升。
  • 自动适配分区数量:不管inventory中有多少个分区,循环都会自动生成对应列表元素,彻底避免硬编码。
  • 兼容可选字段:用default('')处理size这类可能缺失的字段,防止出现未定义错误。
  • 保持数据抽象:生成的列表结构完全符合你的需求,不会像直接用字典那样破坏抽象逻辑。

内容的提问来源于stack exchange,提问作者X bl lJJ H i K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 03:02:49