Parse complex data in ansible

I have fetched data from remote firewall device using ssh in ansible .
I got the context data in stdout_lines in below format.I wanted to form a dict mapped with first and 3rd item in string.How to achieve so?Please help

  • my code!
Example
Output of show context in ansible from remote cisco asa fw device
stdout_lines: [
                       [ 
                             "Context Name           Class                      Interfaces        Mode.                        URL"
                             "  TD-BW-SNSL-Workplace   default       Port-channel1.2345, "   Routed       disk0:/
                             "                                                                        Port-channel10.2298-"
                             "                                                                       2299, Port-,"
                             "                                                                     channel20.2229 "                   
]
]

How can I get the context name and interface from this data in ansible?

The data youve provided is invalid yaml/json, and seems to be irregular as a table (theres no clear correlation between columns in each row). Can you try to provide a better example? As youve posted it, I dont think you can parse it really.

If we clean it up a bit:

# vars.yml
stdout_lines:
  [
    [
      "Context Name           Class                      Interfaces        Mode.                        URL",
      "TD-BW-SNSL-Workplace   default       Port-channel1.2345,    Routed       disk0:/",
      "c2                     default       Port-channel10.2298  Routed  disk0:/",
    ],
  ]

Then this playbook parses it:

- hosts: localhost
  gather_facts: false
  vars_files:
    - vars.yml
  tasks:
    - set_fact:
        s: "{{ (stdout_lines)[0] }}"
    - set_fact:
        contexts: >-
          {{ (contexts | default([])) + [
            item.split()[0] | trim | trim(',')
          ] }}
        interfaces: >-
          {{ (interfaces | default([])) + [
            item.split()[2] | trim | trim(',')
          ] }}
      loop: "{{ s }}"
      when: not item.startswith('Context Name')

    - debug:
        var: contexts
    - debug:
        var: interfaces
    - debug:
        var: contexts | zip(interfaces) | community.general.dict

Heres the (partial) output

TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "contexts": [
        "TD-BW-SNSL-Workplace",
        "c2"
    ]
}

TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "interfaces": [
        "Port-channel1.2345",
        "Port-channel10.2298"
    ]
}

TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "contexts | zip(interfaces) | community.general.dict": {
        "TD-BW-SNSL-Workplace": "Port-channel1.2345",
        "c2": "Port-channel10.2298"
    }
}
1 Like

Im not sure I understand, is this the value you want?

[
  "Port-channel1.2345",
  "Port-channel10.2298-2299",
  "Port-channel20.2229"
]

I see. This is a very challenging data format. It might be easier to look at ways to get better input data formats instead of parsing this.

Would you have a case where there are multiple contexts? Like

TD-BW-SNSL-Workplace
TD-BW-SNSL-Workplace1
TD-BW-SNSL-Workplace2

OK, really messy but here it is:

# vars.yml
context_names:
  [
    " ST-BW-SNSL-OPG-COMMSEE default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-OPG-COMMSEE.cfg",
    "                                       Port-channel10.2006-",
    "                                       2007,Port-          ",
    "                                       channel20.2224      ",
    " ST-BW-SNSL-COMMSEC-NONPROD default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-COMMSEC-NONPROD.cfg",
    "                                       Port-channel10.2273-",
    "                                       2276,Port-          ",
    "                                       channel20.2223      ",
    " ST-BW-SNSL-CYBERARK default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-CYBERARK.cfg",
    "                                       Port-channel10.2272,",
    "                                       Port-channel20.2222 ",
    " ST-BW-SNSL-NON-STOP default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-NON-STOP.cfg",
    "                                       Port-channel10.2041-",
    "                                       2054,2108-2115,Port-",
    "                                       channel20.2227      ",
    " ST-BW-SNSL-ENTERPRISE-MF default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-ENTERPRISE-MF.cfg",
    "                                       Port-channel10.2283,",
    "                                       Port-channel20.2226 ",
    " ST-BW-SNSL-DOT   default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-DOT.cfg",
    "                                       Port-channel10.2279-",
    "                                       2282,2284-2287,Port-",
    "                                       channel20.2225      ",
    " ST-BW-SNSL-Internet-Browsing default              Port-channel1.2345,  Routed       disk0:/ST-BW-SNSL-Internet-Browsing.cfg",
    "                                       Port-channel10.1568,",
    "                                       1570,Port-          ",
    "                                       channel20.2228      ",
    " TD-BW-SNSL-Workplace default              Port-channel1.2345,  Routed       disk0:/TD-BW-SNSL-Workplace.cfg",
    "                                       Port-channel10.2298-",
    "                                       2299,Port-          ",
    "                                       channel20.2229      ",
    "",
    "Total active Security Contexts: 9",
  ]
