AlexW
AlexW

Reputation: 2589

Ansible - pulling data out of a JSON nested dictionary for analysis

I have an Ansible parser which parses some CLI output into the below JSON, the below is a sample for one router only

{
    "ansible_facts": {
        "bgp_summary_facts": [
            {
                "65001_10.10.10.1": {
                    "Data": {
                        "inq": "0",
                        "msgrcvd": "638",
                        "msgsent": "424",
                        "neighbor": "10.10.10.1",
                        "uptime": "01:35:54",
                        "peer_as": "65001",
                        "state": "2",
                        "tblver": "0",
                        "version": "4"
                    }
                }
            },
            {
                "65001_10.10.10.2": {
                    "Data": {
                        "inq": "0",
                        "msgrcvd": "208364",
                        "msgsent": "424",
                        "neighbor": "10.10.10.2",
                        "uptime": "3w1d",
                        "peer_as": "65001",
                        "state": "71",
                        "tblver": "0",
                        "version": "4"
                    }
                }
            },
            {
                "65002_10.10.20.1": {
                    "Data": {
                        "inq": "0",
                        "msgrcvd": "0",
                        "msgsent": "1",
                        "neighbor": "10.10.20.1",
                        "uptime": "never",
                        "peer_as": "65002",
                        "state": "Idle",
                        "tblver": "0",
                        "version": "4"
                    }
                }
            },
            {
                "65010": {
                    "Data": {
                        "inq": "0",
                        "msgrcvd": "22611",
                        "msgsent": "424",
                        "neighbor": "10.10.30.1",
                        "uptime": "2d11h",
                        "peer_as": "65010",
                        "state": "36",
                        "tblver": "0",
                        "version": "4"
                    }
                }
            }
        ]
    },
    "changed": false,
    "included": [
        "parsers/ios/show_ip_bgp_summary.yml"
    ]
}

Now I've been racking my brains and searching and reading tutorials for days on how I can now extract pieces of this data for analysis

my playbook ends currently with this, using tutorials I thought id try use JMESPath to make it work, ive tried tonnes of formats for that, ive also tried looping through dictionary items, I tried to convert my parser to use a list of dictionaries instead of a dictionary of dictionaries, to my frustration I aren't getting anywhere.

my end goal would be to process each dictionary in a loop to perform analysis against, the simplest one would be to output which peers are down (do not have an integer for state)

   - name: PROCESS RESULTS
     debug:
       msg: "{{ item }}"
     with_items: "{{ bgp_summary_facts | json_query('*.neighbor') }}"

end goal sample:

RTR-01
neighbour 10.10.20.1 is down
RTR-02
neighbour 10.30.20.1 is down

or

RTR-01

| neighbour  | bgp as | prefixes | uptime   |
|------------|--------|----------|----------|
| 10.10.10.1 | 65001  | 2        | 01:35:54 |
| 10.10.10.2 | 65001  | 2        | 3w1d     |
| 10.10.20.1 | 65002  |          | never    |

and so on for each router

Upvotes: 1

Views: 4733

Answers (2)

error404
error404

Reputation: 2823

I have created a jinja2 template for the above. The output is similar but I have some confusion on the conditions but thought to share that here.

If you can explain with example would be good.


playbook:

- name: hosts
  hosts: localhost
  tasks:
    - name: include vars
      include_vars: vars_t4.yml

    - name: template module
      template:
        src: template/source.json
        dest: target/final.json

template

template:{% for i in bgp_summary_facts %}
{% for a in  i | dict2items  %}
RTR-{{ a.value.Data.inq }}
neighbour {{ a.value.Data.neighbor }} is down
{% endfor %}
{% endfor %}

output

RTR-0
neighbour 10.10.10.1 is down

RTR-0
neighbour 10.10.10.2 is down

RTR-0
neighbour 10.10.20.1 is down

RTR-0
neighbour 10.10.30.1 is down

Upvotes: 2

ilias-sp
ilias-sp

Reputation: 6685

if i got the requirements right, here is a way to parse the vars and get the "decisions" you listed.

PB with the test variable included:

