arpakitlib 1.8.171__py3-none-any.whl → 1.8.172__py3-none-any.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.
- {arpakitlib-1.8.171.dist-info → arpakitlib-1.8.172.dist-info}/METADATA +1 -1
- {arpakitlib-1.8.171.dist-info → arpakitlib-1.8.172.dist-info}/RECORD +5 -6
- arpakitlib/ar_ssh_runner_util.py +0 -266
- {arpakitlib-1.8.171.dist-info → arpakitlib-1.8.172.dist-info}/LICENSE +0 -0
- {arpakitlib-1.8.171.dist-info → arpakitlib-1.8.172.dist-info}/WHEEL +0 -0
- {arpakitlib-1.8.171.dist-info → arpakitlib-1.8.172.dist-info}/entry_points.txt +0 -0
@@ -407,12 +407,11 @@ arpakitlib/ar_settings_util.py,sha256=Y5wi_cmsjDjfJpM0VJHjbo0NoVPKfypKaD1USowwDt
|
|
407
407
|
arpakitlib/ar_sleep_util.py,sha256=ggaj7ML6QK_ADsHMcyu6GUmUpQ_9B9n-SKYH17h-9lM,1045
|
408
408
|
arpakitlib/ar_sqladmin_util.py,sha256=Jd33EX_fAso4bvrcDhNEYOUlUHkudbadNGOJDg7rqhQ,301
|
409
409
|
arpakitlib/ar_sqlalchemy_util.py,sha256=w_tGPTWIMVjHkTEYo9tVe1sfK_4vvfd3zGATLiYC2J4,11775
|
410
|
-
arpakitlib/ar_ssh_runner_util.py,sha256=yvAwza480MkHKvLkDEsR7JNh2bYNs6P9rCVo4NA85NE,6865
|
411
410
|
arpakitlib/ar_str_util.py,sha256=2lGpnXDf2h1cBZpVf5i1tX_HCv5iBd6IGnrCw4QWWlY,4350
|
412
411
|
arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,4049
|
413
412
|
arpakitlib/ar_yookassa_api_client_util.py,sha256=VozuZeCJjmLd1zj2BdC9WfiAQ3XYOrIMsdpNK-AUlm0,5347
|
414
|
-
arpakitlib-1.8.
|
415
|
-
arpakitlib-1.8.
|
416
|
-
arpakitlib-1.8.
|
417
|
-
arpakitlib-1.8.
|
418
|
-
arpakitlib-1.8.
|
413
|
+
arpakitlib-1.8.172.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
|
414
|
+
arpakitlib-1.8.172.dist-info/METADATA,sha256=vq6aEhKgZA_7pDdYWeQX-RMo4SmrThVESCFFNioovpE,3706
|
415
|
+
arpakitlib-1.8.172.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
416
|
+
arpakitlib-1.8.172.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
|
417
|
+
arpakitlib-1.8.172.dist-info/RECORD,,
|
arpakitlib/ar_ssh_runner_util.py
DELETED
@@ -1,266 +0,0 @@
|
|
1
|
-
# arpakit
|
2
|
-
|
3
|
-
from __future__ import annotations
|
4
|
-
|
5
|
-
import asyncio
|
6
|
-
import logging
|
7
|
-
from datetime import timedelta
|
8
|
-
from typing import Optional, Any
|
9
|
-
|
10
|
-
import asyncssh
|
11
|
-
import paramiko
|
12
|
-
from pydantic import BaseModel
|
13
|
-
|
14
|
-
from arpakitlib.ar_json_util import transfer_data_to_json_str
|
15
|
-
|
16
|
-
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
17
|
-
|
18
|
-
|
19
|
-
class SSHRunTimeouts:
|
20
|
-
fast_command = timedelta(minutes=0, seconds=15).total_seconds()
|
21
|
-
medium_command = timedelta(minutes=2, seconds=30).total_seconds()
|
22
|
-
long_command = timedelta(minutes=5, seconds=0).total_seconds()
|
23
|
-
|
24
|
-
|
25
|
-
class SSHBaseErr(Exception):
|
26
|
-
pass
|
27
|
-
|
28
|
-
|
29
|
-
class SSHCannotConnect(SSHBaseErr):
|
30
|
-
pass
|
31
|
-
|
32
|
-
|
33
|
-
class SSHCannotRun(SSHBaseErr):
|
34
|
-
pass
|
35
|
-
|
36
|
-
|
37
|
-
class SSHRunResHasErr(SSHBaseErr):
|
38
|
-
|
39
|
-
def __init__(self, ssh_run_res: SSHRunRes):
|
40
|
-
self.ssh_run_res = ssh_run_res
|
41
|
-
|
42
|
-
def __repr__(self):
|
43
|
-
return f"return_code={self.ssh_run_res.return_code}, stderr={self.ssh_run_res.err.strip()}"
|
44
|
-
|
45
|
-
def __str__(self):
|
46
|
-
return f"return_code={self.ssh_run_res.return_code}, stderr={self.ssh_run_res.err.strip()}"
|
47
|
-
|
48
|
-
|
49
|
-
class SSHRunRes(BaseModel):
|
50
|
-
out: str
|
51
|
-
err: str
|
52
|
-
return_code: int | None = None
|
53
|
-
|
54
|
-
def simple_dict(self) -> dict[str, Any]:
|
55
|
-
return {
|
56
|
-
"out": self.out,
|
57
|
-
"err": self.err,
|
58
|
-
"return_code": self.return_code,
|
59
|
-
"has_bad_return_code": self.has_bad_return_code,
|
60
|
-
"has_err": self.has_err
|
61
|
-
}
|
62
|
-
|
63
|
-
def simple_json(self) -> str:
|
64
|
-
return transfer_data_to_json_str(
|
65
|
-
self.simple_dict(),
|
66
|
-
beautify=True,
|
67
|
-
fast=False
|
68
|
-
)
|
69
|
-
|
70
|
-
def __repr__(self) -> str:
|
71
|
-
return self.simple_json()
|
72
|
-
|
73
|
-
def __str__(self) -> str:
|
74
|
-
return self.simple_json()
|
75
|
-
|
76
|
-
@property
|
77
|
-
def has_bad_return_code(self) -> bool:
|
78
|
-
if self.return_code is None:
|
79
|
-
return False
|
80
|
-
return self.return_code != 0
|
81
|
-
|
82
|
-
@property
|
83
|
-
def has_err(self) -> bool:
|
84
|
-
if self.err:
|
85
|
-
return True
|
86
|
-
return False
|
87
|
-
|
88
|
-
def raise_for_bad_return_code(self):
|
89
|
-
if self.has_bad_return_code:
|
90
|
-
raise SSHRunResHasErr(ssh_run_res=self)
|
91
|
-
|
92
|
-
def raise_for_err(self):
|
93
|
-
if self.has_err:
|
94
|
-
raise SSHRunResHasErr(ssh_run_res=self)
|
95
|
-
|
96
|
-
|
97
|
-
class SSHRunner:
|
98
|
-
|
99
|
-
def __init__(
|
100
|
-
self,
|
101
|
-
*,
|
102
|
-
hostname: str,
|
103
|
-
port: int = 22,
|
104
|
-
username: str = "root",
|
105
|
-
password: Optional[str] = None,
|
106
|
-
base_timeout: int = timedelta(seconds=5).total_seconds()
|
107
|
-
):
|
108
|
-
self.hostname = hostname
|
109
|
-
self.port = port
|
110
|
-
self.username = username
|
111
|
-
self.password = password
|
112
|
-
|
113
|
-
self.base_timeout = base_timeout
|
114
|
-
|
115
|
-
self._logger = logging.getLogger(
|
116
|
-
f"{logging.getLogger(self.__class__.__name__)} - {self.username}@{self.hostname}:{self.port}"
|
117
|
-
)
|
118
|
-
|
119
|
-
self.async_conn: Optional[asyncssh.SSHClientConnection] = None
|
120
|
-
|
121
|
-
self.sync_client = paramiko.SSHClient()
|
122
|
-
self.sync_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
123
|
-
|
124
|
-
"""SYNC"""
|
125
|
-
|
126
|
-
def sync_connect(self) -> SSHRunner:
|
127
|
-
try:
|
128
|
-
self.sync_client.connect(
|
129
|
-
hostname=self.hostname,
|
130
|
-
username=self.username,
|
131
|
-
password=self.password,
|
132
|
-
port=self.port,
|
133
|
-
timeout=self.base_timeout,
|
134
|
-
auth_timeout=self.base_timeout,
|
135
|
-
banner_timeout=self.base_timeout,
|
136
|
-
channel_timeout=self.base_timeout
|
137
|
-
)
|
138
|
-
except Exception as err:
|
139
|
-
raise SSHCannotConnect(err)
|
140
|
-
return self
|
141
|
-
|
142
|
-
def sync_check_connection(self):
|
143
|
-
self.sync_connect()
|
144
|
-
|
145
|
-
def sync_is_conn_good(self) -> bool:
|
146
|
-
try:
|
147
|
-
self.sync_check_connection()
|
148
|
-
except SSHCannotConnect:
|
149
|
-
return False
|
150
|
-
return True
|
151
|
-
|
152
|
-
def sync_run(
|
153
|
-
self,
|
154
|
-
command: str,
|
155
|
-
*,
|
156
|
-
timeout: float | None = SSHRunTimeouts.medium_command,
|
157
|
-
raise_for_bad_return_code: bool = True
|
158
|
-
) -> SSHRunRes:
|
159
|
-
if timeout is None:
|
160
|
-
timeout = self.base_timeout
|
161
|
-
|
162
|
-
self._logger.info(command)
|
163
|
-
|
164
|
-
self.sync_connect()
|
165
|
-
|
166
|
-
try:
|
167
|
-
stdin, stdout, stderr = self.sync_client.exec_command(
|
168
|
-
command=command,
|
169
|
-
timeout=timeout
|
170
|
-
)
|
171
|
-
return_code = stdout.channel.recv_exit_status()
|
172
|
-
stdout = stdout.read().decode()
|
173
|
-
stderr = stderr.read().decode()
|
174
|
-
except Exception as err:
|
175
|
-
raise SSHCannotRun(err)
|
176
|
-
|
177
|
-
ssh_run_res = SSHRunRes(
|
178
|
-
out=stdout,
|
179
|
-
err=stderr,
|
180
|
-
return_code=return_code
|
181
|
-
)
|
182
|
-
if raise_for_bad_return_code is True:
|
183
|
-
ssh_run_res.raise_for_bad_return_code()
|
184
|
-
|
185
|
-
return ssh_run_res
|
186
|
-
|
187
|
-
def sync_close(self):
|
188
|
-
self.sync_client.close()
|
189
|
-
|
190
|
-
"""ASYNC SYNC"""
|
191
|
-
|
192
|
-
async def async_connect(self) -> SSHRunner:
|
193
|
-
if self.async_conn is None:
|
194
|
-
try:
|
195
|
-
self.async_conn = await asyncssh.connect(
|
196
|
-
host=self.hostname,
|
197
|
-
username=self.username,
|
198
|
-
password=self.password,
|
199
|
-
port=self.port,
|
200
|
-
connect_timeout=self.base_timeout,
|
201
|
-
known_hosts=None
|
202
|
-
)
|
203
|
-
except Exception as err:
|
204
|
-
raise SSHCannotConnect(err)
|
205
|
-
return self
|
206
|
-
|
207
|
-
async def async_check_connection(self):
|
208
|
-
await self.async_connect()
|
209
|
-
|
210
|
-
async def async_is_conn_good(self) -> bool:
|
211
|
-
try:
|
212
|
-
await self.async_check_connection()
|
213
|
-
except SSHCannotConnect:
|
214
|
-
return False
|
215
|
-
return True
|
216
|
-
|
217
|
-
async def async_run(
|
218
|
-
self,
|
219
|
-
command: str,
|
220
|
-
*,
|
221
|
-
timeout: float | None = SSHRunTimeouts.medium_command,
|
222
|
-
raise_for_bad_return_code: bool = True
|
223
|
-
) -> SSHRunRes:
|
224
|
-
if timeout is None:
|
225
|
-
timeout = self.base_timeout
|
226
|
-
|
227
|
-
self._logger.info(command)
|
228
|
-
|
229
|
-
await self.async_connect()
|
230
|
-
|
231
|
-
try:
|
232
|
-
result: asyncssh.SSHCompletedProcess = await self.async_conn.run(
|
233
|
-
command,
|
234
|
-
check=False,
|
235
|
-
timeout=timeout
|
236
|
-
)
|
237
|
-
except Exception as err:
|
238
|
-
raise SSHCannotRun(err)
|
239
|
-
|
240
|
-
ssh_run_res = SSHRunRes(
|
241
|
-
out=result.stdout,
|
242
|
-
err=result.stderr,
|
243
|
-
return_code=result.returncode
|
244
|
-
)
|
245
|
-
if raise_for_bad_return_code is True:
|
246
|
-
ssh_run_res.raise_for_bad_return_code()
|
247
|
-
|
248
|
-
return ssh_run_res
|
249
|
-
|
250
|
-
def async_close(self):
|
251
|
-
if self.async_conn is not None:
|
252
|
-
self.async_conn.close()
|
253
|
-
self.async_conn = None
|
254
|
-
|
255
|
-
|
256
|
-
def __example():
|
257
|
-
pass
|
258
|
-
|
259
|
-
|
260
|
-
async def __async_example():
|
261
|
-
pass
|
262
|
-
|
263
|
-
|
264
|
-
if __name__ == '__main__':
|
265
|
-
__example()
|
266
|
-
asyncio.run(__async_example())
|
File without changes
|
File without changes
|
File without changes
|