Home > database >  Equivalent to list(d.items())[0] in Jinja2
Equivalent to list(d.items())[0] in Jinja2

Time:10-19

I switched from using Python2 to Python3 on the Ansible controller side.
I was using the expression {{ osd['data_devices'].items()[0][0] }} in a Jinja2 template loop {% for osd in osd_spec %} to get the key paths from the below dictionary:

osd_spec:
   - spec_name: osd_spec1
     data_devices:
      paths:
      - /dev/sdg
      - /dev/sdh
   - spec_name: osd_spec2
     data_devices:
      paths:
      - /dev/sda
      - /dev/sdb

After switching to Python3 the expression did not work anymore and I am getting the error:

dict_items object has no element 0

I then figured out that the items() function in Python3 returns a view object instead of a list and though, as suggested here, the output should be wrapped by a list.

Trying list(d.items())[0][0] in Python3 works as expected.
What would be the equivalent expression in Jinja2?

I tried {{ osd['data_devices'].items() | list[0] }}, but, this didn't work.

Any ideas?

CodePudding user response:

On your dictionary, you could use the keys() function and do:

{{ (osd.data_devices.keys() | list)[0] }}

Or use the dict2items filter and do:

{{ (osd.data_devices | dict2items)[0].key }}

As a demonstration, given:

    - block:
      - debug:
          msg: >-
            {% for osd in osd_spec %}
            {{- (osd.data_devices | dict2items)[0].key -}}
            {% endfor %}

      - debug:
          msg: >-
            {% for osd in osd_spec %}
            {{- (osd.data_devices.keys() | list)[0] -}}
            {% endfor %}

      vars:
        osd_spec:
          - spec_name: osd_spec
            data_devices:
              paths:
              - /dev/sdg
              - /dev/sdh

It will yield:

TASK [debug] ******************************************************
ok: [localhost] => 
  msg: paths

TASK [debug] ******************************************************
ok: [localhost] => 
  msg: paths

CodePudding user response:

Grouping the statement will do the job

{{ (osd.data_devices.items()|list)[0][0] }}

Defining a variable will also work

  {% set paths = osd.data_devices.items() | list %}
  {{ paths[0][0] }}
  • Related