IF/Else-Statement at vars

Hi community,
I heard somewhere that you shouldn’t use an if-else statement in jinja2 format inside a variable. Unfortunately, I can’t find anything about this in any best practices guide.

Here’s a code example:

-  ansible.builtin.set_fact:
    myvar: "{{'value' if (my_group_var) else 'other_value'}}"

Thank you for your help

No matter what you heard, use what works for you, as an alternative, if you really must change, I offer ternary:

myvar: "{{ my_group_var|ternary('value', 'other_value') }}"

I advocate for not using “if” statements inside jinja statements and jinjas in general. But I agree with previous comment:

The argument being…?

Can you please explain your comment?

I heard dont use if statements, its better to use ansible filters and when not create your own. But to create every time a new filter its a little bit oversized. In my opinion.

Jinja is a text engine, not all data is text, when something a bit more complex is being used - a lot of problems appear all of the suddent, e.g. jinja spacing issues when you want result to be dict or list. Coertion from text to other data types (implicit in old ansible-core versions, explicit in new versions) is also kind of a problem, I prefer to be sure that I work with “native” data sctructures.

Some more arguments are in this thread

(How to solve ansible challenge from ansible-core maintainer)

if statements are fine from my point of view, jinja is the problem, as this is a text engine, not data processing engine. Ansible filters are much more suitable to process data.

There are plenty of filters in ansible and they cover a lot of functionality, but sometimes you have to create your own. There is nothing inherently wrong about it.

For instance, some functionality might be missing in ansible:

https://github.com/redhat-sap/rh_operations/blob/galaxy/plugins/filter/combine_default.py

Some functionality might be domain specific:

https://github.com/redhat-sap/rh_operations/blob/galaxy/plugins/filter/valid_hostname.py

And sometimes you just create filters to understand how they work:

https://github.com/redhat-sap/rh_operations/blob/galaxy/plugins/filter/all.py

Filters and test plugins are easy, you just have to start.

BTW this is not jinja if, so this is “safe”
This is jinja if

 {%- if something -%}  value  {%- endif -%}

Its not jinja? What is it called?

Sorry for using terminology so lightly. This is of course jinja.
In my view one has to distinguish jinja variables.

myvar: "{{'value' if (my_group_var) else 'other_value'}}"

From jinja blocks:

 {%- if something -%}  value  {%- endif -%}

See

block_start_string

The string marking the beginning of a block. Defaults to '{%'.

block_end_string

The string marking the end of a block. Defaults to '%}'.

variable_start_string

The string marking the beginning of a print statement. Defaults to '{{'.

variable_end_string

The string marking the end of a print statement. Defaults to '}}'.

I loosly call the second one (block) just jinja, as ansible is not imaginable without the first one (variables).

Thanks for clarification!

@kks If you are having that much trouble with whitespace in jinja, you are definitely doing it wrong. I’m using jinja extensively in my code and never had any trouble with parsing of jinja output.

The solution is to not act too smart with jinja and reduce your code to:

{% do something and calculate <final_value> %}
{% set some_var = <final_value> %}
{{ some_var }}

You will have no problem with this pattern.

For simple data manipulation, this beats making custom plugin any time… at least complexity wise.

And with ternary you get the 3rd option for “unknown” values:
myvar: {{ my_group_var |ternary('value if true', 'value if false', 'value if unknown') }}

I did not believe it unill I saw that with my own eyes. https://github.com/ansible/ansible/blob/abf5bf59a229e0df2e15a421a5eff83a7b8e3796/lib/ansible/plugins/filter/core.py#L271

Thank you for sharing.

For whatever reason it is not documented ansible.builtin.ternary filter – Ternary operation filter — Ansible Community Documentation

Odd about the filter documentation! It’s in the “Using filters” part of the Ansible community documentation, tho.

Trivia: if you’re also a network nerd, ‘ternary’ is how the various CAM tables work on a LAN switch (access-lists, qos policies, others). For access-lists in particular, ‘ternary’ is how the software does a look-up “in hardware” on the ASICs for matching fields. Binary is one or the other; ternary is one or the other or else.

It is documented, scroll down