Skip to content

Commit 5c09b8f

Browse files
GitHKAndrei Neagu
andauthored
♻️🐛 docker engine cleans up volumes when removing dynamic-sidecars (ITISFoundation#2915)
* volume removal is handled by the docker engine * refactor and fix test * removed outdated * fixed test * fix tests * retriggering CI * fix test * removed unused * fix broken test * bringing back uuid * renaming * added better exception handling * moved to global space * fix imports * codestyle and fix missing imports * moved mounted_volumes to application from global * disabled rclone test for now * fix labels * fixed test Co-authored-by: Andrei Neagu <[email protected]>
1 parent 8093b42 commit 5c09b8f

29 files changed

+284
-151
lines changed

services/director-v2/src/simcore_service_director_v2/api/routes/dynamic_services.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
)
2727
from ...models.schemas.dynamic_services import SchedulerData
2828
from ...modules import projects_networks
29-
from ...modules.db.repositories.projects_networks import ProjectsNetworksRepository
3029
from ...modules.db.repositories.projects import ProjectsRepository
30+
from ...modules.db.repositories.projects_networks import ProjectsNetworksRepository
3131
from ...modules.dynamic_sidecar.docker_api import (
3232
is_dynamic_service_running,
3333
list_dynamic_sidecar_services,

services/director-v2/src/simcore_service_director_v2/models/schemas/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
r"(^([a-zA-Z0-9:.-]+)/)?(dynamic-sidecar):([a-zA-Z0-9.-]+$)"
1212
)
1313

14-
REGEX_DY_SERVICE_SIDECAR = fr"^{DYNAMIC_SIDECAR_SERVICE_PREFIX}_[a-zA-Z0-9-_]*"
15-
REGEX_DY_SERVICE_PROXY = fr"^{DYNAMIC_PROXY_SERVICE_PREFIX}_[a-zA-Z0-9-_]*"
14+
REGEX_DY_SERVICE_SIDECAR = rf"^{DYNAMIC_SIDECAR_SERVICE_PREFIX}_[a-zA-Z0-9-_]*"
15+
REGEX_DY_SERVICE_PROXY = rf"^{DYNAMIC_PROXY_SERVICE_PREFIX}_[a-zA-Z0-9-_]*"

services/director-v2/src/simcore_service_director_v2/modules/db/repositories/projects_networks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import sqlalchemy as sa
44
from aiopg.sa.result import RowProxy
5-
from models_library.projects_networks import NetworksWithAliases, ProjectsNetworks
65
from models_library.projects import ProjectID
6+
from models_library.projects_networks import NetworksWithAliases, ProjectsNetworks
77
from sqlalchemy.dialects.postgresql import insert as pg_insert
88

99
from ....core.errors import ProjectNotFoundError

services/director-v2/src/simcore_service_director_v2/modules/db/tables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from simcore_postgres_database.models.comp_pipeline import comp_pipeline
22
from simcore_postgres_database.models.comp_runs import comp_runs
33
from simcore_postgres_database.models.comp_tasks import NodeClass, StateType, comp_tasks
4-
from simcore_postgres_database.models.projects_networks import projects_networks
54
from simcore_postgres_database.models.projects import ProjectType, projects
5+
from simcore_postgres_database.models.projects_networks import projects_networks
66

