Skip to content

Commit 658c69d

Browse files
author
Andrei Neagu
committed
added director-v0 client to dynamic-scheduler
1 parent 9940bc6 commit 658c69d

File tree

13 files changed

+330
-26
lines changed

13 files changed

+330
-26
lines changed

packages/common-library/src/common_library/unset.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ class UnSet:
1010

1111
def as_dict_exclude_unset(**params) -> dict[str, Any]:
1212
return {k: v for k, v in params.items() if not isinstance(v, UnSet)}
13+
14+
15+
def as_dict_exclude_none(**params) -> dict[str, Any]:
16+
return {k: v for k, v in params.items() if v is not None}

packages/models-library/src/models_library/service_settings_labels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ class SimcoreServiceLabels(DynamicSidecarServiceLabels):
589589
settings: Annotated[
590590
Json[SimcoreServiceSettingsLabel],
591591
Field(
592-
default_factory=dict,
592+
default_factory=lambda: SimcoreServiceSettingsLabel.model_validate([]),
593593
alias="simcore.service.settings",
594594
description=(
595595
"Json encoded. Contains setting like environment variables and "

packages/service-library/src/servicelib/fastapi/http_client_thin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def __init__(
203203
base_url: URLTypes | None = None,
204204
default_http_client_timeout: TimeoutTypes | None = None,
205205
extra_allowed_method_names: set[str] | None = None,
206-
tracing_settings: TracingSettings | None,
206+
tracing_settings: TracingSettings | None = None,
207207
) -> None:
208208
_assert_public_interface(self, extra_allowed_method_names)
209209

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from functools import cached_property
2+
3+
from pydantic import AnyHttpUrl, Field, TypeAdapter
4+
from settings_library.base import BaseCustomSettings
5+
from settings_library.basic_types import PortInt, VersionTag
6+
7+
8+
class DirectorV0Settings(BaseCustomSettings):
9+
DIRECTOR_V0_ENABLED: bool = True
10+
11+
DIRECTOR_HOST: str = "director"
12+
DIRECTOR_PORT: PortInt = TypeAdapter(PortInt).validate_python(8000)
13+
DIRECTOR_V0_VTAG: VersionTag = Field(
14+
default="v0", description="Director-v0 service API's version tag"
15+
)
16+
17+
@cached_property
18+
def endpoint(self) -> str:
19+
url = AnyHttpUrl.build( # pylint: disable=no-member
20+
scheme="http",
21+
host=self.DIRECTOR_HOST,
22+
port=self.DIRECTOR_PORT,
23+
path=f"{self.DIRECTOR_V0_VTAG}",
24+
)
25+
return f"{url}"

services/director-v2/src/simcore_service_director_v2/core/settings.py

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from common_library.pydantic_validators import validate_numeric_string_as_timedelta
1010
from fastapi import FastAPI
11-
from models_library.basic_types import LogLevel, PortInt, VersionTag
11+
from models_library.basic_types import LogLevel, PortInt
1212
from models_library.clusters import (
1313
BaseCluster,
1414
ClusterAuthentication,
@@ -28,6 +28,7 @@
2828
from settings_library.application import BaseApplicationSettings
2929
from settings_library.base import BaseCustomSettings
3030
from settings_library.catalog import CatalogSettings
31+
from settings_library.director_v0 import DirectorV0Settings
3132
from settings_library.docker_registry import RegistrySettings
3233
from settings_library.http_client_request import ClientRequestSettings
3334
from settings_library.node_ports import (
@@ -49,26 +50,6 @@
4950
from .dynamic_services_settings import DynamicServicesSettings
5051

5152

52-
class DirectorV0Settings(BaseCustomSettings):
53-
DIRECTOR_V0_ENABLED: bool = True
54-
55-
DIRECTOR_HOST: str = "director"
56-
DIRECTOR_PORT: PortInt = PortInt(8080)
57-
DIRECTOR_V0_VTAG: VersionTag = Field(
58-
default="v0", description="Director-v0 service API's version tag"
59-
)
60-
61-
@cached_property
62-
def endpoint(self) -> str:
63-
url = AnyHttpUrl.build( # pylint: disable=no-member
64-
scheme="http",
65-
host=self.DIRECTOR_HOST,
66-
port=self.DIRECTOR_PORT,
67-
path=f"{self.DIRECTOR_V0_VTAG}",
68-
)
69-
return f"{url}"
70-
71-
7253
class ComputationalBackendSettings(BaseCustomSettings):
7354
COMPUTATIONAL_BACKEND_ENABLED: bool = Field(
7455
default=True,

services/director-v2/src/simcore_service_director_v2/modules/director_v0.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def get_service_extras(
9595
raise HTTPException(status_code=resp.status_code, detail=resp.content)
9696

9797
@log_decorator(logger=logger)
98-
async def get_running_service_details(
98+
async def get_running_service_details( # required
9999
self, service_uuid: NodeID
100100
) -> RunningDynamicServiceDetails:
101101
resp = await self._request(
@@ -108,7 +108,7 @@ async def get_running_service_details(
108108
raise HTTPException(status_code=resp.status_code, detail=resp.content)
109109

110110
@log_decorator(logger=logger)
111-
async def get_service_labels(
111+
async def get_service_labels( # required
112112
self, service: ServiceKeyVersion
113113
) -> SimcoreServiceLabels:
114114
resp = await self._request(
@@ -121,7 +121,7 @@ async def get_service_labels(
121121
raise HTTPException(status_code=resp.status_code, detail=resp.content)
122122

123123
@log_decorator(logger=logger)
124-
async def get_running_services(
124+
async def get_running_services( # required
125125
self, user_id: UserID | None = None, project_id: ProjectID | None = None
126126
) -> list[RunningDynamicServiceDetails]:
127127
query_params = {}

services/dynamic-scheduler/src/simcore_service_dynamic_scheduler/core/application.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from ..api.rest.routes import setup_rest_api
2020
from ..api.rpc.routes import setup_rpc_api_routes
2121
from ..services.deferred_manager import setup_deferred_manager
22+
from ..services.director_v0 import setup_director_v0
2223
from ..services.director_v2 import setup_director_v2
2324
from ..services.notifier import setup_notifier
2425
from ..services.rabbitmq import setup_rabbitmq
@@ -62,6 +63,7 @@ def create_app(settings: ApplicationSettings | None = None) -> FastAPI:
6263
# PLUGINS SETUP
6364

6465
setup_director_v2(app)
66+
setup_director_v0(app)
6567

6668
setup_rabbitmq(app)
6769
setup_rpc_api_routes(app)

services/dynamic-scheduler/src/simcore_service_dynamic_scheduler/core/settings.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
from servicelib.logging_utils_filtering import LoggerName, MessageSubstring
66
from settings_library.application import BaseApplicationSettings
77
from settings_library.basic_types import LogLevel, VersionTag
8+
from settings_library.director_v0 import DirectorV0Settings
89
from settings_library.director_v2 import DirectorV2Settings
10+
from settings_library.http_client_request import ClientRequestSettings
911
from settings_library.rabbit import RabbitSettings
1012
from settings_library.redis import RedisSettings
1113
from settings_library.tracing import TracingSettings
@@ -128,6 +130,15 @@ class ApplicationSettings(_BaseApplicationSettings):
128130
default=True, description="If true, it displays swagger doc at /doc"
129131
)
130132

133+
CLIENT_REQUEST: ClientRequestSettings = Field(
134+
json_schema_extra={"auto_default_from_env": True}
135+
)
136+
137+
DYNAMIC_SCHEDULER_DIRECTOR_V0_SETTINGS: DirectorV0Settings = Field(
138+
json_schema_extra={"auto_default_from_env": True},
139+
description="settings for director service",
140+
)
141+
131142
DYNAMIC_SCHEDULER_DIRECTOR_V2_SETTINGS: DirectorV2Settings = Field(
132143
json_schema_extra={"auto_default_from_env": True},
133144
description="settings for director-v2 service",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from ._public_client import DirectorV0PublicClient
2+
from ._setup import setup_director_v0
3+
4+
__all__: tuple[str, ...] = (
5+
"DirectorV0PublicClient",
6+
"setup_director_v0",
7+
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import logging
2+
from typing import Any, cast
3+
4+
import httpx
5+
from fastapi import FastAPI
6+
from models_library.api_schemas_directorv2.dynamic_services_service import (
7+
RunningDynamicServiceDetails,
8+
)
9+
from models_library.projects import ProjectID
10+
from models_library.projects_nodes_io import NodeID
11+
from models_library.service_settings_labels import SimcoreServiceLabels
12+
from models_library.services_base import ServiceKeyVersion
13+
from models_library.users import UserID
14+
from pydantic import TypeAdapter
15+
from servicelib.fastapi.app_state import SingletonInAppStateMixin
16+
17+
from ._thin_client import DirectorV0ThinClient
18+
19+
logger = logging.getLogger(__name__)
20+
21+
22+
def _unenvelope_or_raise_error(resp: httpx.Response) -> list[Any] | dict[str, Any]:
23+
"""
24+
Director responses are enveloped
25+
If successful response, we un-envelop it and return data as a dict
26+
If error, is detected raise an ValueError
27+
"""
28+
body = resp.json()
29+
if "data" in body:
30+
return body["data"]
31+
32+
msg = f"Unexpected, data was not returned: {body=}"
33+
raise ValueError(msg)
34+
35+
36+
class DirectorV0PublicClient(SingletonInAppStateMixin):
37+
app_state_name: str = "director_v0_public_client"
38+
39+
def __init__(self, app: FastAPI) -> None:
40+
self.app = app
41+
42+
async def get_running_service_details(
43+
self, node_id: NodeID
44+
) -> RunningDynamicServiceDetails:
45+
response = await DirectorV0ThinClient.get_from_app_state(
46+
self.app
47+
).get_running_interactive_service_details(node_id)
48+
return TypeAdapter(RunningDynamicServiceDetails).validate_python(
49+
_unenvelope_or_raise_error(response)
50+
)
51+
52+
async def get_service_labels( # required
53+
self, service: ServiceKeyVersion
54+
) -> SimcoreServiceLabels:
55+
response = await DirectorV0ThinClient.get_from_app_state(
56+
self.app
57+
).get_services_labels(service)
58+
return TypeAdapter(SimcoreServiceLabels).validate_python(
59+
_unenvelope_or_raise_error(response)
60+
)
61+
62+
async def get_running_services( # required
63+
self, user_id: UserID | None = None, project_id: ProjectID | None = None
64+
) -> list[RunningDynamicServiceDetails]:
65+
response = await DirectorV0ThinClient.get_from_app_state(
66+
self.app
67+
).get_running_interactive_services(user_id=user_id, project_id=project_id)
68+
return [
69+
RunningDynamicServiceDetails(**x)
70+
for x in cast(list[dict[str, Any]], _unenvelope_or_raise_error(response))
71+
]

0 commit comments

Comments
 (0)