如何在Ansible Playbook中使用YML存储的Jinja模板列表?
Ansible Playbook 问题解决:循环渲染Jinja模板并合并为单个配置文件
问题分析
你遇到的两个核心问题:
- 变量解析错误:原变量定义误用
lookup('template')处理静态YAML文件(应使用lookup('file')),且原YAML键template lab带空格,错误使用点符号访问;同时直接将列表作为template模块的src参数,导致路径被字符串化为带[]和''的格式,无法识别模板文件。 - 模板循环与合并:未实现遍历模板列表并将渲染结果合并到单个文件的逻辑。
解决方案
步骤1:修正模板列表变量定义
首先修正jinja_templates变量的获取方式:
- 使用
lookup('file')读取静态YAML文件(lookup('template')用于渲染Jinja模板,不适合读取静态配置) - 原YAML文件的键是
template lab(带空格),需用字典键访问语法['template lab']而非点符号
修改后的变量定义:
vars: - jinja_templates: "{{ (lookup('file', './template_list.yml') | from_yaml)['template lab'] }}"
步骤2:循环渲染模板并合并到单个文件
提供三种可行方案,按需选择:
方案一:收集所有渲染内容后一次性写入
通过set_fact循环渲染每个模板,将结果收集到变量中,再一次性写入目标文件,减少文件IO操作:
--- - name: Generate merged .conf file hosts: my_routers gather_facts: no vars: - jinja_templates: "{{ (lookup('file', './template_list.yml') | from_yaml)['template lab'] }}" vars_files: - "./yml/{{ inventory_hostname }}.yml" tasks: - name: Render all templates and collect content set_fact: merged_config: "{{ merged_config | default('') + lookup('template', './templates/' + item) + '\n' }}" loop: "{{ jinja_templates }}" - name: Write merged configuration to file copy: content: "{{ merged_config }}" dest: "./tmp/general/{{ inventory_hostname }}.conf" mode: "0644"
方案二:循环渲染并追加到文件
逐个渲染模板,每次将结果追加到目标文件,适合模板内容较多的场景:
--- - name: Generate merged .conf file hosts: my_routers gather_facts: no vars: - jinja_templates: "{{ (lookup('file', './template_list.yml') | from_yaml)['template lab'] }}" vars_files: - "./yml/{{ inventory_hostname }}.yml" tasks: - name: Ensure target directory exists file: path: "./tmp/general" state: directory mode: "0755" - name: Render template and append to config file copy: content: "{{ lookup('template', './templates/' + item) + '\n' }}" dest: "./tmp/general/{{ inventory_hostname }}.conf" mode: "0644" append: yes loop: "{{ jinja_templates }}"
方案三:先渲染临时文件再合并
先将每个模板渲染为临时目录下的单独文件,再用assemble模块合并,便于调试单个模板的渲染结果:
--- - name: Generate merged .conf file hosts: my_routers gather_facts: no vars: - jinja_templates: "{{ (lookup('file', './template_list.yml') | from_yaml)['template lab'] }}" - temp_dir: "./tmp/template_outputs/{{ inventory_hostname }}" vars_files: - "./yml/{{ inventory_hostname }}.yml" tasks: - name: Create temporary directory file: path: "{{ temp_dir }}" state: directory mode: "0755" - name: Render individual templates to temp files template: src: "./templates/{{ item }}" dest: "{{ temp_dir }}/{{ item | replace('.j2', '.conf') }}" mode: "0644" loop: "{{ jinja_templates }}" - name: Merge temp files into final config assemble: src: "{{ temp_dir }}" dest: "./tmp/general/{{ inventory_hostname }}.conf" mode: "0644" delimiter: '\n' # 可选:设置合并时的分隔符
关键说明
- 原YAML文件
template_list.yml中的键template lab带空格,必须用['template lab']访问,不能用template_lab(点符号无法处理带空格的键) lookup('template')用于直接渲染模板内容到字符串,适合收集内容的场景;template模块用于将模板渲染为文件,适合分步处理的场景- 方案一和二会直接覆盖(或追加)目标文件,方案三保留单个模板的渲染结果,便于排查问题
内容的提问来源于stack exchange,提问作者Aldamova
相关产品推荐
相关产品推荐

