appmesh 1.3.2__py3-none-any.whl → 1.3.3__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 CHANGED
@@ -24,59 +24,48 @@ import requests
24
24
  DEFAULT_TOKEN_EXPIRE_SECONDS = "P1W" # default 7 day(s)
25
25
  DEFAULT_RUN_APP_TIMEOUT_SECONDS = "P2D" # 2 days
26
26
  DEFAULT_RUN_APP_LIFECYCLE_SECONDS = "P2DT12H" # 2.5 days
27
+
27
28
  REST_TEXT_MESSAGE_JSON_KEY = "message"
28
29
  MESSAGE_ENCODING_UTF8 = "utf-8"
29
30
  TCP_MESSAGE_HEADER_LENGTH = 4
31
+
30
32
  _SSL_CA_PEM_FILE = "/opt/appmesh/ssl/ca.pem"
31
33
  _SSL_CLIENT_PEM_FILE = "/opt/appmesh/ssl/client.pem"
32
34
  _SSL_CLIENT_PEM_KEY_FILE = "/opt/appmesh/ssl/client-key.pem"
33
- HTTP_USER_AGENT_HEADER_NAME = "User-Agent"
35
+
34
36
  HTTP_USER_AGENT = "appmesh/python"
35
37
  HTTP_USER_AGENT_TCP = "appmesh/python/tcp"
38
+ HTTP_HEADER_KEY_USER_AGENT = "User-Agent"
36
39
  HTTP_HEADER_KEY_X_SEND_FILE_SOCKET = "X-Send-File-Socket"
37
40
  HTTP_HEADER_KEY_X_RECV_FILE_SOCKET = "X-Recv-File-Socket"
38
41
  HTTP_HEADER_KEY_X_TARGET_HOST = "X-Target-Host"
39
42
 
40
43
 
41
- def _get_str_item(data: dict, key):
42
- return data[key] if (data and key in data and data[key] and isinstance(data[key], str)) else None
43
-
44
-
45
- def _get_int_item(data: dict, key):
46
- return int(data[key]) if (data and key in data and data[key] and isinstance(data[key], int)) else None
47
-
48
-
49
- def _get_bool_item(data: dict, key):
50
- return bool(data[key]) if (data and key in data and data[key]) else None
51
-
52
-
53
- def _get_native_item(data: dict, key):
54
- return copy.deepcopy(data[key]) if (data and key in data and data[key]) else None
55
-
56
-
57
- class AppOutput(object):
58
- """App output object for app_output() method"""
59
-
60
- def __init__(self, status_code: HTTPStatus, output: str, out_position: Optional[int], exit_code: Optional[int]) -> None:
61
-
62
- self.status_code = status_code
63
- """HTTP status code"""
64
-
65
- self.output = output
66
- """HTTP response text"""
67
-
68
- self.out_position = out_position
69
- """Current read position (int or None)"""
70
-
71
- self.exit_code = exit_code
72
- """Process exit code (int or None)"""
73
-
74
-
75
44
  class App(object):
76
45
  """
77
46
  App object present an application in App Mesh
78
47
  """
79
48
 
49
+ @staticmethod
50
+ def _get_str_item(data: dict, key) -> Optional[str]:
51
+ """Retrieve a string value from a dictionary by key, if it exists and is a valid string."""
52
+ return data[key] if (data and key in data and data[key] and isinstance(data[key], str)) else None
53
+
54
+ @staticmethod
55
+ def _get_int_item(data: dict, key) -> Optional[int]:
56
+ """Retrieve an integer value from a dictionary by key, if it exists and is a valid integer."""
57
+ return int(data[key]) if (data and key in data and data[key] and isinstance(data[key], int)) else None
58
+
59
+ @staticmethod
60
+ def _get_bool_item(data: dict, key) -> Optional[bool]:
61
+ """Retrieve a boolean value from a dictionary by key, if it exists."""
62
+ return bool(data[key]) if (data and key in data and data[key]) else None
63
+
64
+ @staticmethod
65
+ def _get_native_item(data: dict, key) -> Optional[object]:
66
+ """Retrieve a deep copy of a value from a dictionary by key, if it exists."""
67
+ return copy.deepcopy(data[key]) if (data and key in data and data[key]) else None
68
+
80
69
  @unique
81
70
  class Permission(Enum):
82
71
  """Application permission definition"""
