Skip to content

Commit 666dd44

Browse files
✨👽️ Add log zip endpoints in api-server (ITISFoundation#8056)
1 parent 9b06506 commit 666dd44

File tree

29 files changed

+1246
-121
lines changed

29 files changed

+1246
-121
lines changed

packages/models-library/src/models_library/api_schemas_directorv2/computations.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from ..basic_types import IDStr
1515
from ..projects import ProjectID
16-
from ..projects_nodes_io import NodeID
16+
from ..projects_nodes_io import NodeID, SimcoreS3FileID
1717
from ..projects_pipeline import ComputationTask
1818
from ..users import UserID
1919
from ..wallets import WalletInfo
@@ -126,6 +126,30 @@ class TaskLogFileGet(BaseModel):
126126
] = None
127127

128128

129+
class TaskLogFileIdGet(BaseModel):
130+
task_id: NodeID
131+
file_id: SimcoreS3FileID | None
132+
133+
model_config = ConfigDict(
134+
json_schema_extra={
135+
"examples": [
136+
{
137+
"task_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
138+
"file_id": "1c46752c-b096-11ea-a3c4-02420a00392e/3fa85f64-5717-4562-b3fc-2c963f66afa6/logs/task_logs.txt",
139+
},
140+
{
141+
"task_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
142+
"file_id": "1c46752c-b096-11ea-a3c4-02420a00392e/6ba7b810-9dad-11d1-80b4-00c04fd430c8/logs/debug.log",
143+
},
144+
{
145+
"task_id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
146+
"file_id": None,
147+
},
148+
]
149+
}
150+
)
151+
152+
129153
class TasksSelection(BaseModel):
130154
nodes_ids: list[NodeID]
131155

packages/models-library/src/models_library/api_schemas_rpc_async_jobs/async_jobs.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ class AsyncJobResult(BaseModel):
3030

3131

3232
class AsyncJobGet(BaseModel):
33+
model_config = ConfigDict(
34+
json_schema_extra={
35+
"examples": [
36+
{
37+
"job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
38+
"job_name": "export_data_task",
39+
}
40+
]
41+
}
42+
)
43+
3344
job_id: AsyncJobId
3445
job_name: AsyncJobName
3546

@@ -42,6 +53,18 @@ class AsyncJobAbort(BaseModel):
4253
class AsyncJobFilter(AsyncJobFilterBase):
4354
"""Data for controlling access to an async job"""
4455

