Home > Blockchain >  Apply map filter to value of dictionary with ansible/jinja2
Apply map filter to value of dictionary with ansible/jinja2

Time:11-20

I'm trying to write an ansible playbook that outputs some details about a system, in a nicely formatted way. In particular, disk sizes.

Input variable looks something like:

- friendly_name: 'disk1 name'
  size: 123456
- friendly_name: 'disk2 name'
  size: 654321
{{ dict(ansible_facts.disks | json_query('[].[friendly_name, size]')) }}

I'm struggling to come up with a way to apply a function to the 'value' of the dictionary (or the second value of the nested list, prior to converting it to a dict) - I'd like to apply human_readable(unit='G') or similar, without resorting to set_fact or FilterPlugins

So ideally I'd have an output variable of the form:

{'disk1 name': '1024G', 'disk2 name': '8192G'}

CodePudding user response:

You could split the dictionary ansible_facts.disks into two lists, one containing the size and the other one the friendly name, then apply the human_readable filter to the list containing the size with the map filter, then zip the two lists back together.

Given the task:

- debug:
    msg: "{{ dict(
           ansible_facts.disks | map(attribute='friendly_name') | 
           zip(ansible_facts.disks | map(attribute='size') | map('human_readable','unit','G'))
         ) }}"
  vars:
    ansible_facts:
      disks:
        - friendly_name: 'disk1 name'
          size: 1099511627776
        - friendly_name: 'disk2 name'
          size: 8796093022208

This yields:

TASK [debug] ********************************************************************
ok: [localhost] => {
    "msg": {
        "disk1 name": "1024.00 Gb",
        "disk2 name": "8192.00 Gb"
    }
}

CodePudding user response:

Without the formatting you could simply use items2dict


    - debug:
        msg: "{{ ansible_facts.disks|items2dict(key_name='friendly_name',
                                                value_name='size') }}"

gives

  msg:
    disk1 name: 1099511627776
    disk2 name: 8796093022208

Use Jinja to change the format, e.g.

    - debug:
        msg: "{{ _disks|from_yaml }}"
      vars:
        _disks: |
          {% for i in ansible_facts_disks %}
          {{ i.friendly_name }}: {{ i.size|human_readable(unit='G') }}
          {% endfor %}

gives

  msg:
    disk1 name: 1024.00 GB
    disk2 name: 8192.00 GB
  • Related