How can I test jinja2 templates in ansible?
Solution 1
At this time exists 4 different variants:
1_Online (using https://cryptic-cliffs-32040.herokuapp.com/)
Based on jinja2-live-parser code.
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.
Solution 2
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"]}'
Solution 3
You can use the debug module
tasks:
- name: show templating results
debug:
msg: "{{ lookup('template', 'template-test.j2') }}"
Solution 4
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
Solution 5
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"
Alex
Updated on July 05, 2022Comments
-
Alex almost 2 years
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
-
AutomatedMike over 7 yearsNone of these seem to have the same behavior regarding missing variables. Missing vars fail in ansible but seem to default to false/empty in the above.
-
Alex over 7 yearsI added your answer to list.
-
artburkart over 6 years@AutomatedMike, my answer–which seems to have been stolen with attribution above–fails with missing vars as you'd expect
-
mlncn over 5 years@Alex please remove "Jinja2test.tk"— unfortunately the domain seems to have been taken over by spammy types, and there's no online test there.
-
Felipe Alvarez over 5 yearsI appreciate ansible-native way, also allows you to use ansible filters, too.
-
user228505 almost 5 yearsThere is also this online service: ansible.sivel.net/test with source here: github.com/sivel/ansible-template-ui
-
gczarnocki over 2 yearsDo you know if it's possible to print it pretty (with new lines)?
-
0xC0000022L over 2 yearsAnother answer popped up last year and it looks like it's the "persistent" version of your third method. Still perhaps worthwhile mentioning the option.
-
Pyrocater about 2 yearsWhile the last option above (
ansible -m template
) doesn't use a vars file as written, you can easily make it do so using@
--ansible -m template -a "yadda yadda" --extra-vars=@vars_file.yaml
Edit: looks like this was covered in the answer below, whoops!