How to trim last character when using ansible jinja loop - ansible

My template like as blow
{% if hostvars[inventory_hostname].local_zk_server_id is defined %}
zookeeperServers={% for host in {{ groups[{{ target_hosts }}] %}}
"{{ hostvars[host].inventory_hostname }}:2181,"
{% endfor %}
{% endif %}
output ishost1:2181,host2:2181,host3:2181,
How to trim last comma

There are several possible gotchas in your above template regarding variables access. Moreover, rather than trimming the last character in your string, the best solution is probably not to write it. Here is a better solution IMO in my below example fixing all the problems I'm referring to:
{% set zookeeperServers=[] %}
{% if hostvars[inventory_hostname].local_zk_server_id is defined %}
{% for host in groups[target_hosts] %}
{% zookeeperServers.append(hostvars[host].inventory_hostname + ":2181") %}
{% endfor %}
zookeeperServers="{{ zookeeperServers | join(',') }}"
{% endif %}

Related

Using Twig to generate Markdown, how to indent blocks in twig?

I have very few hours of use with Twig so I probably missed an important tip; please forgive me if this is a trivial question.
I'm using Twig with PHP for the generation of markdown files.
My twig file contains one or more {% for %}...{% endfor %} block and inside a for-loop, a few {% if %}...{% endif %} and ... I can't make any indentation in my Twig otherwise the spaces are also present in my output.
A very stupid example: https://twigfiddle.com/fb6nzq (use the Show raw result to make sure to see the spaces before the word true).
If I don't indent my {% if %}...{% endif %}, I got the correct result (https://twigfiddle.com/fb6nzq/2) but I don't have anymore indentation of blocks in my template.
In my real world twig file, I can have multiple {% endif %} like below and it becomes unreadable.
{% for (variable) %}
{% if (condition) %}
{% if (condition) %}
{% if (condition) %}
{% endif %}
{% endif %}
{% endif %}
{% endfor%}
So ... do you know if there is a wonderful trick to keep an indentation in your code but without having an impact on the output?
Desired twig template:
{% for (variable) %}
{% if (condition) %}
{% if (condition) %}
{% if (condition) %}
{% endif %}
{% endif %}
{% endif %}
{% endfor%}
You can use a dash - on any opening or closing twig expression where:
a dash on the closing expression would do a trim on the left.
{% if true -%}
a dash on the opening expression would do a trim on the right
{%- if true %}
a dash on the both the opening and closing expression would do a trim on the both sides
{%- if true -%}
Mind that: this is acting as a PHP trim, so that means that it will also trim your line feeds!
Here is an example:
{% for i in 1..5 %}
{% if true %}
{% if true %}
{%- if true %}
foo
{%- endif %}
{%- endif %}
{% endif %}
{% endfor %}
That renders:
foo
foo
foo
foo
foo
This is testable here: https://twigfiddle.com/1awhzk
Also note: that there is a spaceless tag to achieve those kind of things.

How can I use AWS tags in a template?

I know that it is possible to loop over lists in a Jinja2 template like this:
{% for host in vars['play_hosts'] %}
"{{ host }}"{% if not loop.last %},{% endif %}
{% endfor %}
(Example stolen from this question.)
How can I use AWS tag based values like "the IPs of all hosts with value 'dev' in tag 'Environment'" instead of vars['play_hosts']?
I found out myself that it is only a matter of using the right group. All ec2 instances with the same tag can be found in a group and can be addressed by using e.g. groups['tag_Environment_dev']. So the example from the question would look like this:
{% for host in groups['tag_Environment_dev'] %}
"{{ host }}"{% if not loop.last %},{% endif %}
{% endfor %}

assignment of undefined variables in Jinja2

I got this piece of YAML and i want jinja2 to assign and create item.menu, if it is not previously defined.
data:
- name: bar
menu: blah
- name: foo
This is my code, the error-output ist "template error while templating string: expected token 'end of statement block'"
{% for item in data %}
{% if item.menu is not defined %}
{% set item.menu=item.name %}
{% endif %}
{% endfor %}
Any Help about what I did wrong would be much apretiated :)
Greetings, Hendrik
You're question is not clear but here is my answer. I'll make everything explicit :
{% for item in data %}
{% if item.menu is not defined %}
{{ item.nameĀ }}
{% else %}
{{ item.menu }}
{% endif %}
{% endfor %}

Ansible: get list of hosts in comma separated value

I have the following loop in a template:
{% for host in groups['dbnodes'] %}
{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{% endfor %}
the issue is that it gives the output in list of ip's and I need it in comma separated value. Any idea how to achieve that?
the answer I get look like this:
10.0.0.190
10.0.0.117
10.0.0.151
but I need it like this:
10.0.0.190,10.0.0.117,10.0.0.151
A quick fix to your Jinja2 template:
{% for host in groups['dbnodes'] -%}
{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}{% if not loop.last %},{% endif %}
{%- endfor %}

Variable in Jinja2 For Loop

We're trying to come up with a way to use ansible facts within jinja2 For Loops.
For example, I want to get all servers that belong to my memcached group as well as a group based on release (something like tag_release_dev or tag_release_prod). When I try to use {{ tt_release }} within the For Loop it evaluates {{ tt_release }} rather than the value of the variable. Is there a way to use a variable within the loop definition?
{% for host in groups["tag_function_mem"] | intersect(groups["tag_release_{{ tt_release }}"]) %}
{{ host }}:11211
{%- if not loop.last %},{% endif %}
{%- if loop.last %}"{% endif %}
{% endfor %}
{% endif %}
it evaluates {{ tt_release }} rather than the value of the variable.
This is because you already are inside a expression. You can not nest expressions - and you don't need to.
What you want is to concatenate the string "tag_release_" and the variable tt_release. In Jinja2 concatenation is done with a +.
{% for host in groups["tag_function_mem"] | intersect(groups["tag_release_" + tt_release]) %}

Resources