Search code examples
ansibleansible-2.xansible-facts

Ansible_devices filter dicts for "holders" and "size" value


I'm trying to get the "holders" and "size" value of each dictionary. I managed this far but whatever i try after this does not work. I'm interested in learning which kind of data structure this is and how to filter it. Going through the Ansible docs gives me no real pointers, neither did posts on this site or google. I'm first just trying to get at "holders" after i'll try to add "size" also. Holders is a list in a dictionary, what am i missing here?

- name: "test ansible_devices"
  hosts: localhost
  tasks:
    - debug:
        var: "{{ ansible_devices|dict2items|selectattr('key','match','^sd.*')|map(attribute='value.partitions') }}"

output:

ok: [localhost] => {
    "msg": [
        {
            "sdd1": {
                "holders": [],
                "links": {
                    "ids": [
                        "lvm-pv-uuid-xxx"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "sectors": "4192256",
                "sectorsize": 512,
                "size": "2.00 GB",
                "start": "2048",
                "uuid": null
            }
        },
        {
            "sdb1": {
                "holders": [
                    "vg_app-lv_app"
                ],
                "links": {
                    "ids": [
                        "lvm-pv-uuid-xxx"
                    ],
                    "labels": [],
                    "masters": [
                        "dm-2"
                    ],
                    "uuids": []
                },
                "sectors": "20969472",
                "sectorsize": 512,
                "size": "10.00 GB",
                "start": "2048",
                "uuid": null
            }
        },
        {
            "sdc1": {
                "holders": [
                    "vg_system-lv_system_home"
                ],
                "links": {
                    "ids": [
                        "lvm-pv-uuid-xxx"
                    ],
                    "labels": [],
                    "masters": [
                        "dm-3"
                    ],
                    "uuids": []
                },
                "sectors": "2095071",
                "sectorsize": 512,
                "size": "1022.98 MB",
                "start": "2048",
                "uuid": null
            }
        },
        {
            "sda1": {
                "holders": [],
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "xxx"
                    ]
                },
                "sectors": "2097152",
                "sectorsize": 512,
                "size": "1.00 GB",
                "start": "2048",
                "uuid": "xxx"
            },
            "sda2": {
                "holders": [
                    "vg_system-lv_system_swap",
                    "vg_system-lv_system_log",
                    "vg_system-lv_system_root",
                    "vg_system-lv_system_home"
                ],
                "links": {
                    "ids": [
                        "lvm-pv-uuid-xxx"
                    ],
                    "labels": [],
                    "masters": [
                        "dm-0",
                        "dm-1",
                        "dm-3",
                        "dm-4"
                    ],
                    "uuids": []
                },
                "sectors": "60815360",
                "sectorsize": 512,
                "size": "29.00 GB",
                "start": "2099200",
                "uuid": null
            }
        }
    ]
}

desired output:

            "sdd1": {
                "holders": [],
                "size": "2.00 GB",

            "sdb1": {
                "holders": [
                    "vg_app-lv_app"
                "size": "30.00 GB",

            "sdc1": {
                "holders": [
                    "vg_system-lv_system_home"
                "size": "10.00 GB",

            "sda1": {
                "holders": [],
                "size": "2.00 GB",

            "sda2": {
                "holders": [
                    "vg_system-lv_system_swap",
                    "vg_system-lv_system_log",
                    "vg_system-lv_system_root",
                    "vg_system-lv_system_home"
                "size": "29.00 GB",

I tried:

   - debug:
       msg: "{{ansible_devices|dict2items|selectattr('key','match','^sd.*')|map(attribute='value.partitions')|map(attribute='holders') }}"

error:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'holders'"}

I tried:

   - debug:
       msg: "{{ansible_devices|dict2items|selectattr('key','match','^sd.*')|map(attribute='value.partitions')|flatten|map(attribute='holders') }}"

error:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'holders'"}

I tried:

- name: "test ansible_devices"
  hosts: localhost
  tasks:
    - debug:
        var: "{{  ansible_devices |dict2items|selectattr('key','match','^sd.*')|map(attribute='value.partitions')|selectattr('holders','match','vg_system-lv_system_log')}}"

error:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'holders'\n\n"}

I tried:

- name: "test ansible_devices"
  hosts: localhost
  tasks:
    - debug:
        var: "{{ ansible_devices|dict2items|selectattr('key','match','^sd.*')|map(attribute='value.partitions')|json_query('holders') }}"

error:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'holders'"}

I tried, just to see if i could get at any value with json_query:

- name: "test ansible_devices"
  hosts: localhost
  vars:
          - query: "dm-1"
  tasks:
    - debug:
        var: "{{  ansible_devices |json_query('query')}}"

error:

fatal: [localhost]: FAILED! => {"msg": "template error while templating string: Expected an expression, got 'end of print statement'. String: {{}}"}

I tried it also with a loop but that was a hopeless try with no results.


Solution

  • Given the partitions

    partitions: "{{ ansible_devices|
                    dict2items|
                    selectattr('key','match','^sd.*')|
                    map(attribute='value.partitions') }}"
    

    Get the keys, and values and create the dictionary

    _keys: "{{ partitions|
               json_query('[].keys(@)')|flatten }}"
    _vals: "{{ partitions|
               json_query('[].*.{holders: holders, size: size}')|flatten }}"
    _dict: "{{ dict(_keys|zip(_vals)) }}"
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        _ansible_devices:
          sda:
            partitions:
              sda1:
                holders: []
                sectors: 2097152
                size: 1.00 GB
                start: 2048
              sda2:
                holders: []
                sectors: 60815360
                size: 29.00 GB
                start: 2099200
    
        partitions: "{{ _ansible_devices|
                        dict2items|
                        selectattr('key','match','^sd.*')|
                        map(attribute='value.partitions') }}"
        _keys: "{{ partitions|
                   json_query('[].keys(@)')|flatten }}"
        _vals: "{{ partitions|
                   json_query('[].*.{holders: holders, size: size}')|flatten }}"
        _dict: "{{ dict(_keys|zip(_vals)) }}"
    
      tasks:
    
        - debug:
            var: partitions
        - debug:
            var: _keys
        - debug:
            var: _vals
        - debug:
            var: _dict