Skip to content

Commit 02a1a8c

Browse files
author
Andrei Neagu
committed
catalog exposes service labels
1 parent 324c053 commit 02a1a8c

File tree

5 files changed

+95
-24
lines changed

5 files changed

+95
-24
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import urllib.parse
2+
from typing import Annotated, Any, cast
3+
4+
from fastapi import APIRouter, Depends
5+
from models_library.generics import Envelope
6+
from models_library.services import ServiceKey, ServiceVersion
7+
8+
from ...services.director import DirectorApi
9+
from ..dependencies.director import get_director_api
10+
11+
router = APIRouter()
12+
13+
14+
@router.get("/{service_key:path}/{service_version}/labels")
15+
async def get_service_labels(
16+
service_key: ServiceKey,
17+
service_version: ServiceVersion,
18+
director_client: Annotated[DirectorApi, Depends(get_director_api)],
19+
) -> Envelope[dict[str, Any]]:
20+
response = await director_client.get(
21+
f"/services/{urllib.parse.quote_plus(service_key)}/{service_version}/labels"
22+
)
23+
return Envelope[dict[str, Any]](data=cast(dict[str, Any], response))

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
_meta,
88
_services,
99
_services_access_rights,
10+
_services_labels,
1011
_services_ports,
1112
_services_resources,
1213
_services_specifications,
@@ -38,6 +39,11 @@
3839
tags=_SERVICE_TAGS,
3940
prefix=_SERVICE_PREFIX,
4041
)
42+
v0_router.include_router(
43+
_services_labels.router,
44+
tags=_SERVICE_TAGS,
45+
prefix=_SERVICE_PREFIX,
46+
)
4147
v0_router.include_router(
4248
_services_specifications.router,
4349
tags=_SERVICE_TAGS,

services/catalog/tests/unit/conftest.py

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -393,11 +393,41 @@ def mocked_director_service_api_base(
393393
yield respx_mock
394394

395395

396+
@pytest.fixture
397+
def get_mocked_service_labels() -> Callable[[str, str], dict]:
398+
def _(service_key: str, service_version: str) -> dict:
399+
return {
400+
"io.simcore.authors": '{"authors": [{"name": "John Smith", "email": "[email protected]", "affiliation": "ACME\'IS Foundation"}]}',
401+
"io.simcore.contact": '{"contact": "[email protected]"}',
402+
"io.simcore.description": '{"description": "Autonomous Nervous System Network model"}',
403+
"io.simcore.inputs": '{"inputs": {"input_1": {"displayOrder": 1.0, "label": "Simulation time", "description": "Duration of the simulation", "type": "ref_contentSchema", "contentSchema": {"type": "number", "x_unit": "milli-second"}, "defaultValue": 2.0}}}',
404+
"io.simcore.integration-version": '{"integration-version": "1.0.0"}',
405+
"io.simcore.key": '{"key": "xxxxx"}'.replace("xxxxx", service_key),
406+
"io.simcore.name": '{"name": "Autonomous Nervous System Network model"}',
407+
"io.simcore.outputs": '{"outputs": {"output_1": {"displayOrder": 1.0, "label": "ANS output", "description": "Output of simulation of Autonomous Nervous System Network model", "type": "data:*/*", "fileToKeyMap": {"ANS_output.txt": "output_1"}}, "output_2": {"displayOrder": 2.0, "label": "Stimulation parameters", "description": "stim_param.txt file containing the input provided in the inputs port", "type": "data:*/*", "fileToKeyMap": {"ANS_stim_param.txt": "output_2"}}}}',
408+
"io.simcore.thumbnail": '{"thumbnail": "https://www.statnews.com/wp-content/uploads/2020/05/3D-rat-heart.-iScience--768x432.png"}',
409+
"io.simcore.type": '{"type": "computational"}',
410+
"io.simcore.version": '{"version": "xxxxx"}'.replace(
411+
"xxxxx", service_version
412+
),
413+
"maintainer": "johnsmith",
414+
"org.label-schema.build-date": "2023-04-17T08:04:15Z",
415+
"org.label-schema.schema-version": "1.0",
416+
"org.label-schema.vcs-ref": "",
417+
"org.label-schema.vcs-url": "",
418+
"simcore.service.restart-policy": "no-restart",
419+
"simcore.service.settings": '[{"name": "Resources", "type": "Resources", "value": {"Limits": {"NanoCPUs": 4000000000, "MemoryBytes": 2147483648}, "Reservations": {"NanoCPUs": 4000000000, "MemoryBytes": 2147483648}}}]',
420+
}
421+
422+
return _
423+
424+
396425
@pytest.fixture
397426
def mocked_director_service_api(
398427
mocked_director_service_api_base: respx.MockRouter,
399428
director_service_openapi_specs: dict[str, Any],
400429
expected_director_list_services: list[dict[str, Any]],
430+
get_mocked_service_labels: Callable[[str, str], dict],
401431
) -> respx.MockRouter:
402432
"""
403433
STANDARD fixture to mock director service API
@@ -461,30 +491,7 @@ def _get_service_labels(request, service_key, service_version):
461491
return httpx.Response(
462492
status_code=status.HTTP_200_OK,
463493
json={
464-
"data": {
465-
"io.simcore.authors": '{"authors": [{"name": "John Smith", "email": "[email protected]", "affiliation": "ACME\'IS Foundation"}]}',
466-
"io.simcore.contact": '{"contact": "[email protected]"}',
467-
"io.simcore.description": '{"description": "Autonomous Nervous System Network model"}',
468-
"io.simcore.inputs": '{"inputs": {"input_1": {"displayOrder": 1.0, "label": "Simulation time", "description": "Duration of the simulation", "type": "ref_contentSchema", "contentSchema": {"type": "number", "x_unit": "milli-second"}, "defaultValue": 2.0}}}',
469-
"io.simcore.integration-version": '{"integration-version": "1.0.0"}',
470-
"io.simcore.key": '{"key": "xxxxx"}'.replace(
471-
"xxxxx", found["key"]
472-
),
473-
"io.simcore.name": '{"name": "Autonomous Nervous System Network model"}',
474-
"io.simcore.outputs": '{"outputs": {"output_1": {"displayOrder": 1.0, "label": "ANS output", "description": "Output of simulation of Autonomous Nervous System Network model", "type": "data:*/*", "fileToKeyMap": {"ANS_output.txt": "output_1"}}, "output_2": {"displayOrder": 2.0, "label": "Stimulation parameters", "description": "stim_param.txt file containing the input provided in the inputs port", "type": "data:*/*", "fileToKeyMap": {"ANS_stim_param.txt": "output_2"}}}}',
475-
"io.simcore.thumbnail": '{"thumbnail": "https://www.statnews.com/wp-content/uploads/2020/05/3D-rat-heart.-iScience--768x432.png"}',
476-
"io.simcore.type": '{"type": "computational"}',
477-
"io.simcore.version": '{"version": "xxxxx"}'.replace(
478-
"xxxxx", found["version"]
479-
),
480-
"maintainer": "iavarone",
481-
"org.label-schema.build-date": "2023-04-17T08:04:15Z",
482-
"org.label-schema.schema-version": "1.0",
483-
"org.label-schema.vcs-ref": "",
484-
"org.label-schema.vcs-url": "",
485-
"simcore.service.restart-policy": "no-restart",
486-
"simcore.service.settings": '[{"name": "Resources", "type": "Resources", "value": {"Limits": {"NanoCPUs": 4000000000, "MemoryBytes": 2147483648}, "Reservations": {"NanoCPUs": 4000000000, "MemoryBytes": 2147483648}}}]',
487-
}
494+
"data": get_mocked_service_labels(found["key"], found["version"])
488495
},
489496
)
490497
return httpx.Response(
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# pylint: disable=redefined-outer-name
2+
# pylint: disable=unused-argument
3+
4+
from collections.abc import Callable
5+
from unittest.mock import AsyncMock
6+
7+
import pytest
8+
from fastapi import FastAPI
9+
from httpx import AsyncClient
10+
from respx import MockRouter
11+
12+
13+
@pytest.fixture
14+
def mock_engine(app: FastAPI) -> None:
15+
app.state.engine = AsyncMock()
16+
17+
18+
async def test_get_service_labels(
19+
postgres_setup_disabled: None,
20+
mocked_director_service_api: MockRouter,
21+
rabbitmq_and_rpc_setup_disabled: None,
22+
background_tasks_setup_disabled: None,
23+
mock_engine: None,
24+
get_mocked_service_labels: Callable[[str, str], dict],
25+
aclient: AsyncClient,
26+
):
27+
service_key = "simcore/services/comp/ans-model"
28+
service_version = "3.0.0"
29+
result = await aclient.get(f"/v0/services/{service_key}/{service_version}/labels")
30+
assert result.status_code == 200, result.text
31+
assert result.json() == {
32+
"data": get_mocked_service_labels(service_key, service_version),
33+
"error": None,
34+
}

services/director/src/simcore_service_director/api/rest/_services.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ async def list_service_labels(
7373
service_key: ServiceKey,
7474
service_version: ServiceVersion,
7575
) -> Envelope[dict[str, Any]]:
76+
# NOTE: avoid using this directly via `director` service, call it via `catalog` service
7677
_logger.debug(
7778
"Retrieving service labels with service_key %s, service_version %s",
7879
service_key,

0 commit comments

Comments
 (0)