如何在Ansible的host_vars/group_vars中用for循环简化变量定义
如何在Ansible的host_vars/group_vars中通过循环生成列表变量减少重复
需求背景
需要简化host_vars/group_vars中的变量定义,避免重复编写相同结构的列表项。例如原始变量定义:
blue_items: - name: ocean color: blue - name: sky color: blue - name: umbrella color: blue
希望通过一个基础列表list_blue_items: ['ocean', 'sky', 'umbrella']自动生成上述blue_items列表。
之前的错误尝试
错误1:直接嵌入Jinja2循环
尝试在YAML中直接写循环,导致YAML语法错误:
list_blue_items: ['ocean', 'sky', 'umbrella'] blue_items: {% for item in list_blue_items %} - name: "{{ item }}" color: blue {% endfor %}
报错信息:
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each: JSON: Expecting value: line 1 column 1 (char 0) Syntax Error while loading YAML. found character that cannot start any token The error appears to be in '/opt/ansible/host_vars/client1/nginx.yml': line 4, column 2, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: blue_items: {% for item in list_blue_items %} ^ here
原因:YAML解析器无法识别键值缩进块内的Jinja2标签,会将{% ... %}视为无效的YAML语法。
错误2:使用块字符串|
添加|后生成的是字符串而非列表结构:
list_blue_items: ['ocean', 'sky', 'umbrella'] blue_items: | {% for item in list_blue_items %} - name: "{{ item }}" color: blue {% endfor %}
原因:|会将后续内容视为纯文本字符串,Ansible不会自动将其解析为YAML列表。
正确实现方法
方法1:用Jinja2的do扩展构造列表
通过临时列表和do语句生成目标结构:
list_blue_items: ['ocean', 'sky', 'umbrella'] blue_items: >- {% set temp_list = [] %} {% for item in list_blue_items %} {% do temp_list.append({'name': item, 'color': 'blue'}) %} {% endfor %} {{ temp_list }}
>-是折叠块标量,会自动去除多余换行,确保输出为合法的列表表达式。do语句用于向临时列表追加构造好的字典,最后输出的临时列表会被Ansible解析为YAML列表。
方法2:使用map过滤器生成字典列表
无需依赖do扩展,直接用map过滤器构造每个列表项:
list_blue_items: ['ocean', 'sky', 'umbrella'] blue_items: "{{ list_blue_items | map('dict', name='', color='blue') | list }}"
map('dict', name='', color='blue')会将列表中的每个元素赋值给name字段,color字段固定为blue,生成对应字典。list过滤器将map的结果转换为最终的列表结构。
验证结果
使用debug模块验证生成的blue_items结构:
- name: 检查blue_items结构 ansible.builtin.debug: var: blue_items
执行后会得到与原始定义完全一致的列表结构。
内容的提问来源于stack exchange,提问作者erzed
相关产品推荐
相关产品推荐

