Search code examples
pythonpython-3.xansiblejinja2

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


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?


Solution

  • 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