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

Ansible中Jinja2模板list变量用indent报错的解决方案咨询

问题描述

编写了如下测试Ansible Playbook:

---
- name: Node Tolerations
  hosts: localhost
  gather_facts: false
  vars:
    tolerations:
      - key: node.cilium.io/agent-not-ready
        operator: Exists
        effect: NoExecute
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
  tasks:
    - name: Set node tolerations fact
      ansible.builtin.set_fact:
        node_tolerations: "{{ (node_tolerations | default([]) | union([':'.join((item.key, item.effect))])) }}"
      with_items: '{{ tolerations }}'

    - name: Set node taint fact
      ansible.builtin.set_fact:
        node_taint: "{{ node_tolerations | select('search', 'control-plane') }}"

    - name: Variable output
      ansible.builtin.debug:
        var: node_taint

执行后得到预期结果:

ok: [localhost] =>
  node_taint:
  - node-role.kubernetes.io/control-plane:NoSchedule

但在Jinja2模板中使用node_taint时,以下写法触发错误AttributeError: 'list' object has no attribute 'splitlines':

node-taint:
  {{ node_taint | indent(2) }}

临时 workaround 写法:

node-taint:
  - {{ node_taint | join }}

同时,使用tolerations变量时也出现相同错误:

tolerations:
  {{ tolerations | indent(2) }}

需求是避免在Jinja2模板中使用for循环,在事实层面处理数据,正常使用indent过滤器。

修复方案

错误根源在于indent过滤器仅支持字符串类型,而node_taint、tolerations都是列表/字典结构,直接传入会报错。需要在Ansible任务中将这些结构化数据提前转换为格式化好的多行字符串,再传入模板使用。

1. 处理node_taint列表

修改Set node taint fact任务,将列表转换为带YAML列表格式前缀的多行字符串:

- name: Set node taint fact as formatted string
  ansible.builtin.set_fact:
    node_taint_str: "{{ node_taint | map('regex_replace', '^', '- ') | join('\n  ') }}"
  vars:
    node_taint: "{{ node_tolerations | select('search', 'control-plane') }}"

此时node_taint_str是格式化后的字符串:

- node-role.kubernetes.io/control-plane:NoSchedule

模板中即可正常使用indent过滤器:

node-taint:
{{ node_taint_str | indent(2) }}

2. 处理tolerations字典列表

添加任务将tolerations转换为标准YAML格式的字符串:

- name: Set tolerations as formatted YAML string
  ansible.builtin.set_fact:
    tolerations_str: "{{ tolerations | to_nice_yaml(indent=2) | trim }}"

to_nice_yaml会自动将字典列表转换为符合YAML规范的格式化字符串,输出示例:

- key: node.cilium.io/agent-not-ready
  operator: Exists
  effect: NoExecute
- key: node-role.kubernetes.io/control-plane
  operator: Exists
  effect: NoSchedule

模板中使用方式:

tolerations:
{{ tolerations_str | indent(2) }}

修改后的完整Playbook

---
- name: Node Tolerations
  hosts: localhost
  gather_facts: false
  vars:
    tolerations:
      - key: node.cilium.io/agent-not-ready
        operator: Exists
        effect: NoExecute
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
  tasks:
    - name: Set node tolerations fact
      ansible.builtin.set_fact:
        node_tolerations: "{{ (node_tolerations | default([]) | union([':'.join((item.key, item.effect))])) }}"
      with_items: '{{ tolerations }}'

    - name: Set node taint fact as formatted string
      ansible.builtin.set_fact:
        node_taint_str: "{{ node_taint | map('regex_replace', '^', '- ') | join('\n  ') }}"
      vars:
        node_taint: "{{ node_tolerations | select('search', 'control-plane') }}"

    - name: Set tolerations as formatted YAML string
      ansible.builtin.set_fact:
        tolerations_str: "{{ tolerations | to_nice_yaml(indent=2) | trim }}"

    - name: Variable output
      ansible.builtin.debug:
        var: node_taint_str
    - name: Variable output
      ansible.builtin.debug:
        var: tolerations_str

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:36:03