@@ -103,10 +92,10 @@ class App(object):
103
92
  if isinstance(data, (str, bytes, bytearray)):
104
93
  data = json.loads(data)
105
94
 
106
- self.exit = _get_str_item(data, "exit")
95
+ self.exit = App._get_str_item(data, "exit")
107
96
  """default exit behavior [restart,standby,keepalive,remove]"""
108
97
 
109
- self.control = _get_native_item(data, "control") if _get_native_item(data, "control") else dict()
98
+ self.control = App._get_native_item(data, "control") if App._get_native_item(data, "control") else dict()
110
99
  """exit code behavior (e.g, --control 0:restart --control 1:standby), higher priority than default exit behavior"""
111
100
 
112
101
  def set_exit_behavior(self, a: Action) -> None:
@@ -126,10 +115,10 @@ class App(object):
126
115
  if isinstance(data, (str, bytes, bytearray)):
127
116
  data = json.loads(data)
128
117
 
129
- self.daily_start = _get_int_item(data, "daily_start")
118
+ self.daily_start = App._get_int_item(data, "daily_start")
130
119
  """daily start time (e.g., '09:00:00+08')"""
131
120
 
132
- self.daily_end = _get_int_item(data, "daily_end")
121
+ self.daily_end = App._get_int_item(data, "daily_end")
133
122
  """daily end time (e.g., '20:00:00+08')"""
134
123
 
135
124
  def set_daily_range(self, start: datetime, end: datetime) -> None:
@@ -146,13 +135,13 @@ class App(object):
146
135
  if isinstance(data, (str, bytes, bytearray)):
147
136
  data = json.loads(data)
148
137
 
149
- self.cpu_shares = _get_int_item(data, "cpu_shares")
138
+ self.cpu_shares = App._get_int_item(data, "cpu_shares")
150
139
  """CPU shares (relative weight)"""
151
140
 
152
- self.memory_mb = _get_int_item(data, "memory_mb")
141
+ self.memory_mb = App._get_int_item(data, "memory_mb")
153
142
  """physical memory limit in MByte"""
154
143
 
155
- self.memory_virt_mb = _get_int_item(data, "memory_virt_mb")
144
+ self.memory_virt_mb = App._get_int_item(data, "memory_virt_mb")
156
145
  """virtual memory limit in MByte"""
157
146
 
158
147
  def __init__(self, data=None):
@@ -165,59 +154,59 @@ class App(object):
165
154
  if isinstance(data, (str, bytes, bytearray)):
166
155
  data = json.loads(data)
167
156
 
168
- self.name = _get_str_item(data, "name")
157
+ self.name = App._get_str_item(data, "name")
169
158
  """application name (unique)"""
170
159
 
171
- self.command = _get_str_item(data, "command")
160
+ self.command = App._get_str_item(data, "command")
172
161
  """full command line with arguments"""
173
162
 
174
- self.shell = _get_bool_item(data, "shell")
163
+ self.shell = App._get_bool_item(data, "shell")
175
164
  """use shell mode, cmd can be more shell commands with string format"""
176
165
 
177
- self.session_login = _get_bool_item(data, "session_login")
166
+ self.session_login = App._get_bool_item(data, "session_login")
178
167
  """app run in session login mode"""
179
168
 
180
- self.description = _get_str_item(data, "description")
169
+ self.description = App._get_str_item(data, "description")
181
170
  """application description string"""
182
171
 
183
- self.metadata = _get_native_item(data, "metadata")
172
+ self.metadata = App._get_native_item(data, "metadata")
184
173
  """metadata string/JSON (input for application, pass to process stdin)"""
185
174
 
186
- self.working_dir = _get_str_item(data, "working_dir")
175
+ self.working_dir = App._get_str_item(data, "working_dir")
187
176
  """working directory"""
188
177
 
189
- self.status = _get_int_item(data, "status")
178
+ self.status = App._get_int_item(data, "status")
190
179
  """initial application status (true is enable, false is disabled)"""
191
180
 
192
- self.docker_image = _get_str_item(data, "docker_image")
181
+ self.docker_image = App._get_str_item(data, "docker_image")
193
182
  """docker image which used to run command line (for docker container application)"""
194
183
 
195
- self.stdout_cache_num = _get_int_item(data, "stdout_cache_num")
184
+ self.stdout_cache_num = App._get_int_item(data, "stdout_cache_num")
196
185
  """stdout file cache number"""
197
186
 
