Jinja2 template and generating a table with fixed columns

OK, I want to create a list using a template. This consists of two columns, one for the host portion of the IPV4 address (the fourth number of the IPv4 address) and one for the host name. The host names and IP addresses are listed in the inventory.

Example:

192.168.2.1 with the host name = host1
192.168.2.35 with the host name = host2
192.168.2.205 with the host name = host3

Using

{% for host in groups[‘intra’] %}
{{ (hostvars[host][‘host_ipv4’] | split(‘.’)).3 }} {{ host }}
{% endfor %}

I generate the following:

1 host1
35 host2
205 host3

However, I need a list where the first column is filled with spaces so that it becomes a “nice” list, such as this one:

1   host1
35  host2
205 host3

Or, to put it another way: the first column should always be padded with spaces to a fixed column width, regardless of whether it contains “only” a letter or number, or even a long name.

I’ve tried so many things with Jinja filters, but nothing seems to work. It’s probably very simple, but I just have a PEBKEC problem.

Does anyone have any ideas on how to do this in the cleanest way possible?

I am grateful for any information!

1 Like

This is one of the cases where creating / using a filter plugin is likely the best choice. While it is possible to do this with several set_fact / vars (depending on how inefficient is still fine) and Jinja2 expressions, a dedicated filter plugin will result in a much more maintainable (and likely also reusable!) result (which will also be more efficient).

Depending on how important the exact formatting is, the community.general.to_prettytable filter could be useful.

1 Like

You can use the formating operator % like this:

{% for host in groups[‘intra’] %}
{{ '%-4s' % ((hostvars[host][‘host_ipv4’] | split(‘.’)).3) }} {{ host }}
{% endfor %}

You can also use the format filter for more modern approach:

4 Likes

Damn! I thought it would be easier than this! Why? O.K. let me expalin my thoughts:

The following lines:

{{'{:31}'.format('hello') }} TEXT
{{'{:31}'.format('community') }} TEXT
{{'{:31}'.format('I wish you a happy new') }} TEXT
{{'{:31}'.format('year → 2026!') }} TEXT

produces:

hello                           TEXT
community                       TEXT
I wish you a happy new          TEXT
year → 2026!                    TEXT

My naive thinking whispered to me, “Just replace the string in quotation marks with a variable and everything will be fine!”

Well, far from it, because when I add the following line to the jinja2 file:

{{'{:31}'.format('{{ host }}') }} TEXT

I crash and burn spectacularly:

{{ host }}                      TEXT

Damn it, the variable isn’t being replaced, but rather the name of the variable is being output.

1 Like

YYMD!

It works and it works fine - muchas gracias!

Just do:

{{'{:31}'.format(host) }} TEXT

In other words, in a code enclosed by {{ and }}, variable interpolation is done so you don’t enclose variables with another {{ and }}. Just use variable names as they are.

2 Likes