---
- hosts: localhost
  gather_facts: false
  vars:
    test_var:
      bgp_summary_facts:
      - 65001_10.10.10.1:
          Data:
            inq: "0"
            msgrcvd: "638"
            msgsent: "424"
            neighbor: 10.10.10.1
            uptime: "01:35:54"
            peer_as: "65001"
            state: "2"
            tblver: "0"
            version: "4"
      - 65001_10.10.10.2:
          Data:
            inq: "0"
            msgrcvd: "208364"
            msgsent: "424"
            neighbor: 10.10.10.2
            uptime: 3w1d
            peer_as: "65001"
            state: "71"
            tblver: "0"
            version: "4"
      - 65002_10.10.20.1:
          Data:
            inq: "0"
            msgrcvd: "0"
            msgsent: "1"
            neighbor: 10.10.20.1
            uptime: never
            peer_as: "65002"
            state: Idle
            tblver: "0"
            version: "4"
      - "65010":
          Data:
            inq: "0"
            msgrcvd: "22611"
            msgsent: "424"
            neighbor: 10.10.30.1
            uptime: 2d11h
            peer_as: "65010"
            state: "36"
            tblver: "0"
            version: "4"
    changed: false
    included:
    - parsers/ios/show_ip_bgp_summary.yml


  tasks:
  - name: print var
    debug:
      msg: "bgp: {{ item.keys() | first }}, Neighbor: {{ item[item.keys() | first].Data['neighbor'] }}, uptime: {{ item[item.keys() | first].Data['uptime'] }}"
    with_items: "{{ test_var.bgp_summary_facts }}"

  - name: print var is down
    debug:
      msg: "is down"
    when: item[item.keys() | first].Data['state'] | int == false
    with_items: "{{ test_var.bgp_summary_facts }}"

i wrote 2 debug tasks for convenience. if you want to produce a table as in your example, you should probably go for a jinja template task.

result:

[http_offline@greenhat-29 tests]$ ansible-playbook  test.yml 

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

TASK [print var] *******************************************************************************************************************************************************************************************************
ok: [localhost] => (item={'65001_10.10.10.1': {'Data': {'inq': '0', 'msgrcvd': '638', 'msgsent': '424', 'neighbor': '10.10.10.1', 'uptime': '01:35:54', 'peer_as': '65001', 'state': '2', 'tblver': '0', 'version': '4'}}}) => {
    "msg": "bgp: 65001_10.10.10.1, Neighbor: 10.10.10.1, uptime: 01:35:54"
}
ok: [localhost] => (item={'65001_10.10.10.2': {'Data': {'inq': '0', 'msgrcvd': '208364', 'msgsent': '424', 'neighbor': '10.10.10.2', 'uptime': '3w1d', 'peer_as': '65001', 'state': '71', 'tblver': '0', 'version': '4'}}}) => {
    "msg": "bgp: 65001_10.10.10.2, Neighbor: 10.10.10.2, uptime: 3w1d"
}
ok: [localhost] => (item={'65002_10.10.20.1': {'Data': {'inq': '0', 'msgrcvd': '0', 'msgsent': '1', 'neighbor': '10.10.20.1', 'uptime': 'never', 'peer_as': '65002', 'state': 'Idle', 'tblver': '0', 'version': '4'}}}) => {
    "msg": "bgp: 65002_10.10.20.1, Neighbor: 10.10.20.1, uptime: never"
}
ok: [localhost] => (item={'65010': {'Data': {'inq': '0', 'msgrcvd': '22611', 'msgsent': '424', 'neighbor': '10.10.30.1', 'uptime': '2d11h', 'peer_as': '65010', 'state': '36', 'tblver': '0', 'version': '4'}}}) => {
    "msg": "bgp: 65010, Neighbor: 10.10.30.1, uptime: 2d11h"
}

TASK [print var is down] ***********************************************************************************************************************************************************************************************
skipping: [localhost] => (item={'65001_10.10.10.1': {'Data': {'inq': '0', 'msgrcvd': '638', 'msgsent': '424', 'neighbor': '10.10.10.1', 'uptime': '01:35:54', 'peer_as': '65001', 'state': '2', 'tblver': '0', 'version': '4'}}}) 
skipping: [localhost] => (item={'65001_10.10.10.2': {'Data': {'inq': '0', 'msgrcvd': '208364', 'msgsent': '424', 'neighbor': '10.10.10.2', 'uptime': '3w1d', 'peer_as': '65001', 'state': '71', 'tblver': '0', 'version': '4'}}}) 
ok: [localhost] => (item={'65002_10.10.20.1': {'Data': {'inq': '0', 'msgrcvd': '0', 'msgsent': '1', 'neighbor': '10.10.20.1', 'uptime': 'never', 'peer_as': '65002', 'state': 'Idle', 'tblver': '0', 'version': '4'}}}) => {
    "msg": "is down"
}
skipping: [localhost] => (item={'65010': {'Data': {'inq': '0', 'msgrcvd': '22611', 'msgsent': '424', 'neighbor': '10.10.30.1', 'uptime': '2d11h', 'peer_as': '65010', 'state': '36', 'tblver': '0', 'version': '4'}}}) 

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

[http_offline@greenhat-29 tests]$ 

hope it helps

Upvotes: 2

Related Questions