Ansible中Jinja2模板列表追加报错:未知标签'do'问题求助
我来帮你搞定这个问题!你碰到的AnsibleError: template templating string: Encountered unknown tag 'do'错误,本质是Jinja2的do标签并非默认启用,而Ansible默认没加载这个扩展,所以解析模板时会报错。下面给你两种可行的解决思路:
方法一:启用Jinja2的do扩展
你可以通过配置让Ansible加载jinja2.ext.do扩展,这样do标签就能正常使用了。
方式1:在Playbook中配置
在你的playbook里添加jinja2_extensions参数,指定启用do扩展:
- name: 你的任务名称 hosts: 目标主机组 vars: jinja2_extensions: jinja2.ext.do tasks: # 你的任务内容
方式2:在Ansible配置文件中全局启用
编辑ansible.cfg文件,在[defaults]段添加:
jinja2_extensions = jinja2.ext.do
这样所有playbook都会默认启用这个扩展。
方法二:避免使用do标签(推荐)
如果你不想修改Ansible配置,也可以用Jinja2默认支持的语法来重构模板,完全避开do标签,兼容性更好。
修正后的模板示例1:用set语句替代do
利用set来执行列表的append操作,忽略返回值即可:
{% set port = 1234 %} {% set server_ip = [] %} {% for ip in host_ip %} {% set _ = server_ip.append(ip ~ ':' ~ port) %} {% endfor %} devices = {{ server_ip|join(', ') }}
这里{% set _ = ... %}的作用是执行append操作,同时用下划线变量接收返回值(我们不需要这个值,只是为了符合Jinja2的语法要求)。
修正后的模板示例2:用列表推导式简化写法
更简洁的方式是用map过滤器直接转换每个IP,再用join拼接,连循环都省了:
{% set port = 1234 %} devices = {{ host_ip | map('regex_replace', '^(.*)$', '\\1:' ~ port) | join(', ') }}
这个写法通过regex_replace把每个IP格式化为IP:端口的形式,再用join(', ')拼接成你需要的字符串,逻辑更清晰,代码也更短。
测试一下这两种修正后的模板,都能生成你期望的devices = 192.168.56.14:1234,192.168.56.13:1234,192.168.56.10:1234结果。
内容的提问来源于stack exchange,提问作者learning fun