198
- self.start_time = _get_int_item(data, "start_time")
187
+ self.start_time = App._get_int_item(data, "start_time")
199
188
  """start date time for app (ISO8601 time format, e.g., '2020-10-11T09:22:05')"""
200
189
 
201
- self.end_time = _get_int_item(data, "end_time")
190
+ self.end_time = App._get_int_item(data, "end_time")
202
191
  """end date time for app (ISO8601 time format, e.g., '2020-10-11T10:22:05')"""
203
192
 
204
- self.interval = _get_int_item(data, "interval")
193
+ self.interval = App._get_int_item(data, "interval")
205
194
  """start interval seconds for short running app, support ISO 8601 durations and cron expression (e.g., 'P1Y2M3DT4H5M6S' 'P5W' '* */5 * * * *')"""
206
195
 
207
- self.cron = _get_bool_item(data, "cron")
196
+ self.cron = App._get_bool_item(data, "cron")
208
197
  """indicate interval parameter use cron expression or not"""
209
198
 
210
- self.daily_limitation = App.DailyLimitation(_get_native_item(data, "daily_limitation"))
199
+ self.daily_limitation = App.DailyLimitation(App._get_native_item(data, "daily_limitation"))
211
200
 
212
- self.retention = _get_str_item(data, "retention")
201
+ self.retention = App._get_str_item(data, "retention")
213
202
  """extra timeout seconds for stopping current process, support ISO 8601 durations (e.g., 'P1Y2M3DT4H5M6S' 'P5W')."""
214
203
 
215
- self.health_check_cmd = _get_str_item(data, "health_check_cmd")
204
+ self.health_check_cmd = App._get_str_item(data, "health_check_cmd")
216
205
  """health check script command (e.g., sh -x 'curl host:port/health', return 0 is health)"""
217
206
 
218
- self.permission = _get_int_item(data, "permission")
207
+ self.permission = App._get_int_item(data, "permission")
219
208
  """application user permission, value is 2 bit integer: [group & other], each bit can be deny:1, read:2, write: 3."""
220
- self.behavior = App.Behavior(_get_native_item(data, "behavior"))
209
+ self.behavior = App.Behavior(App._get_native_item(data, "behavior"))
221
210
 
222
211
  self.env = dict()
223
212
  """environment variables (e.g., -e env1=value1 -e env2=value2, APP_DOCKER_OPTS is used to input docker run parameters)"""
@@ -231,32 +220,32 @@ class App(object):
231
220
  for k, v in data["sec_env"].items():
232
221
  self.sec_env[k] = v
233
222
 
234
- self.pid = _get_int_item(data, "pid")
223
+ self.pid = App._get_int_item(data, "pid")
235
224
  """process id used to attach to the running process"""
236
- self.resource_limit = App.ResourceLimitation(_get_native_item(data, "resource_limit"))
225
+ self.resource_limit = App.ResourceLimitation(App._get_native_item(data, "resource_limit"))
237
226
 
238
227
  # readonly attributes
239
- self.owner = _get_str_item(data, "owner")
228
+ self.owner = App._get_str_item(data, "owner")
240
229
  """owner name"""
241
- self.pstree = _get_str_item(data, "pstree")
230
+ self.pstree = App._get_str_item(data, "pstree")
242
231
  """process tree"""
243
- self.container_id = _get_str_item(data, "container_id")
232
+ self.container_id = App._get_str_item(data, "container_id")
244
233
  """container id"""
245
- self.memory = _get_int_item(data, "memory")
234
+ self.memory = App._get_int_item(data, "memory")
246
235
  """memory usage"""
247
- self.cpu = _get_int_item(data, "cpu")
236
+ self.cpu = App._get_int_item(data, "cpu")
248
237
  """cpu usage"""
249
- self.fd = _get_int_item(data, "fd")
238
+ self.fd = App._get_int_item(data, "fd")
250
239
  """file descriptor usage"""
251
- self.last_start_time = _get_int_item(data, "last_start_time")
240
+ self.last_start_time = App._get_int_item(data, "last_start_time")
252
241
  """last start time"""
253
- self.last_exit_time = _get_int_item(data, "last_exit_time")
242
+ self.last_exit_time = App._get_int_item(data, "last_exit_time")
254
243
  """last exit time"""
255
- self.health = _get_int_item(data, "health")
244
+ self.health = App._get_int_item(data, "health")
256
245
  """health status"""
