You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于字典变量在Ansible的Jinja2模板中包含对应文件?

问题

我正在尝试使用Ansible和Jinja2生成模板化配置文件,现有如下配置:

变量定义

internal_sites:
  - {name: "site1" ,url: "site1.example.com" }
  - {name: "site2" ,url: "site2.example.com" }
  - {name: "site3" ,url: "site3.example.com" }
  - {name: "site4" ,url: "site4.example.com" }

模板目录结构

├── templates
│   ├── base.cfg.j2
│   └── services
│       ├── internal
│       │   ├── site1.txt
│       │   ├── site2.txt
│       │   ├── site3.txt
│       │   ├── site4.txt

需求是在base.cfg.j2中遍历internal_sites的每个条目,生成配置的同时引入对应名称的文本文件内容。尝试了两种写法均报错:

第一种写法

{% for site in internal_sites %}
  acl {{ site.name }} hdr(host) -i {{ site.url }}
  use_backend {{ site.name }} if {{ site.name }}

  backend {{ site.name}}
    {% include "templates/services/internal/"{{lookup('vars', site.name)}} %}

{% endfor %}

报错信息:

FAILED! => {"changed": false, "msg": "AnsibleError: template error while templating string: expected token 'end of statement block', got '{'. String: 
{% for site in internal_sites %}
  acl {{ site.name }} hdr(host) -i {{ site.url }}
  use_backend {{ site.name }} if {{ site.name }}

  backend {{ site.name}}
    {% include \"templates/services/internal/\"{{lookup('vars', site.name)}} %}

{% endfor %}
"}

第二种写法

{% for site in internal_sites %}

  {% set fileloc = 'templates/services/internal/' + site.name %}
  acl {{ site.name }} hdr(host) -i {{ site.url }}
  use_backend {{ site.name }} if {{ site.name }}

  backend {{ site.name}}
    {% include {{fileloc}} %}

{% endfor %}

预期输出示例:

acl site1 hdr(host) -i site1.example.com
  use_backend site1 if site1

  backend site1
    contents of site1.txt
    are included
    here

正确实现方式

错误原因分析

  1. Jinja2的{% include %}语句中,路径参数不需要用{{}}包裹,嵌套{{}}会触发语法解析错误。
  2. Ansible模板路径默认相对于templates目录,无需在路径中添加templates前缀。
  3. 目标文件是带.txt后缀的文件,之前的写法遗漏了后缀,会导致文件查找失败。

修正后的模板代码

{% for site in internal_sites %}
  acl {{ site.name }} hdr(host) -i {{ site.url }}
  use_backend {{ site.name }} if {{ site.name }}

  backend {{ site.name }}
    {% include "services/internal/" ~ site.name ~ ".txt" %}
{% endfor %}

关键说明

  • 使用Jinja2字符串拼接符~组合路径:"services/internal/" ~ site.name ~ ".txt",可正确生成每个站点对应的文件路径。
  • include语句直接使用拼接后的路径字符串,符合Jinja2语法规范。
  • 路径从templates目录开始,因此直接写services/internal/...即可,Ansible会自动在templates目录下定位文件。

运行上述模板后,即可生成符合预期的配置文件,自动引入对应站点的txt文件内容。

内容的提问来源于stack exchange,提问作者CosmicLentil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:20:23