Home > Software engineering >  Ansible - remove empty elements from the list
Ansible - remove empty elements from the list

Time:08-03

I have an ansible output from which I want to remove all empty (none) elements for a specific attribute. Here is the example list:

"resources": [
    {
        "id": "9c40900909",
        "name": "some_name1"
    },
    {
        "id": "pc4b09090"
    },
    {
        "id": "8lknkkn45"
    },
    {
        "id": "9df40900909",
        "name": "some_name2"
    }
]

Here is how I reduced the list to be just "resources" with attribute "name":

- set_fact:
    resources_names: "{{ output.resources | map(attribute='name') }}"

Problem with that is that I get the elements that does not have any value for the name. These are "AnsibleUndefined" in the following output:

- debug:
    msg: resources_names list is "{{ resources_names }}"
ok: [localhost] => {
   "msg": "resources_names list is \"['some_name1', AnsibleUndefined, AnsibleUndefined, 'some_name2']\""
}

I tried to remove it with reject and regexp but that's not working.

- set_fact:
    list2: "{{ resources_names | reject('match', '^$') | list }}"

Same with this one:

- set_fact:
    resources_names: "{{ output.resources | map(attribute='name') | rejectattr('name', 'none') }}"

Any idea?

Thanks.

CodePudding user response:

In a nutshell:

---
- hosts: localhost
  gather_facts: false

  vars:
    resources: [
        {
            "id": "9c40900909",
            "name": "some_name1"
        },
        {
            "id": "pc4b09090"
        },
        {
            "id": "8lknkkn45"
        },
        {
            "id": "9df40900909",
            "name": "some_name2"
        }
    ]

  tasks:
    - debug:
        msg: "{{ resources | selectattr('name', 'defined') | map(attribute='name') }}"

which gives:

$ ansible-playbook /tmp/play.yml 
[WARNING]: No inventory was parsed, only implicit localhost is available

PLAY [localhost] *******************************************************************************************************************************************************************************

TASK [debug] ***********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "some_name1",
        "some_name2"
    ]
}

PLAY RECAP *************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Note for your next question: please make sure you double check your examples and paste valid json/yaml data in your question. Thanks

CodePudding user response:

Use the filter json_query. This filter ignores missing attributes

resources_names: "{{ output.resources|json_query('[].name') }}"

gives

resources_names:
  - some_name1
  - some_name2
  • Related