0

I have an external data file with the following data structure:

---
server1:
  service_name:
    jboss_prod_1:
      enabled: "True"
      started: "True"
    jboss_prod_2:
      enabled: "True"
      started: "True"
    jboss_prod_3:
      enabled: "True"
      started: "True"
    jboss_prod_4:
      enabled: "False"
      started: "False"
    jboss_prod_5:
      enabled: "False"
      started: "False"

server2:
  service_name:
    jboss_prod_3:
      enabled: "True"
      started: "True"
    jboss_prod_5:
      enabled: "True"
      started: "True"
    jboss_prod_7:
      enabled: "True"
      started: "True"
    jboss_prod_9:
      enabled: "False"
      started: "False"
    jboss_prod_13:
      enabled: "False"
      started: "False"

I've been trying to find a way to get down to something with an output that shows the server name, services on it and their 2 values of enabled and started. So far, I can get at the 3rd layer pretty well, but not all the way to the 4th, since the "service name" value is unknown -- i cannot make assumptions as to it's value or order.

This works:

---
- name: test creating a dictionary from external file
  hosts: localhost
  gather_facts: False
  tasks:
    - name: load the file
      include_vars:
        name: service_map
        file: vars/service_map.yml

    - name: SHOW ME THE MONEY!
      loop: "{{ lookup('dict', service_map) }}"
      debug:
        msg: "{{item.value}}"                                                                                                                                                                      
      with_dict:
        - "{{item.value.service_name}}"

and produces this output:

PLAY [test creating a dictionary from external file] **********************************************************************************************************************************************

TASK [load the file] ******************************************************************************************************************************************************************************
ok: [localhost]

TASK [SHOW ME THE MONEY!] *************************************************************************************************************************************************************************
ok: [localhost] => (item={'value': u'server1', 'key': u'key'}) => {
    "msg": "server1"
}
ok: [localhost] => (item={'value': {u'service_name': {u'jboss_prod_2': {u'started': u'True', u'enabled': u'True'}, u'jboss_prod_3': {u'started': u'True', u'enabled': u'True'}, u'jboss_prod_1': {u'started': u'True', u'enabled': u'True'}, u'jboss_prod_4': {u'started': u'False', u'enabled': u'False'}, u'jboss_prod_5': {u'started': u'False', u'enabled': u'False'}}}, 'key': u'value'}) => {
    "msg": {
        "service_name": {
            "jboss_prod_1": {
                "enabled": "True", 
                "started": "True"
            }, 
            "jboss_prod_2": {
                "enabled": "True", 
                "started": "True"
            }, 
            "jboss_prod_3": {
                "enabled": "True", 
                "started": "True"
            }, 
            "jboss_prod_4": {
                "enabled": "False", 
                "started": "False"
            }, 
            "jboss_prod_5": {
                "enabled": "False", 
                "started": "False"
            }
        }
    }
}
ok: [localhost] => (item={'value': u'server2', 'key': u'key'}) => {
    "msg": "server2"
}
ok: [localhost] => (item={'value': {u'service_name': {u'jboss_prod_3': {u'started': u'True', u'enabled': u'True'}, u'jboss_prod_5': {u'started': u'True', u'enabled': u'True'}, u'jboss_prod_9': {u'started': u'False', u'enabled': u'False'}, u'jboss_prod_7': {u'started': u'True', u'enabled': u'True'}, u'jboss_prod_13': {u'started': u'False', u'enabled': u'False'}}}, 'key': u'value'}) => {
    "msg": {
        "service_name": {
            "jboss_prod_13": {
                "enabled": "False", 
                "started": "False"
            }, 
            "jboss_prod_3": {
                "enabled": "True", 
                "started": "True"
            }, 
            "jboss_prod_5": {
                "enabled": "True", 
                "started": "True"
            }, 
            "jboss_prod_7": {
                "enabled": "True", 
                "started": "True"
            }, 
            "jboss_prod_9": {
                "enabled": "False", 
                "started": "False"
            }
        }
    }
}

PLAY RECAP ****************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0 

But I need to see if I can get something that lists the server, the service name and then the 2 states. Hopefully that's enough info that someone can help me out. I'm comparatively new to Ansible and iterating over complex data structures is killing me.

1 Answers1

0

Q: Lists the server, the service name and then the 2 states.

A: The task below does the job

- set_fact:
    service_map2: "{{ service_map2|default({})|
                      combine({item.key:
                               item.value.service_name}) }}"
  loop: "{{ service_map|dict2items }}"

Dictionary service_map2 "lists the server, the service name and then the 2 states"

"service_map2": {
    "server1": {
        "jboss_prod_1": {
            "enabled": "True", 
            "started": "True"
        }, 
        "jboss_prod_2": {
            "enabled": "True", 
            "started": "True"
        }, 
        ...

Notes

1) Use json_query to select information from the dictionary. For example

A) List services that are not enabled

- set_fact:
    result: "{{ result|default({})|
                combine({item.key: item.value|dict2items|json_query(query)})
                }}"
  loop: "{{ service_map2|dict2items }}"
  vars:
    query: "[?value.enabled=='False'].key"
- debug:
    var: result

gives

"result": {
    "server1": [
        "jboss_prod_4", 
        "jboss_prod_5"
    ], 
    "server2": [
        "jboss_prod_9", 
        "jboss_prod_13"
    ]
}

B) List services that are started

    query: "[?value.started=='True'].key"

gives

"result": {
    "server1": [
        "jboss_prod_2", 
        "jboss_prod_3", 
        "jboss_prod_1"
    ], 
    "server2": [
        "jboss_prod_3", 
        "jboss_prod_5", 
        "jboss_prod_7"
    ]
}

C) List server, service name, and states for services that are not enabled.

    query: "[?value.enabled=='False'].{service: key,
                                       enabled: value.enabled,
                                       started: value.started}"

gives

"result": {
    "server1": [
        {
            "enabled": "False", 
            "service": "jboss_prod_4", 
            "started": "False"
        }, 
        {
            "enabled": "False", 
            "service": "jboss_prod_5", 
            "started": "False"
        }
    ], 
    "server2": [
        {
            "enabled": "False", 
            "service": "jboss_prod_9", 
            "started": "False"
        }, 
        {
            "enabled": "False", 
            "service": "jboss_prod_13", 
            "started": "False"
        }
    ]
}

2) The task below creates the list service_map2 instead of the dictionary.

- set_fact:
    service_map2: "{{ service_map2|default([]) +
                      [{item.key:
                        item.value.service_name}] }}"
  loop: "{{ service_map|dict2items }}"


3) It's not necessary to create service_map2. Original data service_map can be used to list selected server, service name, and 2 states
- set_fact:
    result: "{{ result|default({})|
                combine({item.key: item.value.service_name|
                                   dict2items|
                                   json_query(query)})
                }}"
  loop: "{{ service_map|dict2items }}"
  vars:
    query: "[ ...
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63