template for rows in a table

Hi,

Looking for a template which prints the list’s items in the horizontal (rows) of a tables.
I have the below list and trying to print as a table.

vars:
color:

  • green
  • red
  • yellow
  • blue
    cities:
  • toronto
  • montreal
  • mumbai
  • dubai
    lang:
  • English
  • French
  • Hindi
  • Arabic

and a desired out as below

color cities lang
green toronto English
red montreal French
yellow mumbai hindi
blue dubai bangla

Declare the list of columns

  fnames: [color, cities, lang]

and get the columns

  cols: |
    {% filter from_yaml %}
    {% for i in fnames %}
    - {{ lookup('vars', i ) }}
    {% endfor %}
    {% endfilter %}

gives

  cols:
    - [green, red, yellow, blue]
    - [toronto, montreal, mumbai, dubai]
    - [English, French, Hindi, Arabic]

Find the maximal lengths

  max: "{{ cols|map('map', 'length')|map('max') }}"

gives

  max: [6, 8, 7]

and create the list of formats

  frmt: |
    {% filter from_yaml %}
    {% for i in max %}
    - '%-{{ i }}s '
    {% endfor %}
    {% endfilter %}

gives

  frmt: ['%-6s ', '%-8s ', '%-7s ']

Get the rows

    - set_fact:
        rows: "{{ rows|d(cols.0)|zip(item)|map('flatten') }}"
      loop: "{{ cols[1:] }}"

gives

  rows:
    - [green, toronto, English]
    - [red, montreal, French]
    - [yellow, mumbai, Hindi]
    - [blue, dubai, Arabic]

and write the table

    - debug:
        msg: |
          {% for i in range(fnames|length) %}
          {{ frmt[i] % fnames[i] }}{% endfor %}

          {% for j in rows %}
          {% for i in range(fnames|length) %}
          {{ frmt[i] % j[i] }}{% endfor %}

          {% endfor %}

gives

  msg: |-
    color cities lang
    green toronto English
    red montreal French
    yellow mumbai Hindi
    blue dubai Arabic

Hi Vladimir,

I am really interested in learning how you provide such code.
From where can I learn more?

Warm regards,
Abhi

Hi Vladimir,

Thanks . It helps to learn a lot.
Any recommended link to learn the jinja2 formatting?.

in btw, the “cols” are printed as like below (not as [green, red, yellow, blue]).
is there ansible/jinja version conflict or I miss a bit?

  • name: playbook to print the list as table
    hosts: localhost
    vars:
    color:
  • green
  • red
  • yellow
  • blue
    cities:
  • toronto
  • montreal
  • mumbai
  • dubai
    lang:
  • English
  • French
  • Hindi
  • Arabic
    fnames: [color, cities, lang]
    cols: |
    {% filter from_yaml %}
    {% for i in fnames %}
  • {{ lookup(‘vars’, i ) }}
    {% endfor %}
    {% endfilter %}
    max: “{{ cols|map(‘map’, ‘length’)|map(‘max’) }}”
    frmt: |
    {% filter from_yaml %}
    {% for i in max %}
  • '%-{{ i }}s ’
    {% endfor %}
    {% endfilter %}

tasks:

  • name: print the cols
    ansible.builtin.debug:
    msg: “{{cols}}”

  • name: print the max
    ansible.builtin.debug:
    msg: “{{max}}”

  • name: print the frmt
    ansible.builtin.debug:
    msg: “{{frmt}}”

  • set_fact:
    rows: “{{ rows|d(cols.0)|zip(item)|map(‘flatten’) }}”
    loop: “{{ cols[1:] }}”

  • name: print the frmt
    ansible.builtin.debug:
    msg: “{{rows}}”

And the output is as below

PLAY [playbook to print the list as table] ********************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
Friday 20 October 2023 18:24:15 +0300 (0:00:00.036) 0:00:00.036 ********
ok: [localhost]

TASK [print the cols] *****************************************************************************************************************
Friday 20 October 2023 18:24:18 +0300 (0:00:02.702) 0:00:02.738 ********
ok: [localhost] => {
“msg”: [
[
“green”,
“red”,
“yellow”,
“blue”
],
[
“toronto”,
“montreal”,
“mumbai”,
“dubai”
],
[
“English”,
“French”,
“Hindi”,
“Arabic”
]
]
}

TASK [print the max] ******************************************************************************************************************
Friday 20 October 2023 18:24:18 +0300 (0:00:00.125) 0:00:02.863 ********
ok: [localhost] => {
“msg”: [
6,
8,
7
]
}

TASK [print the frmt] *****************************************************************************************************************
Friday 20 October 2023 18:24:18 +0300 (0:00:00.109) 0:00:02.973 ********
ok: [localhost] => {
“msg”: [
"%-6s ",
"%-8s ",
"%-7s "
]
}

TASK [set_fact] ***********************************************************************************************************************
Friday 20 October 2023 18:24:18 +0300 (0:00:00.111) 0:00:03.085 ********
ok: [localhost] => (item=[‘toronto’, ‘montreal’, ‘mumbai’, ‘dubai’])
ok: [localhost] => (item=[‘English’, ‘French’, ‘Hindi’, ‘Arabic’])

TASK [print the frmt] *****************************************************************************************************************
Friday 20 October 2023 18:24:18 +0300 (0:00:00.075) 0:00:03.161 ********
ok: [localhost] => {
“msg”: [
[
“green”,
“toronto”,
“English”
],
[
“red”,
“montreal”,
“French”
],
[
“yellow”,
“mumbai”,
“Hindi”
],
[
“blue”,
“dubai”,
“Arabic”
]
]
}

PLAY RECAP ****************************************************************************************************************************
localhost : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

the "cols" are printed as like below (not as [green, red, yellow,
blue]).
...
    "msg": [
        [
            "green",
            "toronto",
            "English"
        ],
        [
            "red",
            "montreal",
            "French"
        ],
        [
            "yellow",
            "mumbai",
            "Hindi"
        ],
        [
            "blue",
            "dubai",
            "Arabic"
        ]
    ]

>
>> msg: |-
>> color cities lang
>> green toronto English
>> red montreal French
>> yellow mumbai Hindi
>> blue dubai Arabic

What you see depends on the callback. Try

  > ANSIBLE_STDOUT_CALLBACK=yaml ansible-playbook playbook.yml

Learn about formatting:

* Try filters: *to_yaml*, *to_nice_yaml*. Try the option *indent*
* Try the filter *indent*
* Try other callbacks

Links:

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html#formatting-data-yaml-and-json
https://jinja.palletsprojects.com/en/latest/templates/#jinja-filters.indent
https://docs.ansible.com/ansible/latest/plugins/callback.html
https://docs.ansible.com/ansible/latest/collections/index_callback.html
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-stdout-callback

Thanks Vladimir, … Very much helpful …