Search code examples
ansiblejinja2

Using Ansible jinja2 list feature returns more that the list with ansible hostvars


I am trying to use ansible hostvars to select a group of disks, here is my code:

- name: Output disk information
  debug:
    var: hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list

What I expect is a list of devices beginning with nvme or an empty list, but I get the var: value (query if you will) back as well as the list:

ok: [cm42.ag6hq.net] => {
    "hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list": [
        "nvme0n1"
    ]
}
ok: [cm43.ag6hq.net] => {
    "hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list": []
}

What I expected back was:

ok: [cm42.ag6hq.net] => {
    [
        "nvme0n1"
    ]
}
ok: [cm43.ag6hq.net] => {
    []
}

So when I use this query within the with_items: context, it tries to process the whole query, not the resulting list (which is what I expected):

failed: [cm42.ag6hq.net] (item=hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list) => {"ansible_loop_var": "item", "changed": false, "item": "hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list", "msg": "Device /dev/hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list not found."}

Where am I going off the rails here?


Solution

  • Let me see if I can simplify: playbook:

        - name: Get list of NVMe block devices
          set_fact:
            nvme_devices: "{{ hostvars[inventory_hostname]['ansible_devices'] | dict2items | selectattr('key', 'match', '^nvme') | map(attribute='value') | list }}"
    
        - name: Create partitions on the NVMe disks
          parted:
            device: "/dev/{{ item }}"
            number: 1
            state: present
            align: optimal
            unit: "%"
            part_type: primary
            fs_type: ext4
          with_items: "{{ nvme_devices }}"
    

    Output:

    TASK [Create partitions on the NVMe disks] *****************************************************************************************************************************
    failed: [cm41.ag6hq.net] (item={'virtual': 1, 'links': {'ids': ['nvme-INTEL_SSDPEKNU010TZ_PHKA220103081P0B', 'nvme-eui.0000000001000000e4d25c78cf5e5501'], 'uuids': [], 'labels': [], 'masters': []}, 'vendor': None, 'model': 'INTEL SSDPEKNU010TZ', 'sas_address': None, 'sas_device_handle': None, 'serial': 'PHKA220103081P0B', 'removable': '0', 'support_discard': '512', 'partitions': {}, 'rotational': '0', 'scheduler_mode': 'none', 'sectors': '2000409264', 'sectorsize': '512', 'size': '953.87 GB', 'host': 'Non-Volatile memory controller: Intel Corporation Device f1aa (rev 03)', 'holders': []}) => {"ansible_loop_var": "item", "changed": false, "err": "Error: Could not stat device /dev/{virtual: - No such file or directory.\n", "item": {"holders": [], "host": "Non-Volatile memory controller: Intel Corporation Device f1aa (rev 03)", "links": {"ids": ["nvme-INTEL_SSDPEKNU010TZ_PHKA220103081P0B", "nvme-eui.0000000001000000e4d25c78cf5e5501"], "labels": [], "masters": [], "uuids": []}, "model": "INTEL SSDPEKNU010TZ", "partitions": {}, "removable": "0", "rotational": "0", "sas_address": null, "sas_device_handle": null, "scheduler_mode": "none", "sectors": "2000409264", "sectorsize": "512", "serial": "PHKA220103081P0B", "size": "953.87 GB", "support_discard": "512", "vendor": null, "virtual": 1}, "msg": "Error while getting device information with parted script: '/usr/sbin/parted -s -m /dev/{'virtual': 1, 'links': {'ids': ['nvme-INTEL_SSDPEKNU010TZ_PHKA220103081P0B', 'nvme-eui.0000000001000000e4d25c78cf5e5501'], 'uuids': [], 'labels': [], 'masters': []}, 'vendor': None, 'model': 'INTEL SSDPEKNU010TZ', 'sas_address': None, 'sas_device_handle': None, 'serial': 'PHKA220103081P0B', 'removable': '0', 'support_discard': '512', 'partitions': {}, 'rotational': '0', 'scheduler_mode': 'none', 'sectors': '2000409264', 'sectorsize': '512', 'size': '953.87 GB', 'host': 'Non-Volatile memory controller: Intel Corporation Device f1aa (rev 03)', 'holders': []} -- unit '%' print'", "out": "", "rc": 1}
    failed: [cm42.ag6hq.net] (item={'virtual': 1, 'links': {'ids': ['nvme-INTEL_SSDPEKNU010TZ_PHKA219401S71P0B', 'nvme-eui.0000000001000000e4d25cc6ae5c5501'], 'uuids': [], 'labels': [], 'masters': []}, 'vendor': None, 'model': 'INTEL SSDPEKNU010TZ', 'sas_address': None, 'sas_device_handle': None, 'serial': 'PHKA219401S71P0B', 'removable': '0', 'support_discard': '512', 'partitions': {}, 'rotational': '0', 'scheduler_mode': 'none', 'sectors': '2000409264', 'sectorsize': '512', 'size': '953.87 GB', 'host': 'Non-Volatile memory controller: Intel Corporation Device f1aa (rev 03)', 'holders': []}) => {"ansible_loop_var": "item", "changed": false, "err": "Error: Could not stat device /dev/{virtual: - No such file or directory.\n", "item": {"holders": [], "host": "Non-Volatile memory controller: Intel Corporation Device f1aa (rev 03)", "links": {"ids": ["nvme-INTEL_SSDPEKNU010TZ_PHKA219401S71P0B", "nvme-eui.0000000001000000e4d25cc6ae5c5501"], "labels": [], "masters": [], "uuids": []}, "model": "INTEL SSDPEKNU010TZ", "partitions": {}, "removable": "0", "rotational": "0", "sas_address": null, "sas_device_handle": null, "scheduler_mode": "none", "sectors": "2000409264", "sectorsize": "512", "serial": "PHKA219401S71P0B", "size": "953.87 GB", "support_discard": "512", "vendor": null, "virtual": 1}, "msg": "Error while getting device information with parted script: '/usr/sbin/parted -s -m /dev/{'virtual': 1, 'links': {'ids': ['nvme-INTEL_SSDPEKNU010TZ_PHKA219401S71P0B', 'nvme-eui.0000000001000000e4d25cc6ae5c5501'], 'uuids': [], 'labels': [], 'masters': []}, 'vendor': None, 'model': 'INTEL SSDPEKNU010TZ', 'sas_address': None, 'sas_device_handle': None, 'serial': 'PHKA219401S71P0B', 'removable': '0', 'support_discard': '512', 'partitions': {}, 'rotational': '0', 'scheduler_mode': 'none', 'sectors': '2000409264', 'sectorsize': '512', 'size': '953.87 GB', 'host': 'Non-Volatile memory controller: Intel Corporation Device f1aa (rev 03)', 'holders': []} -- unit '%' print'", "out": "", "rc": 1}
    

    It's evident by the "Error: Could not stat device /dev/{virtual: - No such file or directory.\n" error that nvme_devices is not a list of device names, but rather apparently the whole device (see item='virtual... in the output.

    So why doesn't "{{ hostvars[inventory_hostname]['ansible_devices'] | dict2items | selectattr('key', 'match', '^nvme') | map(attribute='value') | list }}" create a list of names?

    ANSWER: because the map attribute is 'value' and not 'key'

    "{{ hostvars[inventory_hostname]['ansible_devices'] | dict2items | selectattr('key', 'match', '^nvme') | map(attribute='key') | list }}" will create a list of names that begin with nvme.