Jinja Template Renderer
Render an Ansible .j2 template against your variables — and see which ones are missing.
Every Ansible `template:` task goes through Jinja, and the usual loop for getting one right is ansible-playbook → wrong output → edit → rerun, with the whole inventory in the way. Paste the template and the group_vars beside it and the render is immediate. The list of undefined variables matters more than the output: that is the play that fails at 3 a.m. because one host had no override.
# managed by Ansible
upstream portfolio {
server 10.0.0.51:8080;
server 10.0.0.52:9000;
server 10.0.0.53:8080 backup;
}
server {
server_name opswithzaeem.com;
listen 443 ssl http2;
ssl_certificate /etc/ssl/opswithzaeem.com.pem;
location / {
proxy_pass http://portfolio;
proxy_set_header Host $host;
}
}Syntax reference — tags, filters, tests
Tags
- {{ name }}
- Insert a value.
- {{ a.b.c }}
- Walk a mapping. Also {{ list[0] }} and {{ list[0].host }}.
- {% if x %} … {% elif y %} … {% else %} … {% endif %}
- Branch.
- {% for i in items %} … {% endfor %}
- Repeat. {% else %} runs when the list is empty.
- {% set n = 3 %}
- Define a variable mid-template.
- {# note #}
- A comment. Renders nothing.
- {%- … -%}
- Eat the whitespace on that side — the fix for blank lines left by block tags.
Inside a for loop
- loop.index
- 1, 2, 3 …
- loop.index0
- 0, 1, 2 …
- loop.first
- true on the first pass
- loop.last
- true on the last — the usual way to skip a trailing comma
- loop.length
- how many items
Filters
- default(v)
- Use v when the variable is undefined. default(v, true) also replaces empty/false.
- join(', ')
- A list into a string.
- upper / lower / capitalize / title
- Case.
- trim
- Strip surrounding whitespace.
- length
- Items in a list, keys in a mapping, characters in a string.
- replace(a, b)
- Substring replacement.
- int / float / string / bool
- Convert. int takes a fallback: | int(0).
- first / last / sort / unique / reverse / list
- List handling.
- indent(4)
- Indent every line after the first — for nesting a block inside YAML.
- tojson
- Serialise, for embedding in JSON or a shell argument.
Tests and operators
- x is defined
- The Ansible idiom. Guard anything that might be absent.
- x is not defined / is undefined
- The negative.
- x is none
- Defined, but null. Not the same as undefined.
- a in b
- Membership in a list, mapping keys, or a substring.
- and / or / not, == != > < >= <=
- The usual operators.
The mistakes that actually cost time
- An undefined variable fails the play. Ansible stops on it rather than rendering an empty string, so the warnings above are the real output of this tool. Guard anything optional with
| default(...)oris defined. defaultdoes not fire on an empty string.{{ name | default('anon') }}still renders nothing whennameis""— it is defined. Passdefault('anon', true)to replace falsy values too.- Block tags leave blank lines.
{% for %}on its own line emits that line's newline. Use{%- ... -%}to trim — it is why generated configs come out double-spaced. - A number in quotes is a string.
port: "8080"compared with{% if port > 1024 %}behaves differently from an unquoted8080. Use| intwhen you mean a number. - Whitespace matters in YAML output. When a template writes YAML, an interpolated multi-line value breaks the indentation.
| indent(4)is the usual repair.
What this renderer does not do
No {% macro %}, {% include %}, {% raw %}, inline if expressions, or Ansible-only filters such as regex_replace and to_nice_yaml — those come from Ansible, not Jinja. Anything unsupported is reported in the warnings rather than dropped silently, so the output never looks more finished than it is.