# playbook.yml
- hosts: localhost
  gather_facts: false
  vars_files:
    - vars.yml
  tasks:
    - set_fact:
        context_indices: "{{ context_indices | default([]) + [idx] }}"
      when: item is search('^ \w') or not item
      loop: "{{ context_names }}"
      loop_control:
        index_var: idx

    - set_fact:
        context_groups: >-
          {{ context_groups | default([]) +
          [context_names[context_indices[idx]:context_indices[idx+1]]]
          }}
      when: context_indices[idx+1] is defined
      loop: "{{ context_indices }}"
      loop_control:
        index_var: idx

    - set_fact:
        contexts: "{{ contexts | default([]) + [(item | first | split())[0] | trim()] }}"
        port_channel_first: >-
          {{ port_channel_first | default([]) + [(item | first | split())[2] | trim()] }}
        port_channel_other: >-
          {{ port_channel_other | default([]) +
          [(item[1:] | map('trim') | join()) | default([])]
          }}
      loop: "{{ context_groups }}"

    - set_fact:
        port_channels: >-
          {{ port_channel_first | zip(port_channel_other) | map('join') | map('split', ',') }}

    - set_fact:
        context_port_channel_map: >-
          {{ contexts | zip(port_channels) | community.general.dict }}

    - debug:
        var: context_port_channel_map

Outputs:

TASK [debug] ***********************************************************************************************************************************************************************************************************************************************
ok: [mikemorency] => {
    "context_port_channel_map": {
        "ST-BW-SNSL-COMMSEC-NONPROD": [
            "Port-channel1.2345",
            "Port-channel10.2273-2276",
            "Port-channel20.2223"
        ],
        "ST-BW-SNSL-CYBERARK": [
            "Port-channel1.2345",
            "Port-channel10.2272",
            "Port-channel20.2222"
        ],
        "ST-BW-SNSL-DOT": [
            "Port-channel1.2345",
            "Port-channel10.2279-2282",
            "2284-2287",
            "Port-channel20.2225"
        ],
        "ST-BW-SNSL-ENTERPRISE-MF": [
            "Port-channel1.2345",
            "Port-channel10.2283",
            "Port-channel20.2226"
        ],
        "ST-BW-SNSL-Internet-Browsing": [
            "Port-channel1.2345",
            "Port-channel10.1568",
            "1570",
            "Port-channel20.2228"
        ],
        "ST-BW-SNSL-NON-STOP": [
            "Port-channel1.2345",
            "Port-channel10.2041-2054",
            "2108-2115",
            "Port-channel20.2227"
        ],
        "ST-BW-SNSL-OPG-COMMSEE": [
            "Port-channel1.2345",
            "Port-channel10.2006-2007",
            "Port-channel20.2224"
        ],
        "TD-BW-SNSL-Workplace": [
            "Port-channel1.2345",
            "Port-channel10.2298-2299",
            "Port-channel20.2229"
        ]
    }
}
1 Like

You can search on Ansible galaxy, check here
https://docs.ansible.com/ansible/latest/collections/index.html
or check here
https://docs.ansible.com/ansible/latest/collections/community/general/index.html#plugins-in-community-general