65
votes

Sometimes I need to test some jinja2 templates that I use in my ansible roles. What is the simplest way for doing this?

For example, I have a template (test.j2):

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

and vars (in group_vars/all):

---
users:
  - Mike
  - Smith
  - Klara
  - Alex
5

5 Answers

95
votes

At this time exists 4 different variants:

1_Online (using https://cryptic-cliffs-32040.herokuapp.com/)
Based on jinja2-live-parser code.

Example

2_Interactive (using python and library 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 (using --check)
Create test playbook jinja2test.yml:

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

and run it:

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

sample output:

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 (using -m template) thanks for @artburkart

Make a file called test.txt.j2

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

Call ansible like so:

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

It will output a file called test.txt in the current directory, which will contain the output of the evaluated test.txt.j2 template.

I understand this doesn't directly use a vars file, but I think it's the simplest way to test a template without using any external dependencies. Also, I believe there are some differences between what the jinja2 library provides and what ansible provides, so using ansible directly circumvents any discrepancies. When the JSON that is fed to --extra-vars satisfies your needs, you can convert it to YAML and be on your way.

45
votes

If you have a jinja2 template called test.j2 and a vars file located at group_vars/all.yml, then you can test the template with the following command:

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

It will output a file called test.txt in the current directory, which will contain the output of the evaluated test.j2 template.

I think this is the simplest way to test a template without using any external dependencies. Also, there are differences between what the jinja2 library provides and what ansible provides, so using ansible directly circumvents any discrepancies. It's also possible to test ad-hoc variables without making an additional vars file by using JSON:

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

You can use the debug module

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

Disclaimer - I am the author of this, but I put together JinjaFx (https://github.com/cmason3/jinjafx).

This is a Python based tool that allows you to pass Jinja2 templates with a YAML file for variables. I originally wrote it so it can pass CSV based data to generate group_vars and host_vars for our deployments, but it also allows easy testing of Jinja2 templates - there is an online version at https://jinjafx.io

0
votes

I needed to verify that the template I had defined gave the right result for the server it was created for. (The template included the hostname as a variable and other per host defined variables.)

Neither of the above methods worked for me. The solution for me was to add

  check_mode: yes
  diff: yes

to the task executing the template command, this got me the difference between the generated file and the file actually on the server without changing the remote file. For me it actually worked better than looking at the whole generated file, since the changes was the interesting part anyway. It needs to log in on the remote machine, so a limited use-case. Example of a complete command:

    - name: diff server.properties
      check_mode: yes
      diff: yes
      ansible.builtin.template:
        src: "src.properties"
        dest: "/opt/kafka/config/server.properties"