1#!/usr/local/bin/python3.8
2
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
5from __future__ import (absolute_import, division, print_function)
6
7__copyright__ = "(c) Copyright 2020 Dell Inc. or its subsidiaries. All rights reserved."
8
9__metaclass__ = type
10
11
12DOCUMENTATION = '''
13module: base_xml_to_dict
14author: "Senthil Kumar Ganesan (@skg-net)"
15short_description: Operations for show command output convertion from xml to json format.
16description:
17
18  - Get the show system inforamtion of a Leaf-Spine.
19
20options:
21    cli_responses:
22        type: str
23        description:
24            - show command xml output
25        required: True
26'''
27EXAMPLES = '''
28Copy below YAML into a playbook (e.g. play.yml) and run as follows:
29
30#$ ansible-playbook -i inv play.yml
31name: setup the plabook to get show command output in dict format
32hosts: localhost
33connection: local
34gather_facts: False
35vars:
36  cli:
37    username: admin
38    password: admin
39tasks:
40- name: "Get Dell EMC OS10 Show output in dict format"
41  os10_command:
42    commands: "{{ command_list }}"
43  register: show
44- debug: var=show
45- name: call to lib to get output in dict
46  base_xml_to_dict:
47    cli_responses: "{{ item }}"
48  loop: "{{ show.stdout }}"
49'''
50
51from ansible.module_utils._text import to_native
52from ansible.module_utils.basic import AnsibleModule
53from collections import OrderedDict
54import traceback
55
56LIB_IMP_ERR = None
57ERR_MSG = None
58try:
59    import xmltodict
60    HAS_LIB = True
61except Exception as e:
62    HAS_LIB = False
63    ERR_MSG = to_native(e)
64    LIB_IMP_ERR = traceback.format_exc()
65
66
67class XmlToDictAnsibleModule(object):
68    """The goal of this class is to convert xml input to dict"""
69
70    def __init__(self):
71        self.module = AnsibleModule(argument_spec=self.get_fields())
72        self.cli_responses = self.module.params['cli_responses']
73        self.exit_msg = OrderedDict()
74
75    def get_fields(self):
76        """Return valid fields"""
77        base_fields = {
78            'cli_responses': {
79                'type': 'str',
80                'required': True
81            }
82        }
83        return base_fields
84
85    def build_xml_list(self, xml_output):
86        xml_str_list = []
87        xml_declaration_tag = '<?xml version="1.0"?>\n'
88        for data in xml_output.split('<?xml version="1.0"'):
89            if not data:
90                continue
91            xml_data = ''.join(data.splitlines(True)[1:])
92            xml_str_list.append(xml_declaration_tag + xml_data)
93
94        return xml_str_list
95
96    def perform_action(self):
97        try:
98            out = list()
99            # the below line should be removed or not valid when the password
100            # decrypt issue is resolved
101            self.cli_responses = self.cli_responses.replace(
102                "*-", '').replace("*", '')
103            xml_str_list = self.build_xml_list(self.cli_responses)
104            for xml_list in xml_str_list:
105                out.append(xmltodict.parse(xml_list))
106
107            self.exit_msg.update({"result": out})
108            self.module.exit_json(changed=False, msg=self.exit_msg)
109        except Exception as e:
110            self.module.fail_json(
111                msg=to_native(e),
112                exception=traceback.format_exc())
113
114
115def main():
116    module_instance = XmlToDictAnsibleModule()
117    if not HAS_LIB:
118        module_instance.module.fail_json(msg=ERR_MSG,
119                                         exception=LIB_IMP_ERR)
120    module_instance.perform_action()
121
122
123if __name__ == '__main__':
124    main()
125