Ansible中如何延迟Jinja2模板字符串的循环内求值?
解决方案
方法一:配置文件存储无花括号的表达式(推荐)
先修改你的配置变量文件,移除eval字段的{{}},只保留纯表达式内容:
checks: - name: "x" setting: "y" eval: "'OK' if var == 'x' else 'NOK'"
接着修改do.yml的Save stuff任务,使用template过滤器在var注册后动态渲染表达式:
--- - debug: var: item - name: Do stuff shell: echo "x" # 示例命令,替换为你的实际操作 register: var - name: Save stuff set_fact: result: "{{ result | d([]) + [ res ] }}" vars: res: name: "{{ item.name }}" setting: "{{ item.setting }}" result: "{{ item.eval | template }}"
方法二:保留配置文件中的花括号(转义避免提前模板化)
如果必须保留配置里的{{}},需要先转义花括号,防止Ansible在解析checks变量时提前模板化:
checks: - name: "x" setting: "y" eval: "{% raw %}{{ 'OK' if var == 'x' else 'NOK' }}{% endraw %}"
或者用字符串拼接转义:
checks: - name: "x" setting: "y" eval: "{{ '{{' }} 'OK' if var == 'x' else 'NOK' {{ '}}' }}"
之后同样在do.yml的Save stuff任务中使用template过滤器延迟求值,代码和方法一一致。
问题根源
你之前的写法中,main.yml里的loop: "{{ checks }}"会触发Ansible提前对整个checks变量做模板渲染——此时var还未被注册,eval字段会被直接解析为NOK,后续任务引用的只是这个提前计算好的静态值,而非基于最新上下文的动态结果。
通过将表达式以纯字符串存储,再在var注册后用template过滤器动态渲染,就能实现延迟求值的效果。
内容的提问来源于stack exchange,提问作者Michal Zaorálek
相关产品推荐
相关产品推荐

