I have the following jinja2 template
[
{% for items in hosts %}
{
"name":"{{ items.name }}",
"display_name":"{{ items.display_name }}",
"services": {{ host_group | from_json | json_query('[*].services[0]') | to_json }},
}
{% endfor %}
]
i need to replace services[0] by a variable {{ loop.index0 }}, i tried this syntax
"services": {{ host_group | from_json | json_query('[*].services[loop.index0]') | to_json }}
but i'm getting an error :
AnsibleFilterError: JMESPathError in json_query filter plugin:
Expecting: star, got: unquoted_identifier: Parse error at column 13, token "loop" (UNQUOTED_IDENTIFIER), for expression:
"[*].services[loop.index0]"
I tried another syntax:
"services": {{ host_group | from_json | json_query('[*].services[' + {{ loop.index0 }} +']') | to_json }},
and it gives also an error :
AnsibleError: template error while templating string: expected token ':', got '}'. String: [
There are two things to keep in mind when working with Jinja:
{{...}}
template markers.So when you write:
json_query('[*].services[loop.index0]')
You are passing json_query
the literal string [*].services[loop.index0]
, which isn't a valid JMESPath query. If you want to substitute the value of a variable in a string, you need to either build the string via concatenation, or use string formatting logic.
Using concatenation might look like:
json_query('[*].services[' ~ loop.index0 ` ']')
Here, ~
is the string concatenation operator -- it's like +
, but it makes sure to convert everything into a string. Compare this:
ansible localhost -m debug -a 'msg={{ "there are " + 4 + " lights" }}'
To this:
ansible localhost -m debug -a 'msg={{ "there are " ~ 4 ~ " lights" }}'
Using string formatting might look like:
json_query('[*].services[%s]' % (loop.index0))
Or:
json_query('[*].services[{}]'.format(loop.index0))
These are two forms of string formatting available in Python; for more details, start here.