So, I am working with Ansible and I am retrieving specific information from some devices. In particular, I have a task like this:
<rpc-reply message-id="urn:uuid:1914-b84d7ff">
<lldp-neighbors-information style="brief">
<lldp-neighbor-information>
<lldp-local-port-id>A1</lldp-local-port-id>
<lldp-local-parent-interface-name>-</lldp-local-parent-interface-name>
<lldp-remote-chassis-id-subtype>A2</lldp-remote-chassis-id-subtype>
<lldp-remote-chassis-id>A3</lldp-remote-chassis-id>
<lldp-remote-port-id-subtype>A4</lldp-remote-port-id-subtype>
<lldp-remote-port-id>A5</lldp-remote-port-id>
<lldp-remote-system-name>A6</lldp-remote-system-name>
</lldp-neighbor-information>
<lldp-neighbor-information>
<lldp-local-port-id>B1</lldp-local-port-id>
<lldp-local-parent-interface-name>-</lldp-local-parent-interface-name>
<lldp-remote-chassis-id-subtype>B2</lldp-remote-chassis-id-subtype>
<lldp-remote-chassis-id>B3</lldp-remote-chassis-id>
<lldp-remote-port-id-subtype>B4</lldp-remote-port-id-subtype>
<lldp-remote-port-id>B5</lldp-remote-port-id>
<lldp-remote-system-name>B6</lldp-remote-system-name>
</lldp-neighbor-information>
<lldp-neighbor-information>
<lldp-local-port-id>C1</lldp-local-port-id>
<lldp-local-parent-interface-name>-</lldp-local-parent-interface-name>
<lldp-remote-chassis-id-subtype>C2</lldp-remote-chassis-id-subtype>
<lldp-remote-chassis-id>C3</lldp-remote-chassis-id>
<lldp-remote-port-id-subtype>C4</lldp-remote-port-id-subtype>
<lldp-remote-port-id>C5</lldp-remote-port-id>
</lldp-neighbor-information>
</lldp-neighbors-information>
</rpc-reply>
My goal is to build a dictionary like this :
{'A6': ['A1', 'A2'], 'B6': ['B1', 'B2']}
What I have done is creating a list with all my keys by doing the following tasks:
- name: Retrieve lldp system names
xml:
xmlstring: "{{ item.string | regex_replace('\n', '') }}"
xpath: "{{ item.path }}"
content: text
loop:
- { path: "/rpc-reply/lldp-neighbors-information/lldp-neighbor-information/lldp-remote-system-name", string: "{{xml_reply.xml}}" }
register: sys_names
- name: Save all sys names in a list
set_fact:
sys_names_list: "{{ sys_names.results[0].matches | map('dict2items') | list | json_query('[].value') }}"
Then I could create a second list for the elements [A1, B1] and a 3rd list [A2, B2] respectively. So then I could just combine the 3 lists and create my dictionary.
So there are 3 questions here :
You can perform this by combining a filter that converts your xml file to a structured json in order to facilitate data manipulations.
In this example, I use this converter from xml to json .
File filter_plugins/from_xml.py :
#!/usr/bin/python
# From https://github.com/nasgoncalves/ansible-xml-to-json-filter/blob/master/filter_plugins/xml_to_json.py
import json
import xml.etree.ElementTree as ET
from collections import defaultdict
class FilterModule(object):
def etree_to_dict(self, t):
d = {t.tag: {} if t.attrib else None}
children = list(t)
if children:
dd = defaultdict(list)
for dc in map(self.etree_to_dict, children):
for k, v in dc.items():
dd[k].append(v)
d = {t.tag: {k: v[0] if len(v) == 1 else v
for k, v in dd.items()}}
if t.attrib:
d[t.tag].update(('@' + k, v)
for k, v in t.attrib.items())
if t.text:
text = t.text.strip()
if children or t.attrib:
if text:
d[t.tag]['#text'] = text
else:
d[t.tag] = text
return d
def filters(self):
return {
'from_xml': self.from_xml,
'xml_to_json': self.xml_to_json
}
def from_xml(self, data):
root = ET.ElementTree(ET.fromstring(data)).getroot()
return self.etree_to_dict(root)
def xml_to_json(self, data):
return json.dumps(self.from_xml(data))
File playbook.yml , I use a jinja2 template to filter key and combine values in a list, then I convert this list to a dict with filter items2dict
:
---
- hosts: localhost
gather_facts: no
connection: local
tasks:
- set_fact:
xml_message: |
<rpc-reply message-id="urn:uuid:1914-b84d7ff">
<lldp-neighbors-information style="brief">
<lldp-neighbor-information>
<lldp-local-port-id>A1</lldp-local-port-id>
<lldp-local-parent-interface-name>-</lldp-local-parent-interface-name>
<lldp-remote-chassis-id-subtype>A2</lldp-remote-chassis-id-subtype>
<lldp-remote-chassis-id>A3</lldp-remote-chassis-id>
<lldp-remote-port-id-subtype>A4</lldp-remote-port-id-subtype>
<lldp-remote-port-id>A5</lldp-remote-port-id>
<lldp-remote-system-name>A6</lldp-remote-system-name>
</lldp-neighbor-information>
<lldp-neighbor-information>
<lldp-local-port-id>B1</lldp-local-port-id>
<lldp-local-parent-interface-name>-</lldp-local-parent-interface-name>
<lldp-remote-chassis-id-subtype>B2</lldp-remote-chassis-id-subtype>
<lldp-remote-chassis-id>B3</lldp-remote-chassis-id>
<lldp-remote-port-id-subtype>B4</lldp-remote-port-id-subtype>
<lldp-remote-port-id>B5</lldp-remote-port-id>
<lldp-remote-system-name>B6</lldp-remote-system-name>
</lldp-neighbor-information>
<lldp-neighbor-information>
<lldp-local-port-id>C1</lldp-local-port-id>
<lldp-local-parent-interface-name>-</lldp-local-parent-interface-name>
<lldp-remote-chassis-id-subtype>C2</lldp-remote-chassis-id-subtype>
<lldp-remote-chassis-id>C3</lldp-remote-chassis-id>
<lldp-remote-port-id-subtype>C4</lldp-remote-port-id-subtype>
<lldp-remote-port-id>C5</lldp-remote-port-id>
</lldp-neighbor-information>
</lldp-neighbors-information>
</rpc-reply>
- set_fact:
my_dict: |
{% set json_message = xml_message | from_xml %}
{% for item in json_message['rpc-reply']['lldp-neighbors-information']['lldp-neighbor-information'] %}
{% if "lldp-remote-system-name" in item %}
- key: {{ item['lldp-remote-system-name'] }}
value: [{{ item['lldp-local-port-id'] }}, {{ item['lldp-remote-chassis-id-subtype'] }}]
{% endif %}
{% endfor %}
- set_fact:
my_dict: "{{ my_dict | from_yaml | items2dict }}"
- debug:
var: my_dict
Executing this playbook with ansible-playbook playbook.yml
returns :
PLAY [localhost] **********************************
TASK [set_fact] ***********************************
ok: [localhost]
TASK [set_fact] ***********************************
ok: [localhost]
TASK [set_fact] ***********************************
ok: [localhost]
TASK [debug] **************************************
ok: [localhost] => {
"my_dict": {
"A6": [
"A1",
"A2"
],
"B6": [
"B1",
"B2"
]
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.