56+
model_config = ConfigDict(
57+
json_schema_extra={
58+
"examples": [
59+
{
60+
"product_name": "osparc",
61+
"user_id": 123,
62+
"client_name": "web_client",
63+
}
64+
]
65+
},
66+
)
67+
4568
product_name: ProductName
4669
user_id: UserID
4770
client_name: Annotated[
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# pylint: disable=no-self-use
2+
# pylint: disable=not-context-manager
3+
# pylint: disable=protected-access
4+
# pylint: disable=redefined-outer-name
5+
# pylint: disable=unused-argument
6+
# pylint: disable=unused-variable
7+
8+
9+
from models_library.api_schemas_directorv2.computations import TaskLogFileIdGet
10+
from models_library.projects import ProjectID
11+
from pydantic import TypeAdapter, validate_call
12+
from pytest_mock import MockType
13+
from servicelib.rabbitmq._client_rpc import RabbitMQRPCClient
14+
15+
16+
class DirectorV2SideEffects:
17+
# pylint: disable=no-self-use
18+
@validate_call(config={"arbitrary_types_allowed": True})
19+
async def get_computation_task_log_file_ids(
20+
self,
21+
rpc_client: RabbitMQRPCClient | MockType,
22+
*,
23+
project_id: ProjectID,
24+
) -> list[TaskLogFileIdGet]:
25+
assert rpc_client
26+
assert project_id
27+
28+
return TypeAdapter(list[TaskLogFileIdGet]).validate_python(
29+
TaskLogFileIdGet.model_json_schema()["examples"],
30+
)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# pylint: disable=no-self-use
2+
# pylint: disable=not-context-manager
3+
# pylint: disable=protected-access
4+
# pylint: disable=redefined-outer-name
5+
# pylint: disable=unused-argument
6+
# pylint: disable=unused-variable
7+
8+
9+
from typing import Literal
10+
11+
from models_library.api_schemas_rpc_async_jobs.async_jobs import (
12+
AsyncJobFilter,
13+
AsyncJobGet,
14+
)
15+
from models_library.api_schemas_webserver.storage import PathToExport
16+
from models_library.products import ProductName
17+
from models_library.users import UserID
18+
from pydantic import TypeAdapter, validate_call
19+
from pytest_mock import MockType
20+
from servicelib.rabbitmq._client_rpc import RabbitMQRPCClient
21+
22+
23+
class StorageSideEffects:
24+
# pylint: disable=no-self-use
25+
@validate_call(config={"arbitrary_types_allowed": True})
26+
async def start_export_data(
27+
self,
28+
rabbitmq_rpc_client: RabbitMQRPCClient | MockType,
29+
*,
30+
user_id: UserID,
31+
product_name: ProductName,
32+
paths_to_export: list[PathToExport],
33+
export_as: Literal["path", "download_link"],
34+
) -> tuple[AsyncJobGet, AsyncJobFilter]:
35+
assert rabbitmq_rpc_client
36+
assert user_id
37+
assert product_name
38+
assert paths_to_export
39+
assert export_as
40+
41+
async_job_get = TypeAdapter(AsyncJobGet).validate_python(
42+
AsyncJobGet.model_json_schema()["examples"][0],
43+
)
44+
async_job_filter = TypeAdapter(AsyncJobFilter).validate_python(
45+
AsyncJobFilter.model_json_schema()["examples"][0],
46+
)
47+
48+
return async_job_get, async_job_filter
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# pylint: disable=too-many-arguments
2+
import logging
3+
from typing import Final
4+
5+
from models_library.api_schemas_directorv2 import (
6+
DIRECTOR_V2_RPC_NAMESPACE,
7+
)
8+
from models_library.api_schemas_directorv2.computations import TaskLogFileIdGet
9+
from models_library.projects import ProjectID
10+
from models_library.rabbitmq_basic_types import RPCMethodName
11+
from pydantic import TypeAdapter
12+
13+
from ....logging_utils import log_decorator
14+
from ... import RabbitMQRPCClient
15+
16+
_logger = logging.getLogger(__name__)
17+
18+
19+
_RPC_METHOD_NAME_ADAPTER: TypeAdapter[RPCMethodName] = TypeAdapter(RPCMethodName)
20+
21+
_GET_COMPUTATION_TASK_LOG_FILE_IDS: Final[RPCMethodName] = (
22+
_RPC_METHOD_NAME_ADAPTER.validate_python("get_computation_task_log_file_ids")
23+
)
24+
25+
26+
@log_decorator(_logger, level=logging.DEBUG)
27+
async def get_computation_task_log_file_ids(
28+
rabbitmq_rpc_client: RabbitMQRPCClient, *, project_id: ProjectID
29+
) -> list[TaskLogFileIdGet]:
30+
"""
31+
Raises:
32+
ComputationalTaskMissingError
33+
"""
34+
result = await rabbitmq_rpc_client.request(
35+
DIRECTOR_V2_RPC_NAMESPACE,
36+
_GET_COMPUTATION_TASK_LOG_FILE_IDS,
37+
project_id=project_id,
38+
)
39+
assert isinstance(result, list) # nosec
40+
assert all(isinstance(item, TaskLogFileIdGet) for item in result) # nosec
41+
return result
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from ..._errors import RPCInterfaceError
2+
3+
4+
class BaseRpcError(RPCInterfaceError):
5+
pass
6+
7+
8+
class ComputationalTaskMissingError(BaseRpcError):
9+
msg_template = "Computational run not found for project {project_id}"

services/api-server/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.9.2
1+
0.10.0

0 commit comments

Comments
 (0)