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
相关产品推荐
相关产品推荐

