scrapli 2.0.0a1__py3-none-manylinux2014_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scrapli/__init__.py +30 -0
- scrapli/auth.py +216 -0
- scrapli/cli.py +1414 -0
- scrapli/cli_decorators.py +148 -0
- scrapli/cli_parse.py +161 -0
- scrapli/cli_result.py +197 -0
- scrapli/definitions/__init__.py +1 -0
- scrapli/definitions/arista_eos.yaml +64 -0
- scrapli/definitions/cisco_iosxe.yaml +63 -0
- scrapli/definitions/cisco_iosxr.yaml +47 -0
- scrapli/definitions/cisco_nxos.yaml +64 -0
- scrapli/definitions/juniper_junos.yaml +85 -0
- scrapli/definitions/nokia_srlinux.yaml +35 -0
- scrapli/exceptions.py +49 -0
- scrapli/ffi.py +76 -0
- scrapli/ffi_mapping.py +202 -0
- scrapli/ffi_mapping_cli.py +646 -0
- scrapli/ffi_mapping_netconf.py +1612 -0
- scrapli/ffi_mapping_options.py +1031 -0
- scrapli/ffi_types.py +154 -0
- scrapli/helper.py +95 -0
- scrapli/lib/__init__.py +1 -0
- scrapli/lib/libscrapli.0.0.1-alpha.10.dylib +0 -0
- scrapli/lib/libscrapli.so.0.0.1-alpha.10 +0 -0
- scrapli/netconf.py +2804 -0
- scrapli/netconf_decorators.py +148 -0
- scrapli/netconf_result.py +72 -0
- scrapli/py.typed +0 -0
- scrapli/session.py +122 -0
- scrapli/transport.py +401 -0
- scrapli-2.0.0a1.dist-info/METADATA +49 -0
- scrapli-2.0.0a1.dist-info/RECORD +35 -0
- scrapli-2.0.0a1.dist-info/WHEEL +5 -0
- scrapli-2.0.0a1.dist-info/licenses/LICENSE +21 -0
- scrapli-2.0.0a1.dist-info/top_level.txt +1 -0
scrapli/__init__.py
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
"""scrapli"""
|
2
|
+
|
3
|
+
from scrapli.auth import LookupKeyValue
|
4
|
+
from scrapli.auth import Options as AuthOptions
|
5
|
+
from scrapli.cli import Cli
|
6
|
+
from scrapli.netconf import Netconf
|
7
|
+
from scrapli.netconf import Options as NetconfOptions
|
8
|
+
from scrapli.session import Options as SessionOptions
|
9
|
+
from scrapli.transport import BinOptions as TransportBinOptions
|
10
|
+
from scrapli.transport import Options as TransportOptions
|
11
|
+
from scrapli.transport import Ssh2Options as TransportSsh2Options
|
12
|
+
from scrapli.transport import TelnetOptions as TransportTelnetOptions
|
13
|
+
from scrapli.transport import TestOptions as TransportTestOptions
|
14
|
+
|
15
|
+
__version__ = "2.0.0-alpha.1"
|
16
|
+
__definitions_version__ = "471f12e"
|
17
|
+
|
18
|
+
__all__ = (
|
19
|
+
"AuthOptions",
|
20
|
+
"Cli",
|
21
|
+
"LookupKeyValue",
|
22
|
+
"Netconf",
|
23
|
+
"NetconfOptions",
|
24
|
+
"SessionOptions",
|
25
|
+
"TransportBinOptions",
|
26
|
+
"TransportOptions",
|
27
|
+
"TransportSsh2Options",
|
28
|
+
"TransportTelnetOptions",
|
29
|
+
"TransportTestOptions",
|
30
|
+
)
|
scrapli/auth.py
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
"""scrapli.auth"""
|
2
|
+
|
3
|
+
from ctypes import c_char_p
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
|
6
|
+
from scrapli.exceptions import OptionsException
|
7
|
+
from scrapli.ffi_mapping import LibScrapliMapping
|
8
|
+
from scrapli.ffi_types import (
|
9
|
+
DriverPointer,
|
10
|
+
to_c_string,
|
11
|
+
)
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass
|
15
|
+
class LookupKeyValue:
|
16
|
+
"""
|
17
|
+
Options a "lookup" key/value pair.
|
18
|
+
|
19
|
+
Used in conjuection with platform definition templating like `__lookup::enable` where "enable"
|
20
|
+
is the key to "lookup" in the list of lookup key/values.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
key: the name of the lookup key
|
24
|
+
value: the value of the lookup key
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
None
|
28
|
+
|
29
|
+
Raises:
|
30
|
+
N/A
|
31
|
+
|
32
|
+
"""
|
33
|
+
|
34
|
+
key: str
|
35
|
+
value: str
|
36
|
+
|
37
|
+
_key: c_char_p | None = field(init=False, default=None, repr=False)
|
38
|
+
_value: c_char_p | None = field(init=False, default=None, repr=False)
|
39
|
+
|
40
|
+
def _get_c_strings(self) -> tuple[c_char_p, c_char_p]:
|
41
|
+
self._key = to_c_string(self.key)
|
42
|
+
self._value = to_c_string(self.value)
|
43
|
+
|
44
|
+
return self._key, self._value
|
45
|
+
|
46
|
+
def __repr__(self) -> str:
|
47
|
+
return f"{self.__class__.__name__}(key='{self.key}', value='REDACTED')"
|
48
|
+
|
49
|
+
|
50
|
+
@dataclass
|
51
|
+
class Options:
|
52
|
+
"""
|
53
|
+
Options holds auth related options to pass to the ffi layer.
|
54
|
+
|
55
|
+
All arguments are optional, though you will almost certainly need to provide *some* -- for
|
56
|
+
example a username and password or key.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
username: the username to use for the connection
|
60
|
+
password: the password to use for the connection
|
61
|
+
private_key_path: filepath to the ssh private key to use
|
62
|
+
private_key_passphrase: the private key passphrase if set
|
63
|
+
lookups: a list of key/values that can be "looked up" from a connection -- used in
|
64
|
+
conjunction with platform definition templating like `__lookup::enable` where "enable"
|
65
|
+
is the key to "lookup" in the list of lookup key/values.
|
66
|
+
in_session_auth_bypass: whether to bypass attempting in session authentication -- only
|
67
|
+
applicable to "bin" and "telnet" transports.
|
68
|
+
username_pattern: the regex pattern to use to look for a username prompt
|
69
|
+
password_pattern: the regex pattern to use to look for a password prompt
|
70
|
+
private_key_passphrase_pattern: the regex pattern to use to look for a passphrase prompt
|
71
|
+
|
72
|
+
Returns:
|
73
|
+
None
|
74
|
+
|
75
|
+
Raises:
|
76
|
+
N/A
|
77
|
+
|
78
|
+
"""
|
79
|
+
|
80
|
+
username: str | None = None
|
81
|
+
password: str | None = None
|
82
|
+
private_key_path: str | None = None
|
83
|
+
private_key_passphrase: str | None = None
|
84
|
+
lookups: list[LookupKeyValue] | None = None
|
85
|
+
in_session_auth_bypass: bool | None = None
|
86
|
+
username_pattern: str | None = None
|
87
|
+
password_pattern: str | None = None
|
88
|
+
private_key_passphrase_pattern: str | None = None
|
89
|
+
|
90
|
+
_username: c_char_p | None = field(init=False, default=None, repr=False)
|
91
|
+
_password: c_char_p | None = field(init=False, default=None, repr=False)
|
92
|
+
_private_key_path: c_char_p | None = field(init=False, default=None, repr=False)
|
93
|
+
_private_key_passphrase: c_char_p | None = field(init=False, default=None, repr=False)
|
94
|
+
_username_pattern: c_char_p | None = field(init=False, default=None, repr=False)
|
95
|
+
_password_pattern: c_char_p | None = field(init=False, default=None, repr=False)
|
96
|
+
_private_key_passphrase_pattern: c_char_p | None = field(init=False, default=None, repr=False)
|
97
|
+
|
98
|
+
def apply( # noqa: C901, PLR0912
|
99
|
+
self, ffi_mapping: LibScrapliMapping, ptr: DriverPointer
|
100
|
+
) -> None:
|
101
|
+
"""
|
102
|
+
Applies the options to the given driver pointer.
|
103
|
+
|
104
|
+
Should not be called directly/by users.
|
105
|
+
|
106
|
+
Args:
|
107
|
+
ffi_mapping: the handle to the ffi mapping singleton
|
108
|
+
ptr: the pointer to the underlying cli or netconf object
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
None
|
112
|
+
|
113
|
+
Raises:
|
114
|
+
OptionsException: if any option apply returns a non-zero return code.
|
115
|
+
|
116
|
+
"""
|
117
|
+
if self.username is not None:
|
118
|
+
self._username = to_c_string(self.username)
|
119
|
+
|
120
|
+
status = ffi_mapping.options_mapping.auth.set_username(ptr, self._username)
|
121
|
+
if status != 0:
|
122
|
+
raise OptionsException("failed to set auth username")
|
123
|
+
|
124
|
+
if self.password is not None:
|
125
|
+
self._password = to_c_string(self.password)
|
126
|
+
|
127
|
+
status = ffi_mapping.options_mapping.auth.set_password(ptr, self._password)
|
128
|
+
if status != 0:
|
129
|
+
raise OptionsException("failed to set auth password")
|
130
|
+
|
131
|
+
if self.private_key_path is not None:
|
132
|
+
self._private_key_path = to_c_string(self.private_key_path)
|
133
|
+
|
134
|
+
status = ffi_mapping.options_mapping.auth.set_private_key_path(
|
135
|
+
ptr, self._private_key_path
|
136
|
+
)
|
137
|
+
if status != 0:
|
138
|
+
raise OptionsException("failed to set auth private key path")
|
139
|
+
|
140
|
+
if self.private_key_passphrase is not None:
|
141
|
+
self._private_key_passphrase = to_c_string(self.private_key_passphrase)
|
142
|
+
|
143
|
+
status = ffi_mapping.options_mapping.auth.set_private_key_passphrase(
|
144
|
+
ptr, self._private_key_passphrase
|
145
|
+
)
|
146
|
+
if status != 0:
|
147
|
+
raise OptionsException("failed to set auth private key passphrase")
|
148
|
+
|
149
|
+
if self.lookups is not None:
|
150
|
+
for lookup in self.lookups:
|
151
|
+
status = ffi_mapping.options_mapping.auth.set_lookup_key_value(
|
152
|
+
ptr, *lookup._get_c_strings()
|
153
|
+
)
|
154
|
+
if status != 0:
|
155
|
+
raise OptionsException("failed to set auth lookup key/value")
|
156
|
+
|
157
|
+
if self.in_session_auth_bypass is not None:
|
158
|
+
status = ffi_mapping.options_mapping.auth.set_in_session_auth_bypass(ptr)
|
159
|
+
if status != 0:
|
160
|
+
raise OptionsException("failed to set session in session auth bypass")
|
161
|
+
|
162
|
+
if self.username_pattern is not None:
|
163
|
+
self._username_pattern = to_c_string(self.username_pattern)
|
164
|
+
|
165
|
+
status = ffi_mapping.options_mapping.auth.set_username_pattern(
|
166
|
+
ptr, self._username_pattern
|
167
|
+
)
|
168
|
+
if status != 0:
|
169
|
+
raise OptionsException("failed to set auth username pattern")
|
170
|
+
|
171
|
+
if self.password_pattern is not None:
|
172
|
+
self._password_pattern = to_c_string(self.password_pattern)
|
173
|
+
|
174
|
+
status = ffi_mapping.options_mapping.auth.set_password_pattern(
|
175
|
+
ptr, self._password_pattern
|
176
|
+
)
|
177
|
+
if status != 0:
|
178
|
+
raise OptionsException("failed to set auth password pattern")
|
179
|
+
|
180
|
+
if self.private_key_passphrase_pattern is not None:
|
181
|
+
self._private_key_passphrase_pattern = to_c_string(self.private_key_passphrase_pattern)
|
182
|
+
|
183
|
+
status = ffi_mapping.options_mapping.auth.set_private_key_passphrase_pattern(
|
184
|
+
ptr, self._private_key_passphrase_pattern
|
185
|
+
)
|
186
|
+
if status != 0:
|
187
|
+
raise OptionsException("failed to set auth private key passphrase pattern")
|
188
|
+
|
189
|
+
def __repr__(self) -> str:
|
190
|
+
"""
|
191
|
+
Magic repr method for Options object
|
192
|
+
|
193
|
+
Args:
|
194
|
+
N/A
|
195
|
+
|
196
|
+
Returns:
|
197
|
+
str: repr for Options object
|
198
|
+
|
199
|
+
Raises:
|
200
|
+
N/A
|
201
|
+
|
202
|
+
"""
|
203
|
+
return (
|
204
|
+
# it will probably be "canonical" to import Options as AuthOptions, so we'll make
|
205
|
+
# the repr do that too
|
206
|
+
f"Auth{self.__class__.__name__}("
|
207
|
+
f"username={self.username!r}, "
|
208
|
+
"password=REDACTED, "
|
209
|
+
f"private_key_path={self.private_key_path!r} "
|
210
|
+
f"private_key_passphrase={self.private_key_passphrase!r} "
|
211
|
+
f"lookups={self.lookups!r}) "
|
212
|
+
f"in_session_auth_bypass={self.in_session_auth_bypass!r}) "
|
213
|
+
f"username_pattern={self.username_pattern!r}) "
|
214
|
+
f"password_pattern={self.password_pattern!r}) "
|
215
|
+
f"private_key_passphrase_pattern={self.private_key_passphrase_pattern!r}) "
|
216
|
+
)
|