Skip to content

Commit a0b8a2f

Browse files
GitHKAndrei Neagu
andauthored
All errors in dynamic-sidecar inherit from OsparcErrorMixin (#6764)
Co-authored-by: Andrei Neagu <[email protected]>
1 parent c49f421 commit a0b8a2f

File tree

6 files changed

+65
-44
lines changed

6 files changed

+65
-44
lines changed

services/dynamic-sidecar/src/simcore_service_dynamic_sidecar/core/docker_utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ async def get_volume_by_label(label: str, run_id: RunID) -> dict[str, Any]:
5050
volumes = data["Volumes"]
5151
_logger.debug("volumes query for label=%s volumes=%s", label, volumes)
5252
if len(volumes) != 1:
53-
raise VolumeNotFoundError(label, run_id, volumes)
53+
raise VolumeNotFoundError(
54+
volume_count=len(volumes),
55+
source_label=label,
56+
run_id=run_id,
57+
volume_names=" ".join(v.get("Name", "UNKNOWN") for v in volumes),
58+
status_code=http_status.HTTP_404_NOT_FOUND,
59+
)
5460
volume_details: dict[str, Any] = volumes[0]
5561
return volume_details
5662

services/dynamic-sidecar/src/simcore_service_dynamic_sidecar/core/error_handlers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ async def http_error_handler(
1212
) -> JSONResponse:
1313
return JSONResponse(
1414
content=jsonable_encoder({"errors": [exception.message]}),
15-
status_code=exception.status_code,
15+
status_code=exception.status_code, # type:ignore[attr-defined]
1616
)
1717

1818

services/dynamic-sidecar/src/simcore_service_dynamic_sidecar/core/errors.py

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,30 @@
1-
from typing import Any
2-
31
from common_library.errors_classes import OsparcErrorMixin
4-
from fastapi import status
5-
from models_library.services import RunID
62

73

8-
class BaseDynamicSidecarError(Exception):
4+
class BaseDynamicSidecarError(OsparcErrorMixin, Exception):
95
"""Used as base for all exceptions"""
106

11-
def __init__(
12-
self, nessage: str, status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR
13-
) -> None:
14-
self.message: str = nessage
15-
self.status_code: int = status_code
16-
super().__init__(nessage)
17-
187

198
class VolumeNotFoundError(BaseDynamicSidecarError):
20-
def __init__(
21-
self, source_label: str, run_id: RunID, volumes: list[dict[str, Any]]
22-
) -> None:
23-
super().__init__(
24-
f"Expected 1 got {len(volumes)} volumes labels with {source_label=}, {run_id=}: "
25-
f"Found {' '.join(v.get('Name', 'UNKNOWN') for v in volumes)}",
26-
status_code=status.HTTP_404_NOT_FOUND,
27-
)
9+
msg_template = (
10+
"Expected 1 got {volume_count} volumes labels with "
11+
"source_label={source_label}, run_id={run_id}: Found {volume_names}"
12+
)
2813

2914

3015
class UnexpectedDockerError(BaseDynamicSidecarError):
31-
def __init__(self, message: str, status_code: int) -> None:
32-
super().__init__(
33-
f"An unexpected Docker error occurred {status_code=}, {message=}",
34-
status_code=status_code,
35-
)
36-
37-
38-
class BaseError(OsparcErrorMixin, BaseDynamicSidecarError):
39-
...
16+
msg_template = "An unexpected Docker error occurred status_code={status_code}, message={message}"
4017

4118

42-
class ContainerExecContainerNotFoundError(BaseError):
19+
class ContainerExecContainerNotFoundError(BaseDynamicSidecarError):
4320
msg_template = "Container '{container_name}' was not found"
4421

4522

46-
class ContainerExecTimeoutError(BaseError):
23+
class ContainerExecTimeoutError(BaseDynamicSidecarError):
4724
msg_template = "Timed out after {timeout} while executing: '{command}'"
4825

4926

50-
class ContainerExecCommandFailedError(BaseError):
27+
class ContainerExecCommandFailedError(BaseDynamicSidecarError):
5128
msg_template = (
5229
"Command '{command}' exited with code '{exit_code}'"
5330
"and output: '{command_result}'"

services/dynamic-sidecar/src/simcore_service_dynamic_sidecar/core/settings.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import cast
66

77
from common_library.pydantic_validators import validate_numeric_string_as_timedelta
8-
from models_library.basic_types import BootModeEnum, PortInt
8+
from models_library.basic_types import PortInt
99
from models_library.callbacks_mapping import CallbacksMapping
1010
from models_library.products import ProductName
1111
from models_library.projects import ProjectID
@@ -21,8 +21,8 @@
2121
field_validator,
2222
)
2323
from servicelib.logging_utils_filtering import LoggerName, MessageSubstring
24+
from settings_library.application import BaseApplicationSettings
2425
from settings_library.aws_s3_cli import AwsS3CliSettings
25-
from settings_library.base import BaseCustomSettings
2626
from settings_library.docker_registry import RegistrySettings
2727
from settings_library.node_ports import StorageAuthSettings
2828
from settings_library.postgres import PostgresSettings
@@ -35,7 +35,7 @@
3535
from settings_library.utils_logging import MixinLoggingSettings
3636

3737

38-
class ResourceTrackingSettings(BaseCustomSettings):
38+
class ResourceTrackingSettings(BaseApplicationSettings):
3939
RESOURCE_TRACKING_HEARTBEAT_INTERVAL: timedelta = Field(
4040
default=DEFAULT_RESOURCE_USAGE_HEARTBEAT_INTERVAL,
4141
description="each time the status of the service is propagated",
@@ -46,17 +46,13 @@ class ResourceTrackingSettings(BaseCustomSettings):
4646
)
4747

4848

49-
class SystemMonitorSettings(BaseCustomSettings):
49+
class SystemMonitorSettings(BaseApplicationSettings):
5050
DY_SIDECAR_SYSTEM_MONITOR_TELEMETRY_ENABLE: bool = Field(
5151
default=False, description="enabled/disabled disk usage monitoring"
5252
)
5353

5454

55-
class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
56-
SC_BOOT_MODE: BootModeEnum = Field(
57-
...,
58-
description="boot mode helps determine if in development mode or normal operation",
59-
)
55+
class ApplicationSettings(BaseApplicationSettings, MixinLoggingSettings):
6056

6157
DYNAMIC_SIDECAR_DY_VOLUMES_MOUNT_DIR: Path = Field(
6258
...,

services/dynamic-sidecar/tests/unit/test_api_rest_containers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ async def test_container_docker_error(
480480
def _expected_error_string(status_code: int) -> dict[str, Any]:
481481
return {
482482
"errors": [
483-
f"An unexpected Docker error occurred status_code={status_code}, message='aiodocker_mocked_error'"
483+
f"An unexpected Docker error occurred status_code={status_code}, message=aiodocker_mocked_error"
484484
]
485485
}
486486

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# pylint:disable=broad-exception-caught
2+
# pylint:disable=no-member
3+
4+
from simcore_service_dynamic_sidecar.core.errors import (
5+
UnexpectedDockerError,
6+
VolumeNotFoundError,
7+
)
8+
from starlette import status
9+
10+
11+
def test_legacy_interface_unexpected_docker_error():
12+
message = "some_message"
13+
status_code = 42
14+
try:
15+
raise UnexpectedDockerError( # noqa: TRY301
16+
message=message, status_code=status_code
17+
)
18+
except Exception as e:
19+
print(e)
20+
assert e.status_code == status_code # noqa: PT017
21+
assert message in e.message # noqa: PT017
22+
23+
24+
def test_legacy_interface_volume_not_found_error():
25+
try:
26+
volumes = [{}, {"Name": "a_volume"}]
27+
volume_names = " ".join(v.get("Name", "UNKNOWN") for v in volumes)
28+
29+
raise VolumeNotFoundError( # noqa: TRY301
30+
volume_count=len(volumes),
31+
source_label="some",
32+
run_id="run_id",
33+
volume_names=volume_names,
34+
status_code=status.HTTP_404_NOT_FOUND,
35+
)
36+
except Exception as e:
37+
print(e)
38+
assert ( # noqa: PT017
39+
e.message
40+
== "Expected 1 got 2 volumes labels with source_label=some, run_id=run_id: Found UNKNOWN a_volume"
41+
)
42+
assert e.status_code == status.HTTP_404_NOT_FOUND # noqa: PT017

0 commit comments

Comments
 (0)