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

如何在Ansible Playbook中使用YML存储的Jinja模板列表?

Ansible Playbook 问题解决:循环渲染Jinja模板并合并为单个配置文件

问题分析

你遇到的两个核心问题:

  1. 变量解析错误:原变量定义误用lookup('template')处理静态YAML文件(应使用lookup('file')),且原YAML键template lab带空格,错误使用点符号访问;同时直接将列表作为template模块的src参数,导致路径被字符串化为带[]和''的格式,无法识别模板文件。
  2. 模板循环与合并:未实现遍历模板列表并将渲染结果合并到单个文件的逻辑。

解决方案

步骤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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 05:24:17