Ansible Playbook中如何动态生成复杂数据实现列表结构转换
Ansible 动态生成嵌套字典列表的实现方案
以下三种方法均基于Ansible内置能力实现,不需要额外安装第三方插件,可直接在Playbook中使用。
方法1:Jinja2 内联循环生成(执行效率最高,优先选用)
直接在变量定义阶段用Jinja2嵌套循环生成目标结构,不需要编写执行任务:
vars: rooms: - room_name: bedroom-1 chairs: 1 - room_name: bedroom-2 chairs: 0 - room_name: bathroom chairs: 0 - room_name: kitchen chairs: 4 # 直接生成目标椅子列表 chair_names: >- [ {% for room in rooms if room.chairs > 0 %} {% for chair_idx in range(1, room.chairs + 1) %} { "chair_name": "{{ room.room_name }}-chair-{{ chair_idx }}", "room_name": "{{ room.room_name }}" }, {% endfor %} {% endfor %} ]
这里用>-折叠符处理多行Jinja2内容,Ansible解析JSON时会自动忽略列表末尾多余的逗号,不需要手动处理格式问题,所有Ansible 2.10及以上版本都能直接运行。
方法2:拆分逻辑分步生成(可读性最好,适合后续扩展)
如果后续还要给椅子条目加其他属性(比如材质、摆放位置),可以把逻辑拆成两个任务,避免嵌套Jinja2过于复杂难以维护:
tasks: - name: 筛选有椅子的房间,生成椅子序号序列 ansible.builtin.set_fact: rooms_with_chair_seq: "{{ rooms_with_chair_seq | default([]) + [ item | combine({'chair_indexes': range(1, item.chairs + 1) | list}) ] }}" loop: "{{ rooms | selectattr('chairs', 'gt', 0) }}" - name: 拆分序号序列,生成最终椅子条目列表 ansible.builtin.set_fact: chair_names: "{{ chair_names | default([]) + [ { 'chair_name': item.0.room_name ~ '-chair-' ~ item.1, 'room_name': item.0.room_name } ] }}" loop: "{{ rooms_with_chair_seq | subelements('chair_indexes') }}"
这个方法每一步逻辑清晰,排查问题的时候可以单独打印中间变量rooms_with_chair_seq校验序号生成是否正确,适合复杂业务场景使用。
方法3:JMESPath 查询生成(适合熟悉json_query的用户)
如果平时习惯用json_query做数据处理,可以直接写JMESPath表达式一步输出结果:
vars: chair_query: >- [?chairs > `0`].{ entries: [*].{ chair_name: join('-', [@.room_name, 'chair', to_string($)]), room_name: @.room_name }([*].range(`1`, chairs + `1`, `1`)) } | [].entries[] chair_names: "{{ rooms | community.general.json_query(chair_query) }}"
Ansible 2.10以下版本把过滤器前缀改成ansible.builtin即可正常运行。
结果验证
三种方法最终生成的chair_names变量完全符合预期:
chair_names: - chair_name: bedroom-1-chair-1 room_name: bedroom-1 - chair_name: kitchen-chair-1 room_name: kitchen - chair_name: kitchen-chair-2 room_name: kitchen - chair_name: kitchen-chair-3 room_name: kitchen - chair_name: kitchen-chair-4 room_name: kitchen
实用提示:如果只是单纯生成该列表直接使用,选方法1即可,变量渲染阶段就能出结果,执行速度最快;如果后续还要调整字段、扩展逻辑,选方法2维护成本最低。
内容的提问来源于stack exchange,提问作者edcsnt
相关产品推荐
相关产品推荐

