Jinja2处理Ansible os_stack输出数据时遇变量错误求助
解决Ansible Jinja2模板的UndefinedVariable错误并生成期望的YAML格式
首先咱们来拆解你遇到的问题:
错误原因分析
你当前的模板代码存在两个关键问题,直接触发了AnsibleUndefinedVariable错误:
- 错误的循环对象:
for group in outputs[0].description这行代码是在循环字符串"lb"的单个字符(也就是'l'和'b'),而不是遍历所有需要的分组名称(lb和web)。当后续代码尝试用单个字符去访问不存在的属性/索引时,自然会抛出错误。 - 误解数据结构的访问方式:
outputs[0].output_value[group]完全不符合原始数据的结构——原始的outputs是一个平级列表,每个元素都是独立的键值对,并不是按分组嵌套的字典。
正确的Jinja2模板实现
我们需要先按description字段对outputs列表分组,再为每组内的IP条目添加递增的index,最后生成你期望的YAML结构。这里可以利用Ansible自带的groupby过滤器简化分组操作:
{%- set ip_specs = {} -%} {%- for group_name, group_items in outputs | groupby('description') -%} {%- set net_list = [] -%} {%- for idx, item in group_items | enumerate(start=1) -%} {%- do net_list.append({ 'net_info': {'ip': item.output_value}, 'index': idx }) -%} {%- endfor %} {%- do ip_specs.update({group_name: net_list}) -%} {%- endfor %} {{ {'vm_list': ip_specs} | to_yaml }}
代码细节解释
- 分组处理:
outputs | groupby('description')会自动把原始列表按description的值分成两组:('lb', [lb相关的两个条目])和('web', [web相关的三个条目])。 - 自动生成索引:用
enumerate(start=1)来自动生成从1开始的递增索引,避免手动维护index列表的繁琐操作。 - 构造目标结构:把每个分组的结果整理到
ip_specs字典中,最后通过to_yaml过滤器转换成标准的YAML格式输出。
测试输出
将你的原始outputs数据代入模板后,会生成完全符合你期望的结果:
vm_list: lb: - net_info: {ip: 10.1.1.11} index: 1 - net_info: {ip: 10.1.1.12} index: 2 web: - net_info: {ip: 10.1.1.13} index: 1 - net_info: {ip: 10.1.1.14} index: 2 - net_info: {ip: 10.1.1.15} index: 3
额外优化提示
如果需要让web组内的条目按output_key中的数字排序(比如让web_2排在web_3前面),可以在遍历分组前先对group_items排序:
{%- for idx, item in group_items | sort(attribute='output_key') | enumerate(start=1) -%}
这样web_1、web_2、web_3会按顺序排列,对应的index也会同步调整。
内容的提问来源于stack exchange,提问作者maurer
相关产品推荐
相关产品推荐