257
- self.version = _get_int_item(data, "version")
246
+ self.version = App._get_int_item(data, "version")
258
247
  """version number"""
259
- self.return_code = _get_int_item(data, "return_code")
248
+ self.return_code = App._get_int_item(data, "return_code")
260
249
  """last exit code"""
261
250
 
262
251
  def set_valid_time(self, start: datetime, end: datetime) -> None:
@@ -300,6 +289,24 @@ class App(object):
300
289
  return output
301
290
 
302
291
 
292
+ class AppOutput(object):
293
+ """App output information"""
294
+
295
+ def __init__(self, status_code: HTTPStatus, output: str, out_position: Optional[int], exit_code: Optional[int]) -> None:
296
+
297
+ self.status_code = status_code
298
+ """HTTP status code"""
299
+
300
+ self.output = output
301
+ """HTTP response text"""
302
+
303
+ self.out_position = out_position
304
+ """Current read position (int or None)"""
305
+
306
+ self.exit_code = exit_code
307
+ """Process exit code (int or None)"""
308
+
309
+
303
310
  class AppRun(object):
304
311
  """
305
312
  Application run object indicate to a remote run from run_async()
@@ -340,10 +347,81 @@ class AppRun(object):
340
347
 
341
348
 
342
349
  class AppMeshClient(metaclass=abc.ABCMeta):
343
- """App Mesh client object used to access App Mesh REST Service
344
-
345
- - install pip package: python3 -m pip install --upgrade appmesh
346
- - import module: from appmesh import appmesh_client
350
+ """
351
+ Client SDK for interacting with the App Mesh service via REST API.
352
+
353
+ The `AppMeshClient` class provides a comprehensive interface for managing and monitoring distributed applications
354
+ within the App Mesh ecosystem. It enables communication with the App Mesh REST API for operations such as
355
+ application lifecycle management, monitoring, and configuration.
356
+
357
+ This client is designed for direct usage in applications that require access to App Mesh services over HTTP-based REST.
358
+
359
+ Usage:
360
+ - Install the App Mesh Python package:
361
+ python3 -m pip install --upgrade appmesh
362
+ - Import the client module:
363
+ from appmesh import appmesh_client
364
+
365
+ Example:
366
+ client = appmesh_client.AppMeshClient()
367
+ client.login("your-name", "your-password")
368
+ response = client.app_view(app_name='ping')
369
+
370
+ Attributes:
371
+ - TLS (Transport Layer Security): Supports secure connections between the client and App Mesh service,
372
+ ensuring encrypted communication.
373
+ - JWT (JSON Web Token) and RBAC (Role-Based Access Control): Provides secure API access with
374
+ token-based authentication and authorization to enforce fine-grained permissions.
375
+
376
+ Methods:
377
+ - login()
378
+ - logoff()
379
+ - authentication()
380
+ - renew()
381
+ - totp_disable()
382
+ - totp_secret()
383
+ - totp_setup()
384
+
385
+ - app_add()
386
+ - app_delete()
387
+ - app_disable()
388
+ - app_enable()
389
+ - app_health()
390
+ - app_output()
391
+ - app_view()
392
+ - app_view_all()
393
+
394
+ - run_async()
395
+ - run_async_wait()
396
+ - run_sync()
397
+
398
+ - config_set()
399
+ - config_view()
400
+ - log_level_set()
401
+ - host_resource()
402
+ - forwarding_host
403
+ - metrics()
404
+
405
+ - tag_add()
406
+ - tag_delete()
407
+ - tag_view()
408
+
409
+ - file_download()
410
+ - file_upload()
411
+
412
+ - user_add()
413
+ - user_delete()
414
+ - user_lock()
415
+ - user_passwd_update()
416
+ - user_self()
417
+ - user_unlock()
418
+ - users_view()
419
+ - permissions_for_user()
420
+ - permissions_view()
421
+ - role_delete()
422
+ - role_update()
423
+ - roles_view()
424
+ - groups_view()
347
425
  """
348
426
 
349
427
  @unique
@@ -475,6 +553,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
475
553
  resp = self._request_http(AppMeshClient.Method.POST, path="/appmesh/self/logoff")
476
554
  if resp.status_code != HTTPStatus.OK:
477
555
  raise Exception(resp.text)
556
+ self.jwt_token = None
478
557
  return resp.status_code == HTTPStatus.OK
479
558
 