77
__all__ = [
88
"StateType",

services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/client_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
import httpx
77
from fastapi import FastAPI
8-
from models_library.projects_networks import DockerNetworkAlias
98
from models_library.projects import ProjectID
9+
from models_library.projects_networks import DockerNetworkAlias
1010
from servicelib.utils import logged_gather
1111
from starlette import status
1212

services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/scheduler/events.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
import httpx
66
from fastapi import FastAPI
7-
from models_library.projects_networks import ProjectsNetworks
87
from models_library.projects import ProjectAtDB
8+
from models_library.projects_networks import ProjectsNetworks
99
from models_library.projects_nodes import Node
1010
from models_library.service_settings_labels import (
1111
SimcoreServiceLabels,
@@ -22,8 +22,8 @@
2222
from ....core.settings import AppSettings, DynamicSidecarSettings
2323
from ....models.schemas.dynamic_services import DynamicSidecarStatus, SchedulerData
2424
from ....modules.director_v0 import DirectorV0Client
25-
from ...db.repositories.projects_networks import ProjectsNetworksRepository
2625
from ...db.repositories.projects import ProjectsRepository
26+
from ...db.repositories.projects_networks import ProjectsNetworksRepository
2727
from .._namepsace import get_compose_namespace
2828
from ..client_api import DynamicSidecarClient, get_dynamic_sidecar_client
2929
from ..docker_api import (
@@ -586,7 +586,6 @@ async def action(cls, app: FastAPI, scheduler_data: SchedulerData) -> None:
586586
await app.state.dynamic_sidecar_scheduler.finish_service_removal(
587587
scheduler_data.node_uuid
588588
)
589-
590589
scheduler_data.dynamic_sidecar.service_removal_state.mark_removed()
591590

592591

services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/volumes_resolver.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,14 @@ def mount_entry(
9292
dynamic-sidecar) is running.
9393
"""
9494
return {
95-
"Source": cls.source(compose_namespace, path),
9695
"Target": cls.target(path),
9796
"Type": "volume",
98-
"VolumeOptions": {"Labels": {"uuid": f"{node_uuid}"}},
97+
"VolumeOptions": {
98+
"Labels": {
99+
"source": cls.source(compose_namespace, path),
100+
"uuid": f"{node_uuid}",
101+
}
102+
},
99103
}
100104

101105
@classmethod
@@ -108,11 +112,11 @@ def mount_r_clone(
108112
r_clone_settings: RCloneSettings,
109113
) -> Dict[str, Any]:
110114
return {
111-
"Source": cls.source(compose_namespace, path),
112115
"Target": cls.target(path),
113116
"Type": "volume",
114117
"VolumeOptions": {
115118
"Labels": {
119+
"source": cls.source(compose_namespace, path),
116120
"uuid": f"{node_uuid}",
117121
},
118122
"DriverConfig": _get_s3_volume_driver_config(

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import NamedTuple, Set
44
from uuid import UUID
55

6+
from models_library.projects import ProjectAtDB, ProjectID, Workbench
67
from models_library.projects_networks import (
78
PROJECT_NETWORK_PREFIX,
89
ContainerAliases,
@@ -11,7 +12,6 @@
1112
NetworksWithAliases,
1213
ProjectsNetworks,
1314
)
14-
from models_library.projects import ProjectAtDB, ProjectID, Workbench
1515
from models_library.projects_nodes_io import NodeIDStr
1616
from models_library.rabbitmq_messages import LoggerRabbitMessage
1717
from models_library.service_settings_labels import SimcoreServiceLabels
@@ -23,8 +23,8 @@
2323
from simcore_service_director_v2.modules.rabbitmq import RabbitMQClient
2424

2525
from ..api.dependencies.director_v0 import DirectorV0Client
26-
from ..modules.db.repositories.projects_networks import ProjectsNetworksRepository
2726
from ..modules.db.repositories.projects import ProjectsRepository
27+
from ..modules.db.repositories.projects_networks import ProjectsNetworksRepository
2828
from ..modules.dynamic_sidecar.scheduler import DynamicSidecarsScheduler
2929

3030
logger = logging.getLogger(__name__)

services/director-v2/tests/integration/02/test_dynamic_sidecar_nodeports_integration.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,16 @@ def _is_docker_r_clone_plugin_installed() -> bool:
281281
return is_plugin_installed
282282

283283

284-
@pytest.fixture(scope="session", params={"true", "false"})
284+
@pytest.fixture(
285+
scope="session",
286+
params={
287+
# NOTE: There is an issue with the docker rclone volume plugin:
288+
# SEE https://github.com/rclone/rclone/issues/6059
289+
# Disabling rclone test until this is fixed.
290+
# "true",
291+
"false",
292+
},
293+
)
285294
def dev_features_enabled(request) -> str:
286295
if request.param == "true" and not _is_docker_r_clone_plugin_installed():
287296
pytest.skip("Required docker plugin `rclone` not installed.")

services/director-v2/tests/unit/test_modules_dynamic_sidecar_volumes_resolver.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
from pathlib import Path
55
from typing import Any, Callable, Dict, List
6-
from uuid import uuid4
6+
from uuid import UUID
77

88
import pytest
99
from faker import Faker
@@ -16,29 +16,28 @@
1616

1717

1818
# FIXTURES
19-
@pytest.fixture(scope="module")
20-
def compose_namespace() -> str:
21-
return f"{DYNAMIC_SIDECAR_SERVICE_PREFIX}_{uuid4()}"
19+
@pytest.fixture
20+
def compose_namespace(faker: Faker) -> str:
21+
return f"{DYNAMIC_SIDECAR_SERVICE_PREFIX}_{faker.uuid4()}"
2222

2323

24-
@pytest.fixture(scope="module")
25-
def node_uuid() -> str:
26-
return f"{uuid4()}"
24+
@pytest.fixture
25+
def node_uuid(faker: Faker) -> UUID:
26+
return faker.uuid4(cast_to=None)
2727

2828

29-
@pytest.fixture(scope="module")
29+
@pytest.fixture
3030
def state_paths() -> List[Path]:
3131
return [Path(f"/tmp/asd/asd/{x}") for x in range(10)]
3232

3333

3434
@pytest.fixture
35-
def expect(node_uuid: str) -> Callable[[str, str], Dict[str, Any]]:
35+
def expected_volume_config(node_uuid: UUID) -> Callable[[str, str], Dict[str, Any]]:
3636
def _callable(source: str, target: str) -> Dict[str, Any]:
3737
return {
38-
"Source": source,
3938
"Target": target,
4039
"Type": "volume",
41-
"VolumeOptions": {"Labels": {"uuid": node_uuid}},
40+
"VolumeOptions": {"Labels": {"source": source, "uuid": f"{node_uuid}"}},
4241
}
4342

4443
return _callable
@@ -49,24 +48,24 @@ def _callable(source: str, target: str) -> Dict[str, Any]:
4948

5049
def test_expected_paths(
5150
compose_namespace: str,
52-
node_uuid: str,
51+
node_uuid: UUID,
5352
state_paths: List[Path],
54-
expect: Callable[[str, str], Dict[str, Any]],
53+
expected_volume_config: Callable[[str, str], Dict[str, Any]],
5554
) -> None:
5655
fake = Faker()
5756

5857
inputs_path = Path(fake.file_path(depth=3)).parent
5958
assert DynamicSidecarVolumesPathsResolver.mount_entry(
6059
compose_namespace, inputs_path, node_uuid
61-
) == expect(
60+
) == expected_volume_config(
6261
source=f"{compose_namespace}{f'{inputs_path}'.replace('/', '_')}",
6362
target=str(Path("/dy-volumes") / inputs_path.relative_to("/")),
6463
)
6564

6665
outputs_path = Path(fake.file_path(depth=3)).parent
6766
assert DynamicSidecarVolumesPathsResolver.mount_entry(
6867
compose_namespace, outputs_path, node_uuid
69-
) == expect(
68+
) == expected_volume_config(
7069
source=f"{compose_namespace}{f'{outputs_path}'.replace('/', '_')}",
7170
target=str(Path("/dy-volumes") / outputs_path.relative_to("/")),
7271
)
@@ -75,7 +74,7 @@ def test_expected_paths(
7574
name_from_path = f"{path}".replace(os.sep, "_")
7675
assert DynamicSidecarVolumesPathsResolver.mount_entry(
7776
compose_namespace, path, node_uuid
78-
) == expect(
77+
) == expected_volume_config(
7978
source=f"{compose_namespace}{name_from_path}",
8079
target=str(Path("/dy-volumes/") / path.relative_to("/")),
8180
)

0 commit comments

Comments
 (0)