As advised in the Frequently Asked Questions of Ansible, moustache do not stack.
Another rule is ‘moustaches don’t stack’. We often see this:
{{ somevar_{{other_var}} }}
The above DOES NOT WORK as you expect, if you need to use a dynamic variable use the following as appropriate:
{{ hostvars[inventory_hostname]['somevar_' ~ other_var] }}
For ‘non host vars’ you can use the vars lookup plugin:
{{ lookup('vars', 'somevar_' ~ other_var) }}
So, there are two cases where this will apply:
-
When trying to access a key of a dictionary from a variable, you would simply use the variable as is, remembering that, when you are inside the expression delimiters
{{ ... }}
, a string will be interpreted as a variable, if not enclosed inside simple or double quotes.- ansible.builtin.debug: msg: "{{ foo[key] }}" vars: key: bar foo: bar: baz
-
When trying to construct the name of the variable or the key of a dictionary from a variable, you will have to use the concatenation operator,
~
:- ansible.builtin.debug: msg: "{{ foo['foo_' ~ key] }}" vars: key: bar foo: foo_bar: baz
You might also need to use the
vars
lookup to access a dynamic variable:- ansible.builtin.debug: msg: "{{ lookup('vars', 'foo_' ~ key) }}" vars: key: bar foo_bar: baz
Side notes:
-
Do use the
vars
lookup —lookup('vars', 'somevar_' ~ other_var)
— and not thevars
dictionary —vars['somevar_' ~ other_var]
, as it was never intended to be an Ansible feature and will be removed in future versionShort history,
vars
is a leftover from previous code that used it to pass variables to template, it was never intended for external use and most of the time didn’t template anything.Unrelated changes allowed it to template ‘sometimes’ but this was never on purpose, the only reason it was not removed is because some people relied on it, that had discovered by looking at the code and/or other people that had already been using it. Even though it has been our intention for a long time to deprecate and remove the
vars
construct, lack of a good way to trigger a runtime message has kept us from doing so.We created 2 alternatives via lookups
varnames
andvars
, which might not be as flexible as a dict but also would not chew up memory for unneeded access, since most users just want to match a small subset of existing variables.Source: https://github.com/ansible/ansible/issues/74904#issuecomment-854137949
-
It is more advisable to use the right concatenation operator,
~
than the math operator+
as advised in the Ansible documentation for the reason raised in Jinja documentation:Usually the objects are numbers, but if both are strings or lists, you can concatenate them this way. This, however, is not the preferred way to concatenate strings! For string concatenation, have a look-see at the
~
operator.Source: https://jinja.palletsprojects.com/en/2.11.x/templates/#math