appmesh 1.5.6__py3-none-any.whl → 1.5.8__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/__init__.py +3 -1
- appmesh/http_client.py +13 -54
- appmesh/http_server.py +118 -0
- appmesh/tcp_server.py +35 -0
- {appmesh-1.5.6.dist-info → appmesh-1.5.8.dist-info}/METADATA +1 -1
- {appmesh-1.5.6.dist-info → appmesh-1.5.8.dist-info}/RECORD +8 -6
- {appmesh-1.5.6.dist-info → appmesh-1.5.8.dist-info}/WHEEL +0 -0
- {appmesh-1.5.6.dist-info → appmesh-1.5.8.dist-info}/top_level.txt +0 -0
appmesh/__init__.py
CHANGED
@@ -14,5 +14,7 @@ Example:
|
|
14
14
|
from .app import App
|
15
15
|
from .http_client import AppMeshClient
|
16
16
|
from .tcp_client import AppMeshClientTCP
|
17
|
+
from .http_server import AppMeshServer
|
18
|
+
from .tcp_server import AppMeshServerTCP
|
17
19
|
|
18
|
-
__all__ = ["App", "AppMeshClient", "AppMeshClientTCP"]
|
20
|
+
__all__ = ["App", "AppMeshClient", "AppMeshClientTCP", "AppMeshServer", "AppMeshServerTCP"]
|
appmesh/http_client.py
CHANGED
@@ -34,10 +34,10 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
34
34
|
- Install the App Mesh Python package:
|
35
35
|
python3 -m pip install --upgrade appmesh
|
36
36
|
- Import the client module:
|
37
|
-
from appmesh import
|
37
|
+
from appmesh import AppMeshClient
|
38
38
|
|
39
39
|
Example:
|
40
|
-
client =
|
40
|
+
client = AppMeshClient()
|
41
41
|
client.login("your-name", "your-password")
|
42
42
|
response = client.app_view(app_name='ping')
|
43
43
|
|
@@ -152,7 +152,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
152
152
|
which may be necessary in environments requiring specific CA chains that differ from the default system CAs.
|
153
153
|
To use both a custom CA and the system's default CAs, create a combined CA bundle by concatenating them into a single file. (e.g., `cat custom_ca.pem /etc/ssl/certs/ca-certificates.crt > combined_ca.pem`).
|
154
154
|
|
155
|
-
|
155
|
+
rest_ssl_client_cert (Union[str, Tuple[str, str]], optional): Path to the SSL client certificate and key. Can be:
|
156
156
|
- `str`: A path to a single PEM file containing both the client certificate and private key.
|
157
157
|
- `tuple`: A pair of paths (`cert_file`, `key_file`), where `cert_file` is the client certificate file path and `key_file` is the private key file path.
|
158
158
|
|
@@ -1209,7 +1209,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
1209
1209
|
else:
|
1210
1210
|
raise TypeError(f"Invalid timeout type: {str(timeout)}")
|
1211
1211
|
|
1212
|
-
def run_task(self, app_name: str, data: str) -> str:
|
1212
|
+
def run_task(self, app_name: str, data: str, timeout: int = 300) -> str:
|
1213
1213
|
"""Client send an invocation message to a running App Mesh application and wait for result.
|
1214
1214
|
|
1215
1215
|
This method posts the provided `data` to the App Mesh service which will
|
@@ -1218,64 +1218,23 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
1218
1218
|
Args:
|
1219
1219
|
app_name (str): Name of the target application (as registered in App Mesh).
|
1220
1220
|
data (str): Payload to deliver to the application. Typically a string.
|
1221
|
+
timeout (int): Maximum time in seconds to wait for a response from the application. Defaults to 60 seconds.
|
1221
1222
|
|
1222
1223
|
Returns:
|
1223
1224
|
str: The HTTP response body returned by the remote application/service.
|
1224
1225
|
"""
|
1225
|
-
|
1226
|
-
if resp.status_code != HTTPStatus.OK:
|
1227
|
-
raise Exception(resp.text)
|
1228
|
-
|
1229
|
-
return resp.text
|
1230
|
-
|
1231
|
-
def task_fetch(self) -> str:
|
1232
|
-
"""Fetch invocation data in the currently running App Mesh application process.
|
1233
|
-
|
1234
|
-
This helper is intended to be called by an application process running from App Mesh
|
1235
|
-
to obtain the payload that a client pushed to it. It reads two required
|
1236
|
-
environment variables set by the runtime:
|
1237
|
-
|
1238
|
-
- APP_MESH_PROCESS_ID: the process UUID for this invocation
|
1239
|
-
- APP_MESH_APPLICATION_NAME: the application name
|
1240
|
-
|
1241
|
-
Returns:
|
1242
|
-
str: The payload provided by the client as returned by the service.
|
1243
|
-
"""
|
1244
|
-
process_uuid = os.environ["APP_MESH_PROCESS_ID"]
|
1245
|
-
app_name = os.environ["APP_MESH_APPLICATION_NAME"]
|
1246
|
-
while True:
|
1247
|
-
resp = self._request_http(
|
1248
|
-
AppMeshClient.Method.GET,
|
1249
|
-
path=f"/appmesh/app/{app_name}/task",
|
1250
|
-
query={"process_uuid": process_uuid},
|
1251
|
-
)
|
1252
|
-
if resp.status_code != HTTPStatus.OK:
|
1253
|
-
time.sleep(0.1)
|
1254
|
-
continue
|
1255
|
-
|
1256
|
-
return resp.text
|
1257
|
-
|
1258
|
-
def task_return(self, result: str) -> None:
|
1259
|
-
"""Return the result of a server-side invocation back to the original client.
|
1260
|
-
|
1261
|
-
The method posts the `result` associated with the current process UUID so
|
1262
|
-
the invoking client can retrieve it. The same environment variables used by
|
1263
|
-
`task_fetch` are required to identify the target process.
|
1264
|
-
|
1265
|
-
Args:
|
1266
|
-
result (str): Result payload to be delivered back to the client.
|
1267
|
-
"""
|
1268
|
-
process_uuid = os.environ["APP_MESH_PROCESS_ID"]
|
1269
|
-
app_name = os.environ["APP_MESH_APPLICATION_NAME"]
|
1226
|
+
path = f"/appmesh/app/{app_name}/task"
|
1270
1227
|
resp = self._request_http(
|
1271
|
-
AppMeshClient.Method.
|
1272
|
-
path=
|
1273
|
-
|
1274
|
-
|
1228
|
+
AppMeshClient.Method.POST,
|
1229
|
+
path=path,
|
1230
|
+
body=data,
|
1231
|
+
query={"timeout": str(timeout)},
|
1275
1232
|
)
|
1276
1233
|
if resp.status_code != HTTPStatus.OK:
|
1277
1234
|
raise Exception(resp.text)
|
1278
1235
|
|
1236
|
+
return resp.text
|
1237
|
+
|
1279
1238
|
def run_app_async(
|
1280
1239
|
self,
|
1281
1240
|
app: Union[App, str],
|
@@ -1369,7 +1328,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
|
|
1369
1328
|
Args:
|
1370
1329
|
app (Union[App, str]): An App instance or a shell command string.
|
1371
1330
|
If a string, an App instance is created as:
|
1372
|
-
`
|
1331
|
+
`appmesh.App({"command": "<command_string>", "shell": True})`
|
1373
1332
|
stdout_print (bool, optional): If True, prints the remote stdout locally. Defaults to True.
|
1374
1333
|
max_time_seconds (Union[int, str], optional): Maximum runtime for the remote process.
|
1375
1334
|
Supports ISO 8601 duration format (e.g., 'P1Y2M3DT4H5M6S', 'P5W'). Defaults to DEFAULT_RUN_APP_TIMEOUT_SECONDS.
|
appmesh/http_server.py
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# TCP-based App Mesh Server
|
2
|
+
# pylint: disable=line-too-long,broad-exception-raised,broad-exception-caught,import-outside-toplevel,protected-access
|
3
|
+
|
4
|
+
import abc
|
5
|
+
import logging
|
6
|
+
import os
|
7
|
+
import time
|
8
|
+
from typing import Optional, Tuple
|
9
|
+
from http import HTTPStatus
|
10
|
+
from .http_client import AppMeshClient
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
class AppMeshServer(metaclass=abc.ABCMeta):
|
16
|
+
"""
|
17
|
+
Server SDK for App Mesh application interacting with the local App Mesh REST service over HTTPS.
|
18
|
+
|
19
|
+
Build-in runtime environment variables required:
|
20
|
+
- APP_MESH_PROCESS_ID
|
21
|
+
- APP_MESH_APPLICATION_NAME
|
22
|
+
|
23
|
+
Methods:
|
24
|
+
- task_fetch(): fetch invocation payloads
|
25
|
+
- task_return(): return results to the invoking client
|
26
|
+
|
27
|
+
Example:
|
28
|
+
context = appmesh.AppMeshServer()
|
29
|
+
payload = context.task_fetch()
|
30
|
+
result = do_something_with(payload)
|
31
|
+
context.task_return(result)
|
32
|
+
"""
|
33
|
+
|
34
|
+
def __init__(
|
35
|
+
self,
|
36
|
+
rest_url: str = "https://127.0.0.1:6060",
|
37
|
+
rest_ssl_verify=AppMeshClient.DEFAULT_SSL_CA_CERT_PATH if os.path.exists(AppMeshClient.DEFAULT_SSL_CA_CERT_PATH) else False,
|
38
|
+
rest_ssl_client_cert=(
|
39
|
+
(
|
40
|
+
AppMeshClient.DEFAULT_SSL_CLIENT_CERT_PATH,
|
41
|
+
AppMeshClient.DEFAULT_SSL_CLIENT_KEY_PATH,
|
42
|
+
)
|
43
|
+
if os.path.exists(AppMeshClient.DEFAULT_SSL_CLIENT_CERT_PATH)
|
44
|
+
else None
|
45
|
+
),
|
46
|
+
rest_timeout: Tuple[float, float] = (60, 300),
|
47
|
+
*,
|
48
|
+
logger_: Optional[logging.Logger] = None,
|
49
|
+
):
|
50
|
+
"""Initialize an App Mesh HTTP client for interacting with the App Mesh server via secure HTTPS.
|
51
|
+
|
52
|
+
Args:
|
53
|
+
follows the same parameters as `AppMeshClient`.
|
54
|
+
"""
|
55
|
+
self._client = AppMeshClient(rest_url, rest_ssl_verify, rest_ssl_client_cert, rest_timeout)
|
56
|
+
self._logger = logger_ or logger
|
57
|
+
|
58
|
+
@staticmethod
|
59
|
+
def _get_runtime_env() -> Tuple[str, str]:
|
60
|
+
"""Read and validate required runtime environment variables."""
|
61
|
+
process_id = os.getenv("APP_MESH_PROCESS_ID")
|
62
|
+
app_name = os.getenv("APP_MESH_APPLICATION_NAME")
|
63
|
+
if not process_id:
|
64
|
+
raise Exception("Missing environment variable: APP_MESH_PROCESS_ID. This must be set by App Mesh service.")
|
65
|
+
if not app_name:
|
66
|
+
raise Exception("Missing environment variable: APP_MESH_APPLICATION_NAME. This must be set by App Mesh service.")
|
67
|
+
return process_id, app_name
|
68
|
+
|
69
|
+
def task_fetch(self) -> str:
|
70
|
+
"""Fetch task data in the currently running App Mesh application process.
|
71
|
+
|
72
|
+
Used by App Mesh application process to obtain the payload from App Mesh service
|
73
|
+
that a client pushed to it.
|
74
|
+
|
75
|
+
|
76
|
+
Returns:
|
77
|
+
str: The payload provided by the client as returned by the service.
|
78
|
+
"""
|
79
|
+
process_id, app_name = self._get_runtime_env()
|
80
|
+
path = f"/appmesh/app/{app_name}/task"
|
81
|
+
|
82
|
+
while True:
|
83
|
+
resp = self._client._request_http(
|
84
|
+
AppMeshClient.Method.GET,
|
85
|
+
path=path,
|
86
|
+
query={"process_uuid": process_id},
|
87
|
+
)
|
88
|
+
|
89
|
+
if resp.status_code != HTTPStatus.OK:
|
90
|
+
self._logger.warning(f"task_fetch failed with status {resp.status_code}: {resp.text}, retrying...")
|
91
|
+
time.sleep(0.1)
|
92
|
+
continue
|
93
|
+
|
94
|
+
return resp.text
|
95
|
+
|
96
|
+
def task_return(self, result: str) -> None:
|
97
|
+
"""Return the result of a server-side invocation back to the original client.
|
98
|
+
|
99
|
+
Used by App Mesh application process to posts the `result` to App Mesh service
|
100
|
+
after processed payload data so the invoking client can retrieve it.
|
101
|
+
|
102
|
+
Args:
|
103
|
+
result (str): Result payload to be delivered back to the client.
|
104
|
+
"""
|
105
|
+
process_id, app_name = self._get_runtime_env()
|
106
|
+
path = f"/appmesh/app/{app_name}/task"
|
107
|
+
|
108
|
+
resp = self._client._request_http(
|
109
|
+
AppMeshClient.Method.PUT,
|
110
|
+
path=path,
|
111
|
+
query={"process_uuid": process_id},
|
112
|
+
body=result,
|
113
|
+
)
|
114
|
+
|
115
|
+
if resp.status_code != HTTPStatus.OK:
|
116
|
+
msg = f"task_return failed with status {resp.status_code}: {resp.text}"
|
117
|
+
self._logger.error(msg)
|
118
|
+
raise Exception(msg)
|
appmesh/tcp_server.py
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# TCP-based App Mesh Server
|
2
|
+
# pylint: disable=line-too-long,broad-exception-raised,broad-exception-caught,import-outside-toplevel,protected-access
|
3
|
+
|
4
|
+
import os
|
5
|
+
import logging
|
6
|
+
from typing import Optional, Tuple
|
7
|
+
from .http_client import AppMeshClient
|
8
|
+
from .tcp_client import AppMeshClientTCP
|
9
|
+
from .http_server import AppMeshServer
|
10
|
+
|
11
|
+
logger = logging.getLogger(__name__)
|
12
|
+
|
13
|
+
|
14
|
+
class AppMeshServerTCP(AppMeshServer):
|
15
|
+
"""
|
16
|
+
Server SDK for interacting with the local App Mesh service over TCP (TLS).
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(
|
20
|
+
self,
|
21
|
+
rest_ssl_verify=AppMeshClient.DEFAULT_SSL_CA_CERT_PATH if os.path.exists(AppMeshClient.DEFAULT_SSL_CA_CERT_PATH) else False,
|
22
|
+
rest_ssl_client_cert=None,
|
23
|
+
tcp_address: Tuple[str, int] = ("localhost", 6059),
|
24
|
+
*,
|
25
|
+
logger_: Optional[logging.Logger] = None,
|
26
|
+
):
|
27
|
+
"""Construct an App Mesh server TCP object to communicate securely with an App Mesh server over TLS.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
follows the same parameters as `AppMeshClientTCP`.
|
31
|
+
"""
|
32
|
+
# Deliberately avoid calling super().__init__ to inject a TCP client while keeping the same public API.
|
33
|
+
object.__init__(self)
|
34
|
+
self._client = AppMeshClientTCP(rest_ssl_verify=rest_ssl_verify, rest_ssl_client_cert=rest_ssl_client_cert, tcp_address=tcp_address)
|
35
|
+
self._logger = logger_ or logger
|
@@ -1,13 +1,15 @@
|
|
1
|
-
appmesh/__init__.py,sha256=
|
1
|
+
appmesh/__init__.py,sha256=fQHuLWBaMZmbs5i5AV4KIXhv9YlIWkhYIv9WSLGNLm4,548
|
2
2
|
appmesh/app.py,sha256=9Q-SOOej-MH13BU5Dv2iTa-p-sECCJQp6ZX9DjWWmwE,10526
|
3
3
|
appmesh/app_output.py,sha256=JK_TMKgjvaw4n_ys_vmN5S4MyWVZpmD7NlKz_UyMIM8,1015
|
4
4
|
appmesh/app_run.py,sha256=9ISKGZ3k3kkbQvSsPfRfkOLqD9xhbqNOM7ork9F4w9c,1712
|
5
5
|
appmesh/appmesh_client.py,sha256=0ltkqHZUq094gKneYmC0bEZCP0X9kHTp9fccKdWFWP0,339
|
6
|
-
appmesh/http_client.py,sha256=
|
6
|
+
appmesh/http_client.py,sha256=j7OIHiRKeFs8o4zTT-tOcCwaYfeACzL86lmz1E2UP_M,57437
|
7
|
+
appmesh/http_server.py,sha256=HOE6DMzmo6FR16aSUQjSDLua_Q8o8807MNhPaAt-abs,4264
|
7
8
|
appmesh/tcp_client.py,sha256=yi0n2NpBBCA-JHYWQPPE_1euE7Oz6JHBe1op7lypTXY,10999
|
8
9
|
appmesh/tcp_messages.py,sha256=w1Kehz_aX4X2CYAUsy9mFVJRhxnLQwwc6L58W4YkQqs,969
|
10
|
+
appmesh/tcp_server.py,sha256=42YW3-hU82AwhE32DF4Gn6GucSg5qNJavP7xGSrpBVc,1353
|
9
11
|
appmesh/tcp_transport.py,sha256=-XDTQbsKL3yCbguHeW2jNqXpYgnCyHsH4rwcaJ46AS8,8645
|
10
|
-
appmesh-1.5.
|
11
|
-
appmesh-1.5.
|
12
|
-
appmesh-1.5.
|
13
|
-
appmesh-1.5.
|
12
|
+
appmesh-1.5.8.dist-info/METADATA,sha256=iSbvWio_TfOfwA-xXU4ZsSWENhl-FDoAUkJrSZRyaz4,11768
|
13
|
+
appmesh-1.5.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
14
|
+
appmesh-1.5.8.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
|
15
|
+
appmesh-1.5.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|