Completed
Push — master ( b519bb...486e1a )
by Jaspar
25s queued 15s
created

ScannersMixin.modify_scanner()   C

Complexity

Conditions 10

Size

Total Lines 66
Code Lines 37

Duplication

Lines 66
Ratio 100 %

Importance

Changes 0
Metric Value
cc 10
eloc 37
nop 10
dl 66
loc 66
rs 5.9999
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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 gvm.protocols.gmpv214.entities.scanners.ScannersMixin.modify_scanner() 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.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2021 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
20
from enum import Enum
21
from typing import Any, Optional
22
23
from gvm.errors import InvalidArgument, InvalidArgumentType, RequiredArgument
24
from gvm.protocols.gmpv208.entities.scanners import (
25
    ScannersMixin as Gmp208ScannersMixin,
26
)
27
from gvm.xml import XmlCommand
28
29
30
class ScannerType(Enum):
31
    """Enum for scanner type"""
32
33
    OSP_SCANNER_TYPE = "1"
34
    OPENVAS_SCANNER_TYPE = "2"
35
    CVE_SCANNER_TYPE = "3"
36
    GREENBONE_SENSOR_SCANNER_TYPE = "5"
37
38
39
def get_scanner_type_from_string(
40
    scanner_type: Optional[str],
41
) -> Optional[ScannerType]:
42
    """Convert a scanner type string to an actual ScannerType instance
43
44
    Arguments:
45
        scanner_type: Scanner type string to convert to a ScannerType
46
    """
47
    if not scanner_type:
48
        return None
49
50
    scanner_type = scanner_type.lower()
51
52
    if (
53
        scanner_type == ScannerType.OSP_SCANNER_TYPE.value
54
        or scanner_type == 'osp'
55
    ):
56
        return ScannerType.OSP_SCANNER_TYPE
57
58
    if (
59
        scanner_type == ScannerType.OPENVAS_SCANNER_TYPE.value
60
        or scanner_type == 'openvas'
61
    ):
62
        return ScannerType.OPENVAS_SCANNER_TYPE
63
64
    if (
65
        scanner_type == ScannerType.CVE_SCANNER_TYPE.value
66
        or scanner_type == 'cve'
67
    ):
68
        return ScannerType.CVE_SCANNER_TYPE
69
70
    if (
71
        scanner_type == ScannerType.GREENBONE_SENSOR_SCANNER_TYPE.value
72
        or scanner_type == 'greenbone'
73
    ):
74
        return ScannerType.GREENBONE_SENSOR_SCANNER_TYPE
75
76
    raise InvalidArgument(
77
        argument='scanner_type', function=get_scanner_type_from_string.__name__
78
    )
79
80
81
class ScannersMixin(Gmp208ScannersMixin):
82
    # Override bc. of ScannerType (?)
83
84 View Code Duplication
    def create_scanner(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
85
        self,
86
        name: str,
87
        host: str,
88
        port: int,
89
        scanner_type: ScannerType,
90
        credential_id: str,
91
        *,
92
        ca_pub: Optional[str] = None,
93
        comment: Optional[str] = None,
94
    ) -> Any:
95
        """Create a new scanner
96
97
        Arguments:
98
            name: Name of the scanner
99
            host: The host of the scanner
100
            port: The port of the scanner
101
            scanner_type: Type of the scanner.
102
            credential_id: UUID of client certificate credential for the
103
                scanner
104
            ca_pub: Certificate of CA to verify scanner certificate
105
            comment: Comment for the scanner
106
        Returns:
107
            The response. See :py:meth:`send_command` for details.
108
        """
109
        if not name:
110
            raise RequiredArgument(
111
                function=self.create_scanner.__name__, argument='name'
112
            )
113
114
        if not host:
115
            raise RequiredArgument(
116
                function=self.create_scanner.__name__, argument='host'
117
            )
118
119
        if not port:
120
            raise RequiredArgument(
121
                function=self.create_scanner.__name__, argument='port'
122
            )
123
124
        if not scanner_type:
125
            raise RequiredArgument(
126
                function=self.create_scanner.__name__, argument='scanner_type'
127
            )
128
129
        if not credential_id:
130
            raise RequiredArgument(
131
                function=self.create_scanner.__name__, argument='credential_id'
132
            )
133
134
        if not isinstance(scanner_type, ScannerType):
135
            raise InvalidArgumentType(
136
                function=self.create_scanner.__name__,
137
                argument='scanner_type',
138
                arg_type=ScannerType.__name__,
139
            )
140
141
        cmd = XmlCommand("create_scanner")
142
        cmd.add_element("name", name)
143
        cmd.add_element("host", host)
144
        cmd.add_element("port", str(port))
145
        cmd.add_element("type", scanner_type.value)
146
147
        if ca_pub:
148
            cmd.add_element("ca_pub", ca_pub)
149
150
        cmd.add_element("credential", attrs={"id": str(credential_id)})
151
152
        if comment:
153
            cmd.add_element("comment", comment)
154
155
        return self._send_xml_command(cmd)
156
157 View Code Duplication
    def modify_scanner(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
158
        self,
159
        scanner_id: str,
160
        *,
161
        scanner_type: Optional[ScannerType] = None,
162
        host: Optional[str] = None,
163
        port: Optional[int] = None,
164
        comment: Optional[str] = None,
165
        name: Optional[str] = None,
166
        ca_pub: Optional[str] = None,
167
        credential_id: Optional[str] = None,
168
    ) -> Any:
169
        """Modifies an existing scanner.
170
171
        Arguments:
172
            scanner_id: UUID of scanner to modify.
173
            scanner_type: New type of the Scanner.
174
            host: Host of the scanner.
175
            port: Port of the scanner.
176
            comment: Comment on scanner.
177
            name: Name of scanner.
178
            ca_pub: Certificate of CA to verify scanner's certificate.
179
            credential_id: UUID of the client certificate credential for the
180
                Scanner.
181
182
        Returns:
183
            The response. See :py:meth:`send_command` for details.
184
        """
185
        if not scanner_id:
186
            raise RequiredArgument(
187
                function=self.modify_scanner.__name__,
188
                argument='scanner_id argument',
189
            )
190
191
        cmd = XmlCommand("modify_scanner")
192
        cmd.set_attribute("scanner_id", scanner_id)
193
194
        if scanner_type is not None:
195
            if not isinstance(scanner_type, ScannerType):
196
                raise InvalidArgumentType(
197
                    function=self.modify_scanner.__name__,
198
                    argument='scanner_type',
199
                    arg_type=ScannerType.__name__,
200
                )
201
202
            cmd.add_element("type", scanner_type.value)
203
204
        if host:
205
            cmd.add_element("host", host)
206
207
        if port:
208
            cmd.add_element("port", str(port))
209
210
        if comment:
211
            cmd.add_element("comment", comment)
212
213
        if name:
214
            cmd.add_element("name", name)
215
216
        if ca_pub:
217
            cmd.add_element("ca_pub", ca_pub)
218
219
        if credential_id:
220
            cmd.add_element("credential", attrs={"id": str(credential_id)})
221
222
        return self._send_xml_command(cmd)
223