Skip to content

Commit 042a392

Browse files
GitHKAndrei Neagu
andauthored
✨ dynamic-sidecar restart policy (⚠️ devops) (#2654)
* added restart policy * added endpoint to restart containers * refacto rabbitmq and add ui iframe reload command * changed defaults rabbit_channels * fixed .env-devel * adding rabbitmq parsing * cleanup * adding restart containers policy integration * added restart endpoint * user is warned he needs to reload the UI * js codestyle * fixed pylint * fixed import order * fix pylint * upgraded version * reformat * added test case * refactor description * fixed description * removed uncecessary * using shared client * refactor using restart command * renaming * using namedtuple * added test to check containers get restarted * codestyle * codestyle * refactor to use project_uuid * typing enhancements * typo * removed unused parameter * fix routes * remove files from disk when disconnecting port * pylint * refactor * using asyncio implementation * changed to NotADirectoryError * fix pylint Co-authored-by: Andrei Neagu <[email protected]>
1 parent 387f1e3 commit 042a392

File tree

38 files changed

+680
-71
lines changed

38 files changed

+680
-71
lines changed

.env-devel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ POSTGRES_PASSWORD=adminadmin
3535
POSTGRES_PORT=5432
3636
POSTGRES_USER=scu
3737

38-
RABBIT_CHANNELS={"log": "comp.backend.channels.log", "progress": "comp.backend.channels.progress", "instrumentation": "comp.backend.channels.instrumentation"}
38+
RABBIT_CHANNELS={"log": "simcore.services.logs", "progress": "simcore.services.progress", "instrumentation": "simcore.services.instrumentation", "events": "simcore.services.events"}
3939
RABBIT_HOST=rabbit
4040
RABBIT_PASSWORD=adminadmin
4141
RABBIT_PORT=5672

api/specs/webserver/openapi-projects.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,32 @@ paths:
450450
default:
451451
$ref: "#/components/responses/DefaultErrorResponse"
452452

453+
/projects/{project_uuid}/nodes/{node_id}/restart:
454+
parameters:
455+
- name: project_uuid
456+
in: path
457+
required: true
458+
schema:
459+
type: string
460+
- name: node_id
461+
in: path
462+
required: true
463+
schema:
464+
type: string
465+
466+
post:
467+
tags:
468+
- project
469+
description: Restarts containers started by the dynamic-sidecar
470+
operationId: post_restart
471+
472+
responses:
473+
"204":
474+
description: Restarts containers started by the dynamic-sidecar
475+
476+
default:
477+
$ref: "#/components/responses/DefaultErrorResponse"
478+
453479
/projects/{study_uuid}/tags/{tag_id}:
454480
parameters:
455481
- name: tag_id

api/specs/webserver/openapi.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ paths:
203203
/projects/{project_id}/nodes/{node_id}:retrieve:
204204
$ref: "./openapi-projects.yaml#/paths/~1projects~1{project_id}~1nodes~1{node_id}~1retrieve"
205205

206+
/projects/{project_uuid}/nodes/{node_id}:restart:
207+
$ref: "./openapi-projects.yaml#/paths/~1projects~1{project_uuid}~1nodes~1{node_id}~1restart"
208+
206209
/nodes/{nodeInstanceUUID}/outputUi/{outputKey}:
207210
$ref: "./openapi-node-v0.0.1.yaml#/paths/~1nodes~1{nodeInstanceUUID}~1outputUi~1{outputKey}"
208211

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import List, Optional, Union
2+
from enum import Enum
23

34
from models_library.projects import ProjectID
45
from models_library.projects_nodes import NodeID
@@ -9,6 +10,10 @@
910
from simcore_postgres_database.models.comp_tasks import NodeClass
1011

1112

13+
class RabbitEventMessageType(str, Enum):
14+
RELOAD_IFRAME = "RELOAD_IFRAME"
15+
16+
1217
class RabbitMessageBase(BaseModel):
1318
node_id: NodeID
1419
user_id: UserID
@@ -19,6 +24,10 @@ class LoggerRabbitMessage(RabbitMessageBase):
1924
messages: List[str]
2025

2126

27+
class EventRabbitMessage(RabbitMessageBase):
28+
action: RabbitEventMessageType
29+
30+
2231
class ProgressRabbitMessage(RabbitMessageBase):
2332
progress: NonNegativeFloat
2433

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# pylint: disable=unsubscriptable-object
2+
from enum import Enum
23
import json
34
from functools import cached_property
45
from pathlib import Path
@@ -107,6 +108,11 @@ class Config(_BaseConfig):
107108
ComposeSpecLabel = Dict[str, Any]
108109

109110

111+
class RestartPolicy(str, Enum):
112+
NO_RESTART = "no-restart"
113+
ON_INPUTS_DOWNLOADED = "on-inputs-downloaded"
114+
115+
110116
class DynamicSidecarServiceLabels(BaseModel):
111117
paths_mapping: Optional[Json[PathMappingsLabel]] = Field(
112118
None,
@@ -137,6 +143,17 @@ class DynamicSidecarServiceLabels(BaseModel):
137143
),
138144
)
139145