480
559
  def authentication(self, token: str, permission=None) -> bool:
@@ -662,7 +741,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
662
741
  return AppOutput(status_code=resp.status_code, output=resp.text, out_position=out_position, exit_code=exit_code)
663
742
 
664
743
  def app_health(self, app_name: str) -> bool:
665
- """Get application health status, 0 is health.
744
+ """Get application health status
666
745
 
667
746
  Args:
668
747
  app_name (str): the application name.
@@ -1142,12 +1221,13 @@ class AppMeshClient(metaclass=abc.ABCMeta):
1142
1221
  ########################################
1143
1222
  # File management
1144
1223
  ########################################
1145
- def file_download(self, file_path: str, local_file: str) -> bool:
1146
- """Copy a remote file to local, the local file will have the same permission as the remote file
1224
+ def file_download(self, file_path: str, local_file: str, apply_file_attributes: bool = True) -> bool:
1225
+ """Copy a remote file to local. Optionally, the local file will have the same permission as the remote file.
1147
1226
 
1148
1227
  Args:
1149
1228
  file_path (str): the remote file path.
1150
1229
  local_file (str): the local file path to be downloaded.
1230
+ apply_file_attributes (bool): whether to apply file attributes (permissions, owner, group) to the local file.
1151
1231
 
1152
1232
  Returns:
1153
1233
  bool: success or failure.
@@ -1156,23 +1236,27 @@ class AppMeshClient(metaclass=abc.ABCMeta):
1156
1236
  if resp.status_code != HTTPStatus.OK:
1157
1237
  raise Exception(resp.text)
1158
1238
 
1239
+ # Write the file content locally
1159
1240
  with open(local_file, "wb") as fp:
1160
1241
  for chunk in resp.iter_content(chunk_size=512):
1161
1242
  if chunk:
1162
1243
  fp.write(chunk)
1163
- if "File-Mode" in resp.headers:
1164
- os.chmod(path=local_file, mode=int(resp.headers["File-Mode"]))
1165
- if "File-User" in resp.headers and "File-Group" in resp.headers:
1166
- file_uid = int(resp.headers["File-User"])
1167
- file_gid = int(resp.headers["File-Group"])
1168
- try:
1169
- os.chown(path=local_file, uid=file_uid, gid=file_gid)
1170
- except Exception as ex:
1171
- print(ex)
1244
+
1245
+ # Apply file attributes (permissions, owner, group) if requested
1246
+ if apply_file_attributes:
1247
+ if "File-Mode" in resp.headers:
1248
+ os.chmod(path=local_file, mode=int(resp.headers["File-Mode"]))
1249
+ if "File-User" in resp.headers and "File-Group" in resp.headers:
1250
+ file_uid = int(resp.headers["File-User"])
1251
+ file_gid = int(resp.headers["File-Group"])
1252
+ try:
1253
+ os.chown(path=local_file, uid=file_uid, gid=file_gid)
1254
+ except Exception as ex:
1255
+ print(ex)
1172
1256
  return resp.status_code == HTTPStatus.OK
1173
1257
 
1174
- def file_upload(self, local_file: str, file_path: str) -> bool:
1175
- """Upload a local file to the remote server, the remote file will have the same permission as the local file
1258
+ def file_upload(self, local_file: str, file_path: str, apply_file_attributes: bool = True) -> bool:
1259
+ """Upload a local file to the remote server. Optionally, the remote file will have the same permission as the local file.
1176
1260
 
1177
1261
  Dependency:
1178
1262
  sudo apt install python3-pip
@@ -1181,6 +1265,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
1181
1265
  Args:
1182
1266
  local_file (str): the local file path.
1183
1267
  file_path (str): the target remote file to be uploaded.
1268
+ apply_file_attributes (bool): whether to upload file attributes (permissions, owner, group) along with the file.
1184
1269
 
1185
1270
  Returns:
1186
1271
  bool: success or failure.
@@ -1189,13 +1274,16 @@ class AppMeshClient(metaclass=abc.ABCMeta):
1189
1274
 
1190
1275
  with open(file=local_file, mode="rb") as fp:
1191
1276
  encoder = MultipartEncoder(fields={"filename": os.path.basename(file_path), "file": ("filename", fp, "application/octet-stream")})
