Introduction
Writing efficient conditional logic in Ansible often means leveraging Jinja2 templating. One particularly powerful feature is the ternary operator, which helps you choose between two values based on a condition. However, many users encounter the dreaded error:
``
template error while templating string: unexpected character
`
This article walks through the correct way to use ternary expressions in Ansible using Jinja2 filters and shows how to avoid common pitfalls.
The Problem: Using JavaScript-style Ternary in Ansible
If you've ever written something like this in your Ansible playbook or template:
`jinja2
{{ env == 'dev' ? 'localhost' : 'db.prod.internal' }}
`
You’ve likely been met with a syntax error. That’s because Jinja2 does not support this JavaScript-style ternary operator. Instead, Ansible uses a different syntax via the ternary filter.
The Correct Way: Use the ternary Filter
To properly use conditional logic in Ansible, wrap your condition in parentheses and apply the ternary() filter:
`jinja2
{{ (env == 'dev') | ternary('localhost', 'db.prod.internal') }}
`
This line says: if env is 'dev', return 'localhost'; otherwise, return 'db.prod.internal'.
Example Use Case in a Template
Suppose you’re building an .env.j2 file and want to set the database host depending on the environment:
`jinja2
DB_HOST={{ (env | default('prod')) == 'dev' | ternary('localhost', 'db.prod.internal') }}
`
This ensures the condition works even if env isn’t defined.
Common Mistakes and Fixes
| Mistake | Why it's wrong | Correct Syntax |
|--------|----------------|----------------|
| env == 'dev' ? 'a' : 'b' | Not valid Jinja2 | (env == 'dev') | ternary('a', 'b') |
| Missing parentheses | Jinja2 parses it incorrectly | Always use parentheses around the condition |
| Forgetting | before ternary | ternary is a filter, not a function | Use | ternary(...) |
Debugging Tips
- Use debug
tasks to check expressions:
`yaml
- debug:
msg: "{{ (my_var is defined) | ternary(my_var, 'default') }}"
`
- Pipe | type_debug
to see what kind of data you're working with.
Why Use Ternary?
The ternary operator in Jinja2 helps you:
- Avoid verbose if-else
blocks in templates.
- Keep playbooks and configuration files cleaner.
- Make conditional assignments more readable.
Conclusion
When used correctly, the ternary operator can drastically improve the clarity and maintainability of your Ansible playbooks and templates. Avoid syntax errors by remembering: wrap the condition in parentheses and use the | ternary(true_value, false_value) filter. Stick to this structure, and you’ll avoid the classic unexpected character` template error for good.