我该如何在ansible中测试jinja2模板?

81
有时我需要测试一些在我的ansible角色中使用的jinja2模板。最简单的方法是什么?
例如,我有一个模板(test.j2):
{% if users is defined and users %}
{% for user in users %}{{ user }}
{% endfor %}
{% endif %}

在组变量(group_vars/all)中可以定义变量:
---
users:
  - Mike
  - Smith
  - Klara
  - Alex
5个回答

113

目前存在四种不同的变体:

1_在线版(使用https://cryptic-cliffs-32040.herokuapp.com/
基于jinja2-live-parser代码。

示例

2_交互式(使用Python和库jinja2、PyYaml)

import yaml
from jinja2 import Template
>>> template = Template("""
... {% if users is defined and users %}
... {% for user in users %}{{ user }}
... {% endfor %}
... {% endif %}
... """)
>>> values = yaml.load("""
... ---
... users:
...   - Mike
...   - Smith
...   - Klara
...   - Alex
... """)
>>> print "{}".format(template.render(values))


Mike
Smith
Klara
Alex

3_Ansible(使用--check选项)
创建测试剧本jinja2test.yml:

---
- hosts: 127.0.0.1
  tasks:
  - name: Test jinja2template
    template: src=test.j2 dest=test.conf

并运行它:

ansible-playbook jinja2test.yml --check --diff --connection=local

示例输出:

PLAY [127.0.0.1] **************************************************************

GATHERING FACTS ***************************************************************

ok: [127.0.0.1]

TASK: [Test jinja2template] ***************************************************
--- before: test.conf
+++ after: /Users/user/ansible/test.j2
@@ -0,0 +1,4 @@
+Mike
+Smith
+Klara
+Alex

changed: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1                  : ok=2    changed=1    unreachable=0    failed=0

4_Ansible (使用-m模板) 感谢@artburkart

创建一个名为test.txt.j2的文件

{% if users is defined and users %}
{% for user in users %}
{{ user }}
{% endfor %}
{% endif %}

这样调用ansible:

ansible all -i "localhost," -c local -m template -a "src=test.txt.j2 dest=./test.txt" --extra-vars='{"users": ["Mike", "Smith", "Klara", "Alex"]}'

该命令将在当前目录下输出名为test.txt的文件,其中包含了test.txt.j2 模板的输出结果。

我知道这种方法并没有直接使用vars文件,但我认为这是测试模板最简单的方式,而且不需要使用任何外部依赖。此外,我相信jinja2库提供的功能与ansible提供的存在一些差异,因此直接使用ansible可以避免任何不一致之处。当传递给--extra-vars参数的JSON满足您的需求时,您可以将其转换为YAML格式并继续进行。


1
这些似乎对于缺失变量的行为没有相同的反应。在Ansible中,缺失的变量会导致失败,但在上述情况下似乎默认为false/empty。 - AutomatedMike
2
@AutomatedMike,我的回答似乎被上面的引用偷走了,当然会因为缺少变量而失败。 - artburkart
@Alex,请移除“Jinja2test.tk”——不幸的是,该域名似乎已被垃圾邮件发送者接管,并且那里没有在线测试。 - mlncn
2
还有这个在线服务:https://ansible.sivel.net/test/ 源代码在这里:https://github.com/sivel/ansible-template-ui - user228505
去年又出现了另一个答案,看起来它是你第三种方法的“持久”版本。或许值得一提这个选项。 - 0xC0000022L
显示剩余2条评论

48

如果您有一个名为test.j2的jinja2模板,以及一个位于group_vars/all.yml的变量文件,则可以使用以下命令测试该模板:

如果您有一个名为test.j2的jinja2模板,以及一个位于group_vars/all.yml的变量文件,则可以使用以下命令测试该模板:

ansible all -i localhost, -c local -m template -a "src=test.j2 dest=./test.txt" --extra-vars=@group_vars/all.yml

它将在当前目录中输出名为test.txt的文件,其中包含评估test.j2模板的输出内容。

我认为这是测试模板最简单的方法,而不使用任何外部依赖。此外,jinja2库提供的功能与ansible提供的功能存在差异,因此直接使用ansible可以规避任何差异。还可以使用JSON测试即席变量,而无需创建额外的vars文件:

ansible all -i "localhost," -c local -m template -a "src=test.j2 dest=./test.txt" --extra-vars='{"users": ["Mike", "Smith", "Klara", "Alex"]}'

1
我把你的答案添加到了列表中。 - Alex
2
我很欣赏 Ansible 原生的方式,它还允许你使用 Ansible 过滤器。 - Felipe Alvarez

17

您可以使用调试模块

tasks: 
- name: show templating results
  debug:
   msg: "{{ lookup('template', 'template-test.j2') }}"

2
你知道是否可以漂亮地打印它(带有换行符)吗? - gczarnocki

8
免责声明 - 我是此内容的作者,但我制作了JinjaFx (https://github.com/cmason3/jinjafx)。
这是一个基于Python的工具,允许您通过一个YAML文件传递Jinja2模板所需的变量。我最初编写它是为了将CSV数据传递以生成我们部署所需的group_vars和host_vars,但它也可以方便地测试Jinja2模板 - 在https://jinjafx.io上有一个在线版本。

3

我需要确认我定义的模板针对创建它的服务器给出正确结果。(该模板包括主机名变量和其他按主机定义的变量)

以上两种方法都对我无效。对我而言解决方案是添加

  check_mode: yes
  diff: yes

执行模板命令的任务中,通过这个命令能够查看生成的文件和服务器上实际存在的文件之间的差异,而不改变远程文件。 对我来说,这比查看整个生成的文件更加有效,因为变化才是有趣的部分。 需要登录到远程机器,因此只适用于有限的使用情况。 下面是一个完整命令的示例:
    - name: 比较server.properties文件
      check_mode: yes
      diff: yes
      ansible.builtin.template:
        src: "src.properties"
        dest: "/opt/kafka/config/server.properties"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接