146+
restart_policy: RestartPolicy = Field(
147+
RestartPolicy.NO_RESTART,
148+
alias="simcore.service.restart-policy",
149+
description=(
150+
"the dynamic-sidecar can restart all running containers "
151+
"on certain events. Supported events:\n"
152+
"- `no-restart` default\n"
153+
"- `on-inputs-downloaded` after inputs are downloaded\n"
154+
),
155+
)
156+
140157
@cached_property
141158
def needs_dynamic_sidecar(self) -> bool:
142159
"""if paths mapping is present the service needs to be ran via dynamic-sidecar"""
@@ -204,6 +221,7 @@ class Config(_BaseConfig):
204221
"simcore.service.paths-mapping": json.dumps(
205222
PathMappingsLabel.Config.schema_extra["example"]
206223
),
224+
"simcore.service.restart-policy": RestartPolicy.NO_RESTART.value,
207225
},
208226
# dynamic-service with compose spec
209227
{
@@ -235,6 +253,7 @@ class Config(_BaseConfig):
235253
}
236254
),
237255
"simcore.service.container-http-entrypoint": "rt-web",
256+
"simcore.service.restart-policy": RestartPolicy.ON_INPUTS_DOWNLOADED.value,
238257
},
239258
]
240259
}

packages/models-library/src/models_library/settings/rabbit.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import warnings
2-
from typing import Dict
2+
from typing_extensions import TypedDict
33

44
from pydantic import BaseSettings, Extra
55
from pydantic.networks import AnyUrl
66
from pydantic.types import PositiveInt, SecretStr
77

8+
9+
class Channels(TypedDict):
10+
log: str
11+
progress: str
12+
instrumentation: str
13+
events: str
14+
15+
816
warnings.warn(
917
"models_library.settings will be mostly replaced by settings_library in future versions. "
1018
"SEE https://github.com/ITISFoundation/osparc-simcore/pull/2395 for details",
@@ -26,10 +34,11 @@ class RabbitConfig(BaseSettings):
2634
password: SecretStr = SecretStr("simcore")
2735

2836
# channels
29-
channels: Dict[str, str] = {
30-
"log": "comp.backend.channels.log",
31-
"progress": "comp.backend.channels.progress",
32-
"instrumentation": "comp.backend.channels.instrumentation",
37+
channels: Channels = {
38+
"log": "simcore.services.log",
39+
"progress": "simcore.services.progress",
40+
"instrumentation": "simcore.services.instrumentation",
41+
"events": "simcore.services.events",
3342
}
3443

3544
@property

packages/models-library/src/models_library/settings/services_common.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class ServicesCommonSettings(BaseSettings):
3232
"allow the service to finish the operation."
3333
),
3434
)
35+
restart_containers_timeout: PositiveInt = Field(
36+
1 * _MINUTE, description="timeout of containers restart"
37+
)
3538

3639
class Config:
3740
env_prefix = "SERVICES_COMMON_"

packages/models-library/tests/test_service_settings_labels.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
),
3131
SimcoreServiceExample(
3232
example=SimcoreServiceLabels.Config.schema_extra["examples"][1],
33-
items=2,
33+
items=3,
3434
uses_dynamic_sidecar=True,
3535
id="dynamic-service",
3636
),
3737
SimcoreServiceExample(
3838
example=SimcoreServiceLabels.Config.schema_extra["examples"][2],
39-
items=4,
39+
items=5,
4040
uses_dynamic_sidecar=True,
4141
id="dynamic-service-with-compose-spec",
4242
),
@@ -130,3 +130,13 @@ def test_simcore_services_labels_compose_spec_null_container_http_entry_provided
130130
sample_data["simcore.service.compose-spec"] = None
131131
with pytest.raises(ValidationError):
132132
SimcoreServiceLabels(**sample_data)
133+
134+
135+
def test_raises_error_wrong_restart_policy() -> None:
136+
simcore_service_labels: Dict[str, Any] = deepcopy(
137+
SimcoreServiceLabels.Config.schema_extra["examples"][2]
138+
)
139+
simcore_service_labels["simcore.service.restart-policy"] = "__not_a_valid_policy__"
140+
141+
with pytest.raises(ValueError):
142+
SimcoreServiceLabels(**simcore_service_labels)

packages/pytest-simcore/src/pytest_simcore/docker_registry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ def jupyter_service(docker_registry: str, node_meta_schema: Dict) -> Dict[str, A
231231
)
232232

233233

234-
@pytest.fixture(scope="session", params=["2.0.2"])
234+
@pytest.fixture(scope="session", params=["2.0.3"])
235235
def dy_static_file_server_version(request):
236236
return request.param
237237

packages/service-integration/src/service_integration/osparc_config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from pathlib import Path
1616
from typing import Any, Dict, List, Literal, Optional
17+
from models_library.service_settings_labels import RestartPolicy
1718

1819
from models_library.services import (
1920
COMPUTATIONAL_SERVICE_KEY_FORMAT,
@@ -157,6 +158,8 @@ class RuntimeConfig(BaseModel):
157158
compose_spec: Optional[ComposeSpecification] = None
158159
container_http_entrypoint: Optional[str] = None
159160

161+
restart_policy: RestartPolicy = RestartPolicy.NO_RESTART
162+
160163
paths_mapping: Optional[PathsMapping] = None
161164

162165
settings: List[SettingsItem] = []

0 commit comments

Comments
 (0)