Ansible - Getting List Values from within a Dictionary (Regsiter Variable)

Viewed 2083

So I'm working on some audit points using Ansible for many of the servers we support. In most cases, I have had to use the shell modules to get the data I want and then write some files based on pass/fail cases. In a lot of situations, this has been the easier way to work with the output data. First, I realize this isn't necessarily Ansible's forte. I guess at some point it was pitched to the company that it could do this pretty easily, and I would agree - it's easier in many ways than just writing a custom python/BASH script to do the same. So - I do realize I'm bending the concept of Ansible a bit here for reporting, rather than configuration/state management. However; I like the tool and want to show the company we can get a lot of value from it.

While I could do this section easily using the shell module, I would like to learn Ansible a bit better. So thought I would post this question.

I'm using the Yum module to just get a repolist on the target hosts. But I've been running into confusion on just how to extract the list values nested in the output dictionary. I have done some checking on the types and as far as I can tell - the 'results' variable is a dictionary, with the output in in a list. What I want to do, is get the key/values from the list and then perform some other tasks based on that output. But for the life of me - I can't figure out how to do this!

Ideally - I would like to either use some 'when' module statements based on the output (When the repo ID is.. do this.. for example) or at least be able to store them in a variable to work with the data. So from this output, I just want to get the repoid and if it's enabled. How can I get these values from the nested list?

Simple Playbook:

---
- hosts: localhost
  become: yes
  tasks:

  - name: Section 1.1 - Check Yum Repos
    yum:
      list: repos
    register: section1_1

  - name: Debug
    debug:
      var: section1_1

Here is my output from the debug task in this playbook:

TASK [Debug] ****************************************************************************************************************************************************
ok: [localhost] => {
    "section1_1": {
        "changed": false,
        "failed": false,
        "results": [
            {
                "repoid": "ansible",
                "state": "enabled"
            },
            {
                "repoid": "epel",
                "state": "enabled"
            },
            {
                "repoid": "ol7_UEKR6",
                "state": "enabled"
            },
            {
                "repoid": "ol7_latest",
                "state": "enabled"
            }
        ]
    }
}

I suspect this might be easy for someone out there. I've been trying this and that's for quite a while now and finally got to the point where I thought I would just ask :)

2 Answers

As the output of registered in section1_1 is a list of dictionaries. We can loop through each item, to get the dictionary keys.

Example:

- name: Get the first repo's repoid and state
  debug:
    msg: "Repo ID: {{ results[0]['repoid'] }}, is {{ results[0]['state'] }}"
# This will show -- Repo ID: ansible, is enabled

Similarly we can access other elements with their number.

Or we can loop through each element of array:

- name: loop through array and conditionally do something
  debug:
    msg: "Repo ID is {{ item.repoid }}, so I am going to write a playbook."
  when: item.repoid == 'ansible'
  loop: "{{ results }}"

Q: "Get the key/values from the list."

A: There are more options. Given the simplified data below

    section1_1:
      changed: false,
      failed: false,
      results:
        - {repoid: ansible, state: enabled}
        - {repoid: epel, state: enabled}
        - {repoid: test9, state: disabled}
  • Use map to create a list of all repos. For example
    - set_fact:
        keys_all: "{{ section1_1.results|
                      map(attribute='repoid')|
                      list }}"
    - debug:
        var: keys_all

gives

  keys_all:
  - ansible
  - epel
  - test9

  • Use map and selectattr to create a list of enabled repos. For example
    - set_fact:
        keys_ena: "{{ section1_1.results|
                      selectattr('state', 'eq', 'enabled')|
                      map(attribute='repoid')|
                      list }}"
    - debug:
        var: keys_ena

gives

  keys_ena:
  - ansible
  - epel

Use items2dict to create a dictionary. For example

    - set_fact:
        dict: "{{ section1_1.results|
                  items2dict(key_name='repoid', value_name='state') }}"
    - debug:
        var: dict

gives

  dict:
    ansible: enabled
    epel: enabled
    test9: disabled
Related