Completed
Push — master ( f07019...0c998d )
by
unknown
18s queued 13s
created

send-targets.gmp.parse_send_xml_tree()   D

Complexity

Conditions 13

Size

Total Lines 77
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 54
nop 2
dl 0
loc 77
rs 4.2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like send-targets.gmp.parse_send_xml_tree() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2018-2019 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
import sys
20
21
from lxml import etree as e
22
23
24
def check_args(args):
25
    len_args = len(args.script) - 1
26
    if len_args is not 1:
27
        message = """
28
        This script pulls target data from an xml document and feeds it to \
29
    a desired GSM
30
        One parameter after the script name is required.
31
32
        1. <xml_doc>  -- .xml file containing targets
33
34
        Example:
35
            $ gvm-script --gmp-username name --gmp-password pass \
36
    ssh --hostname <gsm> scripts/send-targets.gmp.py example_file.xml
37
        """
38
        print(message)
39
        quit()
40
41
42
def error_and_exit(msg):
43
    print("Error: {}\n".format(msg), file=sys.stderr)
44
    sys.exit(1)
45
46
47
def yes_or_no(question):
48
    reply = str(input(question + ' (y/n): ')).lower().strip()
49
    if reply[0] == ('y'):
50
        return True
51
    if reply[0] == ('n'):
52
        return False
53
    else:
54
        return yes_or_no("Please enter 'y' or 'n'")
55
56
57 View Code Duplication
def create_xml_tree(xml_doc):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
58
    try:
59
        xml_tree = e.parse(xml_doc)
60
        xml_tree = e.tostring(xml_tree)
61
        xml_tree = e.XML(xml_tree)
62
    except IOError as err:
63
        error_and_exit("Failed to read xml_file: {} (exit)".format(str(err)))
64
65
    if len(xml_tree) == 0:
66
        error_and_exit("XML file is empty (exit)")
67
68
    return xml_tree
69
70
71
def parse_send_xml_tree(gmp, xml_tree):
72
    credential_options = [
73
        'ssh_credential',
74
        'smb_credential',
75
        'esxi_credential',
76
        'snmp_credential',
77
    ]
78
    counter = 1
79
80
    for target in xml_tree.xpath('target'):
81
        keywords = {}  # {'make_unique': True}
82
83
        keywords['name'] = target.find('name').text
84
85
        keywords['hosts'] = target.find('hosts').text
86
87
        keywords['exclude_hosts'] = target.find('exclude_hosts').text
88
89
        comment = target.find('comment').text
90
        if comment is not None:
91
            keywords['comment'] = comment
92
93
        credentials = gmp.get_credentials()[0].xpath("//credential/@id")
94
95
        for credential in credential_options:
96
            cred_id = target.find(credential).xpath('@id')[0]
97
            if cred_id == '':
98
                continue
99
            if cred_id not in credentials:
100
                response = yes_or_no(
101
                    "\nThe credential '{}' for 'target {}' could not be "
102
                    "located...\nWould you like to continue?".format(
103
                        credential, counter
104
                    )
105
                )
106
107
                if response is False:
108
                    print("Terminating...\n")
109
                    quit()
110
                else:
111
                    continue
112
113
            temp_dict = {}
114
            temp_dict['id'] = cred_id
115
            elem_path = target.find(credential)
116
            if elem_path.find('port').text is not None:
117
                temp_dict['port'] = elem_path.find('port').text
118
119
            keywords[credential] = temp_dict
120
121
        alive_test = target.find('alive_test')
122
123
        if alive_test is not None:
124
            keywords['alive_test'] = alive_test
125
126
        reverse_lookup_only = target.find('reverse_lookup_only').text
127
        if reverse_lookup_only == '1':
128
            keywords['reverse_lookup_only'] = 1
129
130
        reverse_lookup_unify = target.find('reverse_lookup_unify').text
131
        if reverse_lookup_unify == '1':
132
            keywords['reverse_lookup_unify'] = 1
133
134
        port_range = target.find('port_range').text
135
        if port_range is not None:
136
            keywords['port_range'] = port_range
137
138
        if target.xpath('port_list/@id') is not None:
139
            port_list = {}
140
            port_list = target.xpath('port_list/@id')[0]
141
            keywords['port_list_id'] = port_list
142
143
        print(keywords)
144
145
        gmp.create_target(**keywords)
146
147
        counter += 1
148
149
150
def main(gmp, args):
151
    # pylint: disable=undefined-variable
152
153
    check_args(args)
154
155
    xml_doc = args.script[1]
156
157
    print('\nSending targets...')
158
159
    xml_tree = create_xml_tree(xml_doc)
160
    parse_send_xml_tree(gmp, xml_tree)
161
162
    print('\n  Target(s) created!\n')
163
164
165
if __name__ == '__gmp__':
166
    main(gmp, args)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable args does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable gmp does not seem to be defined.
Loading history...
167