1192
- file_stat = os.stat(local_file)
1193
- header = {}
1194
- header["File-Path"] = file_path
1195
- header["File-Mode"] = str(file_stat.st_mode)
1196
- header["File-User"] = str(file_stat.st_uid)
1197
- header["File-Group"] = str(file_stat.st_gid)
1198
- header["Content-Type"] = encoder.content_type
1277
+ header = {"File-Path": file_path, "Content-Type": encoder.content_type}
1278
+
1279
+ # Include file attributes (permissions, owner, group) if requested
1280
+ if apply_file_attributes:
1281
+ file_stat = os.stat(local_file)
1282
+ header["File-Mode"] = str(file_stat.st_mode)
1283
+ header["File-User"] = str(file_stat.st_uid)
1284
+ header["File-Group"] = str(file_stat.st_gid)
1285
+
1286
+ # Upload file with or without attributes
1199
1287
  # https://stackoverflow.com/questions/22567306/python-requests-file-upload
1200
1288
  resp = self._request_http(
1201
1289
  AppMeshClient.Method.POST_STREAM,
@@ -1340,7 +1428,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
1340
1428
  header[HTTP_HEADER_KEY_X_TARGET_HOST] = self.forwarding_host
1341
1429
  else:
1342
1430
  header[HTTP_HEADER_KEY_X_TARGET_HOST] = self.forwarding_host + ":" + str(parse.urlsplit(self.server_url).port)
1343
- header[HTTP_USER_AGENT_HEADER_NAME] = HTTP_USER_AGENT
1431
+ header[HTTP_HEADER_KEY_USER_AGENT] = HTTP_USER_AGENT
1344
1432
 
1345
1433
  if method is AppMeshClient.Method.GET:
1346
1434
  return requests.get(url=rest_url, params=query, headers=header, cert=self.ssl_client_cert, verify=self.ssl_verify, timeout=self.rest_timeout)
@@ -1359,10 +1447,37 @@ class AppMeshClient(metaclass=abc.ABCMeta):
1359
1447
 
1360
1448
 
1361
1449
  class AppMeshClientTCP(AppMeshClient):
1362
- """Client object used to access App Mesh REST Service over TCP (better performance than AppMeshClient)
1450
+ """
1451
+ Client SDK for interacting with the App Mesh service over TCP, with enhanced support for large file transfers.
1452
+
1453
+ The `AppMeshClientTCP` class extends the functionality of `AppMeshClient` by offering a TCP-based communication layer
1454
+ for the App Mesh REST API. It overrides the file download and upload methods to support large file transfers with
1455
+ improved performance, leveraging TCP for lower latency and higher throughput compared to HTTP.
1456
+
1457
+ This client is suitable for applications requiring efficient data transfers and high-throughput operations within the
1458
+ App Mesh ecosystem, while maintaining compatibility with all other attributes and methods from `AppMeshClient`.
1363
1459
 
1364
1460
  Dependency:
1365
- pip3 install msgpack
1461
+ - Install the required package for message serialization:
1462
+ pip3 install msgpack
1463
+
1464
+ Usage:
1465
+ - Import the client module:
1466
+ from appmesh import appmesh_client
1467
+
1468
+ Example:
1469
+ client = appmesh_client.AppMeshClientTCP()
1470
+ client.login("your-name", "your-password")
1471
+ client.file_download("/tmp/os-release", "os-release")
1472
+
1473
+ Attributes:
1474
+ - Inherits all attributes from `AppMeshClient`, including TLS secure connections and JWT-based authentication.
1475
+ - Optimized for TCP-based communication to provide better performance for large file transfers.
1476
+
1477
+ Methods:
1478
+ - file_download()
1479
+ - file_upload()
1480
+ - Inherits all other methods from `AppMeshClient`, providing a consistent interface for managing applications within App Mesh.
1366
1481
  """
1367
1482
 
1368
1483
  def __init__(
@@ -1505,7 +1620,7 @@ class AppMeshClientTCP(AppMeshClient):
1505
1620
  appmesh_requst.headers["Authorization"] = "Bearer " + super().jwt_token
1506
1621
  if super().forwarding_host and len(super().forwarding_host) > 0:
1507
1622
  raise Exception("Not support forward request in TCP mode")
1508
- appmesh_requst.headers[HTTP_USER_AGENT_HEADER_NAME] = HTTP_USER_AGENT_TCP
1623
+ appmesh_requst.headers[HTTP_HEADER_KEY_USER_AGENT] = HTTP_USER_AGENT_TCP
1509
1624
  appmesh_requst.uuid = str(uuid.uuid1())
1510
1625
  appmesh_requst.http_method = method.value
1511
1626
  appmesh_requst.request_uri = path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: appmesh
3
- Version: 1.3.2
3
+ Version: 1.3.3
4
4
  Summary: Client SDK for App Mesh
5
5
  Home-page: https://github.com/laoshanxi/app-mesh
6
6
  Author: laoshanxi
@@ -25,11 +25,9 @@ Requires-Dist: aniso8601
25
25
  </a>
26
26
  [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/laoshanxi/app-mesh/badge)](https://api.securityscorecards.dev/projects/github.com/laoshanxi/app-mesh)
27
27
 
28
- # App Mesh
28
+ # App Mesh: Advanced Application Management Platform
29
29
 
30
- App Mesh is a `Multi-Tenant`, `Cloud Native`, `Micro Service` application management platform designed to manage, schedule, and monitor applications. Each app can be a specific microservice for service discovery or a standard app with replication. App Mesh ensures all defined applications run on time with the specified behavior and resource requests. The platform supports both standalone and cluster modes and provides REST APIs, a command-line interface, and a web UI.
31
-
32
- App Mesh is similar to Kubernetes but is much more lightweight, supporting both containerized and native applications.
30
+ App Mesh is an open-source, multi-tenant application management platform designed for cloud-native environments. It efficiently manages, schedules, and monitors both microservices and traditional applications, offering a lightweight alternative to Kubernetes. App Mesh bridges the gap between simple process managers and complex container orchestration systems, making it ideal for organizations seeking to modernize their infrastructure without adopting full container-native complexity. Supporting both containerized and native applications, it provides a versatile solution for diverse enterprise needs.
33
31
 
34
32
  <div align=center><img src="https://github.com/laoshanxi/picture/raw/master/appmesh/diagram.png" align=center /></div>
35
33
 
@@ -87,7 +85,7 @@ Refer to the [Installation doc](https://app-mesh.readthedocs.io/en/latest/Instal
87
85
  | Non-container app | √ |
88
86
  | Service expose | √ | √ |
89
87
  | Scheduler | √ | √ |
90
- | Definition file | JSON | YAML |
88
+ | Definition file | YAML | YAML |
91
89
  | GUI | √ | √ |
92
90
  | Virtual Network | | √ |
93
91
  | Monitor tools | √ | √ |
@@ -112,6 +110,7 @@ Refer to the [Installation doc](https://app-mesh.readthedocs.io/en/latest/Instal
112
110
  - [Kubernetes run none-container applications](https://app-mesh.readthedocs.io/en/latest/success/kubernetes_run_native_application.html)
113
111
  - [Remote execute](https://app-mesh.readthedocs.io/en/latest/success/remote_run_cli_and_python.html)
114
112
  - [Python parallel run](https://app-mesh.readthedocs.io/en/latest/success/python_parallel_run.html)
113
+ - [Secure consul cluster](https://app-mesh.readthedocs.io/en/latest/success/secure_consul_cluster.html)
115
114
 
116
115
  ---
117
116
 
@@ -0,0 +1,6 @@
1
+ appmesh/__init__.py,sha256=xRdXeFHEieRauuJZElbEBASgXG0ZzU1a5_0isAhM7Gw,11
2
+ appmesh/appmesh_client.py,sha256=Hsp4at6YCLcAoz8eRx928amyCTqN4ZAIFnVHxEbzDrI,67720
3
+ appmesh-1.3.3.dist-info/METADATA,sha256=73_wYNYMLoHLoew35YGTd2bGKWhfScEObKhr07yyHx0,11191
4
+ appmesh-1.3.3.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
5
+ appmesh-1.3.3.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
6
+ appmesh-1.3.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,6 +0,0 @@
1
- appmesh/__init__.py,sha256=xRdXeFHEieRauuJZElbEBASgXG0ZzU1a5_0isAhM7Gw,11
2
- appmesh/appmesh_client.py,sha256=Ev0MMq7nu02pFbmTCLvPdxK3P-NmOeQQXiIYAibSYjQ,62923
3
- appmesh-1.3.2.dist-info/METADATA,sha256=pp8AVbBvK6naixdn039eaqy49JFa9dX6Qs7XS7mD7-0,11031
4
- appmesh-1.3.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
5
- appmesh-1.3.2.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
6
- appmesh-1.3.2.dist-info/RECORD,,