appmesh 1.1.9__py3-none-any.whl → 1.2.1__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.
- appmesh/appmesh_client.py +97 -45
- {appmesh-1.1.9.dist-info → appmesh-1.2.1.dist-info}/METADATA +1 -1
- appmesh-1.2.1.dist-info/RECORD +6 -0
- appmesh-1.1.9.dist-info/RECORD +0 -6
- {appmesh-1.1.9.dist-info → appmesh-1.2.1.dist-info}/WHEEL +0 -0
- {appmesh-1.1.9.dist-info → appmesh-1.2.1.dist-info}/top_level.txt +0 -0
appmesh/appmesh_client.py
CHANGED
@@ -10,9 +10,10 @@ import ssl
|
|
10
10
|
import uuid
|
11
11
|
|
12
12
|
from enum import Enum, unique
|
13
|
+
from datetime import datetime
|
13
14
|
from http import HTTPStatus
|
15
|
+
from typing import Optional
|
14
16
|
from urllib import parse
|
15
|
-
from datetime import datetime
|
16
17
|
|
17
18
|
import aniso8601
|
18
19
|
import requests
|
@@ -48,6 +49,24 @@ def _get_native_item(data: dict, key):
|
|
48
49
|
return copy.deepcopy(data[key]) if (data and key in data and data[key]) else None
|
49
50
|
|
50
51
|
|
52
|
+
class AppOutput(object):
|
53
|
+
"""App output object for app_output() method"""
|
54
|
+
|
55
|
+
def __init__(self, status_code: HTTPStatus, output: str, out_position: Optional[int], exit_code: Optional[int]) -> None:
|
56
|
+
|
57
|
+
self.status_code = status_code
|
58
|
+
"""HTTP status code"""
|
59
|
+
|
60
|
+
self.output = output
|
61
|
+
"""HTTP response text"""
|
62
|
+
|
63
|
+
self.out_position = out_position
|
64
|
+
"""Current read position (int or None)"""
|
65
|
+
|
66
|
+
self.exit_code = exit_code
|
67
|
+
"""Process exit code (int or None)"""
|
68
|
+
|
69
|
+
|
51
70
|
class App(object):
|
52
71
|
"""
|
53
72
|
App object present an application in App Mesh
|
@@ -78,10 +97,12 @@ class App(object):
|
|
78
97
|
def __init__(self, data=None) -> None:
|
79
98
|
if isinstance(data, (str, bytes, bytearray)):
|
80
99
|
data = json.loads(data)
|
81
|
-
|
100
|
+
|
82
101
|
self.exit = _get_str_item(data, "exit")
|
83
|
-
|
102
|
+
"""default exit behavior [restart,standby,keepalive,remove]"""
|
103
|
+
|
84
104
|
self.control = _get_native_item(data, "control") if _get_native_item(data, "control") else dict()
|
105
|
+
"""exit code behavior (e.g, --control 0:restart --control 1:standby), higher priority than default exit behavior"""
|
85
106
|
|
86
107
|
def set_exit_behavior(self, a: Action) -> None:
|
87
108
|
"""Set error handling behavior while application exit"""
|
@@ -99,10 +120,12 @@ class App(object):
|
|
99
120
|
def __init__(self, data=None) -> None:
|
100
121
|
if isinstance(data, (str, bytes, bytearray)):
|
101
122
|
data = json.loads(data)
|
102
|
-
|
123
|
+
|
103
124
|
self.daily_start = _get_int_item(data, "daily_start")
|
104
|
-
|
125
|
+
"""daily start time (e.g., '09:00:00+08')"""
|
126
|
+
|
105
127
|
self.daily_end = _get_int_item(data, "daily_end")
|
128
|
+
"""daily end time (e.g., '20:00:00+08')"""
|
106
129
|
|
107
130
|
def set_daily_range(self, start: datetime, end: datetime) -> None:
|
108
131
|
"""Set valid day hour range"""
|
@@ -117,12 +140,15 @@ class App(object):
|
|
117
140
|
def __init__(self, data=None) -> None:
|
118
141
|
if isinstance(data, (str, bytes, bytearray)):
|
119
142
|
data = json.loads(data)
|
120
|
-
|
143
|
+
|
121
144
|
self.cpu_shares = _get_int_item(data, "cpu_shares")
|
122
|
-
|
145
|
+
"""CPU shares (relative weight)"""
|
146
|
+
|
123
147
|
self.memory_mb = _get_int_item(data, "memory_mb")
|
124
|
-
|
148
|
+
"""physical memory limit in MByte"""
|
149
|
+
|
125
150
|
self.memory_virt_mb = _get_int_item(data, "memory_virt_mb")
|
151
|
+
"""virtual memory limit in MByte"""
|
126
152
|
|
127
153
|
def __init__(self, data=None):
|
128
154
|
"""Construct an App Mesh Application object
|
@@ -134,73 +160,99 @@ class App(object):
|
|
134
160
|
if isinstance(data, (str, bytes, bytearray)):
|
135
161
|
data = json.loads(data)
|
136
162
|
|
137
|
-
# application name
|
138
163
|
self.name = _get_str_item(data, "name")
|
139
|
-
|
164
|
+
"""application name (unique)"""
|
165
|
+
|
140
166
|
self.command = _get_str_item(data, "command")
|
167
|
+
"""full command line with arguments"""
|
141
168
|
|
142
|
-
# use shell mode, cmd can be more shell commands with string format
|
143
169
|
self.shell = _get_bool_item(data, "shell")
|
144
|
-
|
170
|
+
"""use shell mode, cmd can be more shell commands with string format"""
|
171
|
+
|
145
172
|
self.session_login = _get_bool_item(data, "session_login")
|
146
|
-
|
173
|
+
"""app run in session login mode"""
|
174
|
+
|
147
175
|
self.description = _get_str_item(data, "description")
|
148
|
-
|
176
|
+
"""application description string"""
|
177
|
+
|
149
178
|
self.metadata = _get_native_item(data, "metadata")
|
150
|
-
|
179
|
+
"""metadata string/JSON (input for application, pass to process stdin)"""
|
180
|
+
|
151
181
|
self.working_dir = _get_str_item(data, "working_dir")
|
152
|
-
|
182
|
+
"""working directory"""
|
183
|
+
|
153
184
|
self.status = _get_int_item(data, "status")
|
154
|
-
|
185
|
+
"""initial application status (true is enable, false is disabled)"""
|
186
|
+
|
155
187
|
self.docker_image = _get_str_item(data, "docker_image")
|
156
|
-
|
188
|
+
"""docker image which used to run command line (for docker container application)"""
|
189
|
+
|
157
190
|
self.stdout_cache_num = _get_int_item(data, "stdout_cache_num")
|
191
|
+
"""stdout file cache number"""
|
158
192
|
|
159
|
-
# start date time for app (ISO8601 time format, e.g., '2020-10-11T09:22:05')
|
160
193
|
self.start_time = _get_int_item(data, "start_time")
|
161
|
-
|
194
|
+
"""start date time for app (ISO8601 time format, e.g., '2020-10-11T09:22:05')"""
|
195
|
+
|
162
196
|
self.end_time = _get_int_item(data, "end_time")
|
163
|
-
|
197
|
+
"""end date time for app (ISO8601 time format, e.g., '2020-10-11T10:22:05')"""
|
198
|
+
|
164
199
|
self.interval = _get_int_item(data, "interval")
|
165
|
-
|
200
|
+
"""start interval seconds for short running app, support ISO 8601 durations and cron expression (e.g., 'P1Y2M3DT4H5M6S' 'P5W' '* */5 * * * *')"""
|
201
|
+
|
166
202
|
self.cron = _get_bool_item(data, "cron")
|
203
|
+
"""indicate interval parameter use cron expression or not"""
|
204
|
+
|
167
205
|
self.daily_limitation = App.DailyLimitation(_get_native_item(data, "daily_limitation"))
|
168
206
|
|
169
|
-
# extra timeout seconds for stopping current process, support ISO 8601 durations (e.g., 'P1Y2M3DT4H5M6S' 'P5W').
|
170
207
|
self.retention = _get_str_item(data, "retention")
|
208
|
+
"""extra timeout seconds for stopping current process, support ISO 8601 durations (e.g., 'P1Y2M3DT4H5M6S' 'P5W')."""
|
171
209
|
|
172
|
-
# health check script command (e.g., sh -x 'curl host:port/health', return 0 is health)
|
173
210
|
self.health_check_cmd = _get_str_item(data, "health_check_cmd")
|
174
|
-
|
211
|
+
"""health check script command (e.g., sh -x 'curl host:port/health', return 0 is health)"""
|
212
|
+
|
175
213
|
self.permission = _get_int_item(data, "permission")
|
214
|
+
"""application user permission, value is 2 bit integer: [group & other], each bit can be deny:1, read:2, write: 3."""
|
176
215
|
self.behavior = App.Behavior(_get_native_item(data, "behavior"))
|
177
216
|
|
178
|
-
# environment variables (e.g., -e env1=value1 -e env2=value2, APP_DOCKER_OPTS is used to input docker run parameters)
|
179
217
|
self.env = dict()
|
218
|
+
"""environment variables (e.g., -e env1=value1 -e env2=value2, APP_DOCKER_OPTS is used to input docker run parameters)"""
|
180
219
|
if data and "env" in data:
|
181
220
|
for k, v in data["env"].items():
|
182
221
|
self.env[k] = v
|
183
|
-
|
222
|
+
|
184
223
|
self.sec_env = dict()
|
224
|
+
"""security environment variables, encrypt in server side with application owner's cipher"""
|
185
225
|
if data and "sec_env" in data:
|
186
226
|
for k, v in data["sec_env"].items():
|
187
227
|
self.sec_env[k] = v
|
188
|
-
|
228
|
+
|
189
229
|
self.pid = _get_int_item(data, "pid")
|
230
|
+
"""process id used to attach to the running process"""
|
190
231
|
self.resource_limit = App.ResourceLimitation(_get_native_item(data, "resource_limit"))
|
191
232
|
|
192
233
|
# readonly attributes
|
193
234
|
self.owner = _get_str_item(data, "owner")
|
235
|
+
"""owner name"""
|
194
236
|
self.pstree = _get_str_item(data, "pstree")
|
237
|
+
"""process tree"""
|
195
238
|
self.container_id = _get_str_item(data, "container_id")
|
239
|
+
"""container id"""
|
196
240
|
self.memory = _get_int_item(data, "memory")
|
241
|
+
"""memory usage"""
|
197
242
|
self.cpu = _get_int_item(data, "cpu")
|
243
|
+
"""cpu usage"""
|
198
244
|
self.fd = _get_int_item(data, "fd")
|
245
|
+
"""file descriptor usage"""
|
199
246
|
self.last_start_time = _get_int_item(data, "last_start_time")
|
247
|
+
"""last start time"""
|
200
248
|
self.last_exit_time = _get_int_item(data, "last_exit_time")
|
249
|
+
"""last exit time"""
|
201
250
|
self.health = _get_int_item(data, "health")
|
251
|
+
"""health status"""
|
202
252
|
self.version = _get_int_item(data, "version")
|
253
|
+
"""version number"""
|
203
254
|
self.return_code = _get_int_item(data, "return_code")
|
255
|
+
"""last exit code"""
|
204
256
|
|
205
257
|
def set_valid_time(self, start: datetime, end: datetime) -> None:
|
206
258
|
"""Set avialable time window"""
|
@@ -250,8 +302,11 @@ class Run(object):
|
|
250
302
|
|
251
303
|
def __init__(self, client, app_name: str, process_id: str):
|
252
304
|
self.app_name = app_name
|
305
|
+
"""application name"""
|
253
306
|
self.proc_uid = process_id
|
307
|
+
"""process_uuid from run_async()"""
|
254
308
|
self.__client = client
|
309
|
+
"""AppMeshClient object"""
|
255
310
|
|
256
311
|
def wait(self, stdout_print: bool = True, timeout: int = 0) -> int:
|
257
312
|
"""Wait for an async run to be finished
|
@@ -302,6 +357,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
302
357
|
rest_timeout (tuple, optional): HTTP timeout, Defaults to 60 seconds for connect timeout and 300 seconds for read timeout
|
303
358
|
jwt_token (str, optional): JWT token, provide correct token is same with login() & authenticate().
|
304
359
|
"""
|
360
|
+
|
305
361
|
self.server_url = rest_url
|
306
362
|
self.__jwt_token = jwt_token
|
307
363
|
self.ssl_verify = rest_ssl_verify
|
@@ -539,7 +595,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
539
595
|
apps.append(App(app))
|
540
596
|
return apps
|
541
597
|
|
542
|
-
def app_output(self, app_name: str, stdout_position: int = 0, stdout_index: int = 0, stdout_maxsize: int = 10240, process_uuid: str = "", timeout: int = 0):
|
598
|
+
def app_output(self, app_name: str, stdout_position: int = 0, stdout_index: int = 0, stdout_maxsize: int = 10240, process_uuid: str = "", timeout: int = 0) -> AppOutput:
|
543
599
|
"""Get application stdout/stderr
|
544
600
|
|
545
601
|
Args:
|
@@ -552,10 +608,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
552
608
|
timeout (int, optional): wait for the running process for some time(seconds) to get the output.
|
553
609
|
|
554
610
|
Returns:
|
555
|
-
|
556
|
-
str: output string.
|
557
|
-
int or None: current read position.
|
558
|
-
int or None: process exit code.
|
611
|
+
AppOutput object.
|
559
612
|
"""
|
560
613
|
resp = self._request_http(
|
561
614
|
AppMeshClient.Method.GET,
|
@@ -570,7 +623,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
570
623
|
)
|
571
624
|
out_position = int(resp.headers["Output-Position"]) if "Output-Position" in resp.headers else None
|
572
625
|
exit_code = int(resp.headers["Exit-Code"]) if "Exit-Code" in resp.headers else None
|
573
|
-
return (resp.status_code
|
626
|
+
return AppOutput(status_code=resp.status_code, output=resp.text, out_position=out_position, exit_code=exit_code)
|
574
627
|
|
575
628
|
def app_health(self, app_name: str) -> int:
|
576
629
|
"""Get application health status, 0 is health.
|
@@ -1169,28 +1222,27 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
1169
1222
|
Returns:
|
1170
1223
|
int: return exit code if process finished, return None for timeout or exception.
|
1171
1224
|
"""
|
1172
|
-
exit_code = None
|
1173
1225
|
if run:
|
1174
|
-
|
1226
|
+
last_output_position = 0
|
1175
1227
|
start = datetime.now()
|
1176
1228
|
interval = 1 if self.__class__.__name__ == "AppMeshClient" else 1000
|
1177
1229
|
while len(run.proc_uid) > 0:
|
1178
|
-
|
1179
|
-
if output and stdout_print:
|
1180
|
-
print(output, end="")
|
1181
|
-
if
|
1182
|
-
|
1183
|
-
if exit_code is not None:
|
1230
|
+
app_out = self.app_output(app_name=run.app_name, stdout_position=last_output_position, stdout_index=0, process_uuid=run.proc_uid, timeout=interval)
|
1231
|
+
if app_out.output and stdout_print:
|
1232
|
+
print(app_out.output, end="")
|
1233
|
+
if app_out.out_position is not None:
|
1234
|
+
last_output_position = app_out.out_position
|
1235
|
+
if app_out.exit_code is not None:
|
1184
1236
|
# success
|
1185
1237
|
self.app_delete(run.app_name)
|
1186
|
-
|
1187
|
-
if
|
1238
|
+
return app_out.exit_code
|
1239
|
+
if app_out.status_code != HTTPStatus.OK:
|
1188
1240
|
# failed
|
1189
1241
|
break
|
1190
1242
|
if timeout > 0 and (datetime.now() - start).seconds > timeout:
|
1191
1243
|
# timeout
|
1192
1244
|
break
|
1193
|
-
return
|
1245
|
+
return None
|
1194
1246
|
|
1195
1247
|
def run_sync(
|
1196
1248
|
self,
|
@@ -0,0 +1,6 @@
|
|
1
|
+
appmesh/__init__.py,sha256=xRdXeFHEieRauuJZElbEBASgXG0ZzU1a5_0isAhM7Gw,11
|
2
|
+
appmesh/appmesh_client.py,sha256=b1UOMQm8GUy6WAl3385YGMbs4qyZqKukZn9vx8RRswU,60702
|
3
|
+
appmesh-1.2.1.dist-info/METADATA,sha256=l4ZxoKiK0ftZ8HqGi7A7wbm77-1shEFyFCsNYR1tzzs,10928
|
4
|
+
appmesh-1.2.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
5
|
+
appmesh-1.2.1.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
|
6
|
+
appmesh-1.2.1.dist-info/RECORD,,
|
appmesh-1.1.9.dist-info/RECORD
DELETED
@@ -1,6 +0,0 @@
|
|
1
|
-
appmesh/__init__.py,sha256=xRdXeFHEieRauuJZElbEBASgXG0ZzU1a5_0isAhM7Gw,11
|
2
|
-
appmesh/appmesh_client.py,sha256=8nnB38J3wvS8tguEzX_KTJkilW6uMoA4opKIaDq1lG0,59591
|
3
|
-
appmesh-1.1.9.dist-info/METADATA,sha256=UDHcFjxQFDL5Ld2v-LguTsuWcx8_pzKR6I3wyMHI3is,10928
|
4
|
-
appmesh-1.1.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
5
|
-
appmesh-1.1.9.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
|
6
|
-
appmesh-1.1.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|