Skip to content

Commit ac9b47c

Browse files
committed
✨ Refactor director service API references to improve clarity and consistency
1 parent 3b14b42 commit ac9b47c

19 files changed

+102
-80
lines changed

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Final
22

33
from pydantic import BaseModel, ConfigDict, Field, field_validator
4+
from pydantic.config import JsonDict
45
from pydantic.types import ByteSize, NonNegativeInt
56

67
from ..service_settings_labels import ContainerSpec
@@ -63,13 +64,14 @@ class ServiceExtras(BaseModel):
6364
service_build_details: ServiceBuildDetails | None = None
6465
container_spec: ContainerSpec | None = None
6566

66-
model_config = ConfigDict(
67-
json_schema_extra={
68-
"examples": [
67+
@staticmethod
68+
def _update_json_schema_extra(schema: JsonDict) -> None:
69+
examples = [
70+
*(
6971
{"node_requirements": node_example}
7072
for node_example in NodeRequirements.model_json_schema()["examples"]
71-
]
72-
+ [
73+
),
74+
*(
7375
{
7476
"node_requirements": node_example,
7577
"service_build_details": {
@@ -79,8 +81,8 @@ class ServiceExtras(BaseModel):
7981
},
8082
}
8183
for node_example in NodeRequirements.model_json_schema()["examples"]
82-
]
83-
+ [
84+
),
85+
*(
8486
{
8587
"node_requirements": node_example,
8688
"service_build_details": {
@@ -91,9 +93,11 @@ class ServiceExtras(BaseModel):
9193
"container_spec": {"Command": ["run", "subcommand"]},
9294
}
9395
for node_example in NodeRequirements.model_json_schema()["examples"]
94-
]
95-
}
96-
)
96+
),
97+
]
98+
schema.update({"examples": examples})
99+
100+
model_config = ConfigDict(json_schema_extra=_update_json_schema_extra)
97101

98102

99103
CHARS_IN_VOLUME_NAME_BEFORE_DIR_NAME: Final[NonNegativeInt] = 89

services/catalog/src/simcore_service_catalog/api/rest/_services_extras.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from models_library.services import ServiceKey, ServiceVersion
66

77
from ...clients.director import DirectorApi
8+
from ...service import services
89
from .._dependencies.director import get_director_api
910

1011
router = APIRouter()
@@ -16,4 +17,7 @@ async def get_service_extras(
1617
service_version: ServiceVersion,
1718
director_client: Annotated[DirectorApi, Depends(get_director_api)],
1819
) -> ServiceExtras:
19-
return await director_client.get_service_extras(service_key, service_version)
20+
21+
return await services.get_service_extras(
22+
director_client, service_key, service_version
23+
)

services/catalog/src/simcore_service_catalog/clients/director.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ async def get_service_extras(
206206
service_key: ServiceKey,
207207
service_version: ServiceVersion,
208208
) -> ServiceExtras:
209+
# NOTE: SEE https://github.com/ITISFoundation/osparc-simcore/issues/7509
210+
209211
# check physical node requirements
210212
# all nodes require "CPU"
211213
result: dict[str, Any] = {

services/catalog/src/simcore_service_catalog/service/services.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
ServiceGetV2,
88
ServiceUpdateV2,
99
)
10+
from models_library.api_schemas_directorv2.services import ServiceExtras
11+
from models_library.basic_types import VersionStr
1012
from models_library.groups import GroupID
1113
from models_library.products import ProductName
1214
from models_library.rest_pagination import PageLimitInt, PageTotalCount
@@ -510,3 +512,11 @@ async def list_my_service_release_history(
510512
]
511513

512514
return total_count, items
515+
516+
517+
async def get_service_extras(
518+
director_api: DirectorApi, service_key: ServiceKey, service_version: VersionStr
519+
) -> ServiceExtras:
520+
return await director_api.get_service_extras(
521+
service_key=service_key, service_version=service_version
522+
)

services/catalog/tests/unit/conftest.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,14 @@ async def rpc_client(
280280

281281

282282
@pytest.fixture
283-
def director_setup_disabled(mocker: MockerFixture) -> None:
283+
def director_lifespan_disabled(mocker: MockerFixture) -> None:
284284
mocker.patch.object(
285285
simcore_service_catalog.core.events, "director_lifespan", autospec=True
286286
)
287287

288288

289289
@pytest.fixture
290-
def director_service_openapi_specs(
290+
def director_rest_openapi_specs(
291291
osparc_simcore_services_dir: Path,
292292
) -> dict[str, Any]:
293293
openapi_path = (
@@ -303,7 +303,7 @@ def director_service_openapi_specs(
303303

304304

305305
@pytest.fixture
306-
def expected_director_list_services(
306+
def expected_director_rest_api_list_services(
307307
user_email: EmailStr, user_first_name: str, user_last_name: str
308308
) -> list[dict[str, Any]]:
309309
"""This fixture has at least TWO purposes:
@@ -367,9 +367,9 @@ def expected_director_list_services(
367367

368368

369369
@pytest.fixture
370-
def mocked_director_service_api_base(
370+
def mocked_director_rest_api_base(
371371
app_settings: ApplicationSettings,
372-
director_service_openapi_specs: dict[str, Any],
372+
director_rest_openapi_specs: dict[str, Any],
373373
) -> Iterator[respx.MockRouter]:
374374
"""
375375
BASIC fixture to mock director service API
@@ -382,7 +382,7 @@ def mocked_director_service_api_base(
382382
), "Check dependency on fixture `director_setup_disabled`"
383383

384384
# NOTE: this MUST be in sync with services/director/src/simcore_service_director/api/v0/openapi.yaml
385-
openapi = director_service_openapi_specs
385+
openapi = director_rest_openapi_specs
386386
assert Version(openapi["info"]["version"]) == Version("0.1.0")
387387

388388
with respx.mock(
@@ -445,10 +445,10 @@ def mock_service_extras() -> ServiceExtras:
445445

446446

447447
@pytest.fixture
448-
def mocked_director_service_api(
449-
mocked_director_service_api_base: respx.MockRouter,
450-
director_service_openapi_specs: dict[str, Any],
451-
expected_director_list_services: list[dict[str, Any]],
448+
def mocked_director_rest_api(
449+
mocked_director_rest_api_base: respx.MockRouter,
450+
director_rest_openapi_specs: dict[str, Any],
451+
expected_director_rest_api_list_services: list[dict[str, Any]],
452452
get_mocked_service_labels: Callable[[str, str], dict],
453453
mock_service_extras: ServiceExtras,
454454
) -> respx.MockRouter:
@@ -458,14 +458,14 @@ def mocked_director_service_api(
458458
To customize the mock responses use `mocked_director_service_api_base` instead
459459
"""
460460
# alias
461-
openapi = director_service_openapi_specs
462-
respx_mock = mocked_director_service_api_base
461+
openapi = director_rest_openapi_specs
462+
respx_mock = mocked_director_rest_api_base
463463

464464
def _search(service_key, service_version):
465465
try:
466466
return next(
467467
s
468-
for s in expected_director_list_services
468+
for s in expected_director_rest_api_list_services
469469
if (s["key"] == service_key and s["version"] == service_version)
470470
)
471471
except StopIteration:
@@ -475,7 +475,7 @@ def _search(service_key, service_version):
475475
assert openapi["paths"].get("/services")
476476

477477
respx_mock.get(path__regex=r"/services$", name="list_services").respond(
478-
status.HTTP_200_OK, json={"data": expected_director_list_services}
478+
status.HTTP_200_OK, json={"data": expected_director_rest_api_list_services}
479479
)
480480

481481
# GET

services/catalog/tests/unit/test_api_rest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def test_sync_client(
1212
repository_lifespan_disabled: None,
1313
rabbitmq_and_rpc_setup_disabled: None,
1414
background_task_lifespan_disabled: None,
15-
director_setup_disabled: None,
15+
director_lifespan_disabled: None,
1616
client: TestClient,
1717
):
1818

@@ -27,7 +27,7 @@ async def test_async_client(
2727
repository_lifespan_disabled: None,
2828
rabbitmq_and_rpc_setup_disabled: None,
2929
background_task_lifespan_disabled: None,
30-
director_setup_disabled: None,
30+
director_lifespan_disabled: None,
3131
aclient: httpx.AsyncClient,
3232
):
3333
response = await aclient.get("/v0/")

services/catalog/tests/unit/test_clients_director.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ async def test_director_client_high_level_api(
3636
repository_lifespan_disabled: None,
3737
background_task_lifespan_disabled: None,
3838
rabbitmq_and_rpc_setup_disabled: None,
39-
expected_director_list_services: list[dict[str, Any]],
40-
mocked_director_service_api: MockRouter,
39+
expected_director_rest_api_list_services: list[dict[str, Any]],
40+
mocked_director_rest_api: MockRouter,
4141
app: FastAPI,
4242
):
4343
# gets director client as used in handlers
@@ -50,7 +50,9 @@ async def test_director_client_high_level_api(
5050
assert await director_api.is_responsive()
5151

5252
# GET
53-
expected_service = ServiceMetaDataPublished(**expected_director_list_services[0])
53+
expected_service = ServiceMetaDataPublished(
54+
**expected_director_rest_api_list_services[0]
55+
)
5456
assert (
5557
await director_api.get_service(expected_service.key, expected_service.version)
5658
== expected_service
@@ -62,13 +64,13 @@ async def test_director_client_low_level_api(
6264
repository_lifespan_disabled: None,
6365
background_task_lifespan_disabled: None,
6466
rabbitmq_and_rpc_setup_disabled: None,
65-
mocked_director_service_api: MockRouter,
66-
expected_director_list_services: list[dict[str, Any]],
67+
mocked_director_rest_api: MockRouter,
68+
expected_director_rest_api_list_services: list[dict[str, Any]],
6769
app: FastAPI,
6870
):
6971
director_api = get_director_api(app)
7072

71-
expected_service = expected_director_list_services[0]
73+
expected_service = expected_director_rest_api_list_services[0]
7274
key = expected_service["key"]
7375
version = expected_service["version"]
7476

services/catalog/tests/unit/test_service_manifest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def app_environment(
3434
async def test_services_manifest_api(
3535
repository_lifespan_disabled: None,
3636
rabbitmq_and_rpc_setup_disabled: None,
37-
mocked_director_service_api: MockRouter,
37+
mocked_director_rest_api: MockRouter,
3838
app: FastAPI,
3939
):
4040
director_api = get_director_api(app)
@@ -44,7 +44,7 @@ async def test_services_manifest_api(
4444

4545
# LIST
4646
all_services_map = await manifest.get_services_map(director_api)
47-
assert mocked_director_service_api["list_services"].called
47+
assert mocked_director_rest_api["list_services"].called
4848

4949
for service in all_services_map.values():
5050
if is_function_service(service.key):
@@ -67,7 +67,7 @@ async def test_services_manifest_api(
6767

6868
assert service == expected_service
6969
if not is_function_service(service.key):
70-
assert mocked_director_service_api["get_service"].called
70+
assert mocked_director_rest_api["get_service"].called
7171

7272
# BATCH
7373
for expected_services in toolz.partition(2, all_services_map.values()):

services/catalog/tests/unit/test_utils_service_extras.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def mock_engine(app: FastAPI) -> None:
1818

1919
async def test_get_service_extras(
2020
repository_lifespan_disabled: None,
21-
mocked_director_service_api: MockRouter,
21+
mocked_director_rest_api: MockRouter,
2222
rabbitmq_and_rpc_setup_disabled: None,
2323
background_task_lifespan_disabled: None,
2424
mock_engine: None,

services/catalog/tests/unit/test_utils_service_labels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def mock_engine(app: FastAPI) -> None:
1717

1818
async def test_get_service_labels(
1919
repository_lifespan_disabled: None,
20-
mocked_director_service_api: MockRouter,
20+
mocked_director_rest_api: MockRouter,
2121
rabbitmq_and_rpc_setup_disabled: None,
2222
background_task_lifespan_disabled: None,
2323
mock_engine: None,

0 commit comments

Comments
 (0)