|
1 | | -import contextlib |
2 | 1 | import re |
3 | | -from typing import Annotated, Any, Final, TypeAlias |
| 2 | +from typing import Annotated, TypeAlias |
4 | 3 |
|
5 | 4 | from pydantic import ( |
6 | | - BaseModel, |
7 | | - ByteSize, |
8 | | - ConfigDict, |
9 | | - Field, |
10 | 5 | StringConstraints, |
11 | | - TypeAdapter, |
12 | | - ValidationError, |
13 | | - model_validator, |
14 | 6 | ) |
15 | 7 |
|
16 | 8 | from .basic_regex import DOCKER_GENERIC_TAG_KEY_RE, DOCKER_LABEL_KEY_REGEX |
17 | 9 | from .basic_types import ConstrainedStr |
18 | | -from .generated_models.docker_rest_api import Task |
19 | | -from .products import ProductName |
20 | | -from .projects import ProjectID |
21 | | -from .projects_nodes_io import NodeID |
22 | | -from .users import UserID |
23 | 10 |
|
24 | 11 |
|
25 | 12 | class DockerLabelKey(ConstrainedStr): |
@@ -47,192 +34,6 @@ def from_key(cls, key: str) -> "DockerLabelKey": |
47 | 34 | ), |
48 | 35 | ] |
49 | 36 |
|
50 | | -_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX: Final[str] = "io.simcore.runtime." |
51 | | -_BACKWARDS_COMPATIBILITY_SIMCORE_RUNTIME_DOCKER_LABELS_MAP: Final[dict[str, str]] = { |
52 | | - "node_id": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}node-id", |
53 | | - "product_name": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}product-name", |
54 | | - "project_id": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}project-id", |
55 | | - "simcore_user_agent": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}simcore-user-agent", |
56 | | - "study_id": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}project-id", |
57 | | - "user_id": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}user-id", |
58 | | - "uuid": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}node-id", |
59 | | - "mem_limit": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}memory-limit", |
60 | | - "swarm_stack_name": f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}swarm-stack-name", |
61 | | -} |
62 | | -_UNDEFINED_LABEL_VALUE_STR: Final[str] = "undefined" |
63 | | -_UNDEFINED_LABEL_VALUE_INT: Final[str] = "0" |
64 | | - |
65 | | - |
66 | | -DOCKER_TASK_EC2_INSTANCE_TYPE_PLACEMENT_CONSTRAINT_KEY: Final[DockerLabelKey] = ( |
67 | | - TypeAdapter(DockerLabelKey).validate_python("ec2-instance-type") |
68 | | -) |
69 | | - |
70 | | - |
71 | | -def to_simcore_runtime_docker_label_key(key: str) -> DockerLabelKey: |
72 | | - return DockerLabelKey( |
73 | | - f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}{key.replace('_', '-').lower()}" |
74 | | - ) |
75 | | - |
76 | | - |
77 | | -class StandardSimcoreDockerLabels(BaseModel): |
78 | | - """ |
79 | | - Represents the standard label on oSparc created containers (not yet services) |
80 | | - In order to create this object in code, please use model_construct() method! |
81 | | - """ |
82 | | - |
83 | | - user_id: UserID = Field(..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}user-id") # type: ignore[literal-required] |
84 | | - project_id: ProjectID = Field( # type: ignore[literal-required] |
85 | | - ..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}project-id" |
86 | | - ) |
87 | | - node_id: NodeID = Field(..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}node-id") # type: ignore[literal-required] |
88 | | - |
89 | | - product_name: ProductName = Field( # type: ignore[literal-required] |
90 | | - ..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}product-name" |
91 | | - ) |
92 | | - simcore_user_agent: str = Field( # type: ignore[literal-required] |
93 | | - ..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}simcore-user-agent" |
94 | | - ) |
95 | | - |
96 | | - swarm_stack_name: str = Field( # type: ignore[literal-required] |
97 | | - ..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}swarm-stack-name" |
98 | | - ) |
99 | | - |
100 | | - memory_limit: ByteSize = Field( # type: ignore[literal-required] |
101 | | - ..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}memory-limit" |
102 | | - ) |
103 | | - cpu_limit: float = Field( # type: ignore[literal-required] |
104 | | - ..., alias=f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}cpu-limit" |
105 | | - ) |
106 | | - |
107 | | - @model_validator(mode="before") |
108 | | - @classmethod |
109 | | - def _backwards_compatibility(cls, values: dict[str, Any]) -> dict[str, Any]: |
110 | | - # NOTE: this is necessary for dy-sidecar and legacy service until they are adjusted |
111 | | - if mapped_values := { |
112 | | - _BACKWARDS_COMPATIBILITY_SIMCORE_RUNTIME_DOCKER_LABELS_MAP[k]: v |
113 | | - for k, v in values.items() |
114 | | - if k in _BACKWARDS_COMPATIBILITY_SIMCORE_RUNTIME_DOCKER_LABELS_MAP |
115 | | - }: |
116 | | - # these values were sometimes omitted, so let's provide some defaults |
117 | | - for key in ["product-name", "simcore-user-agent", "swarm-stack-name"]: |
118 | | - mapped_values.setdefault( |
119 | | - f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}{key}", |
120 | | - _UNDEFINED_LABEL_VALUE_STR, |
121 | | - ) |
122 | | - |
123 | | - mapped_values.setdefault( |
124 | | - f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}memory-limit", |
125 | | - values.get("memory_limit", _UNDEFINED_LABEL_VALUE_INT), |
126 | | - ) |
127 | | - |
128 | | - def _convert_nano_cpus_to_cpus(nano_cpu: str) -> str: |
129 | | - with contextlib.suppress(ValidationError): |
130 | | - return f"{TypeAdapter(float).validate_python(nano_cpu) / (1.0 * 10**9):.2f}" |
131 | | - return _UNDEFINED_LABEL_VALUE_INT |
132 | | - |
133 | | - mapped_values.setdefault( |
134 | | - f"{_SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX}cpu-limit", |
135 | | - values.get( |
136 | | - "cpu_limit", |
137 | | - _convert_nano_cpus_to_cpus( |
138 | | - values.get( |
139 | | - "nano_cpus_limit", |
140 | | - _UNDEFINED_LABEL_VALUE_INT, |
141 | | - ) |
142 | | - ), |
143 | | - ), |
144 | | - ) |
145 | | - return mapped_values |
146 | | - return values |
147 | | - |
148 | | - def to_simcore_runtime_docker_labels(self) -> dict[DockerLabelKey, str]: |
149 | | - """returns a dictionary of strings as required by docker""" |
150 | | - return { |
151 | | - to_simcore_runtime_docker_label_key(k): f"{v}" |
152 | | - for k, v in sorted(self.model_dump().items()) |
153 | | - } |
154 | | - |
155 | | - @classmethod |
156 | | - def from_docker_task(cls, docker_task: Task) -> "StandardSimcoreDockerLabels": |
157 | | - assert docker_task.spec # nosec |
158 | | - assert docker_task.spec.container_spec # nosec |
159 | | - task_labels = docker_task.spec.container_spec.labels or {} |
160 | | - return cls.model_validate(task_labels) |
161 | | - |
162 | | - model_config = ConfigDict( |
163 | | - populate_by_name=True, |
164 | | - json_schema_extra={ |
165 | | - "examples": [ |
166 | | - # legacy service labels |
167 | | - { |
168 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
169 | | - "swarm_stack_name": "devel-simcore", |
170 | | - "user_id": "5", |
171 | | - "uuid": "1f963626-66e1-43f1-a777-33955c08b909", |
172 | | - }, |
173 | | - # legacy container labels |
174 | | - { |
175 | | - "mem_limit": "1073741824", |
176 | | - "nano_cpus_limit": "4000000000", |
177 | | - "node_id": "1f963626-66e1-43f1-a777-33955c08b909", |
178 | | - "simcore_user_agent": "puppeteer", |
179 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
180 | | - "swarm_stack_name": "devel-simcore", |
181 | | - "user_id": "5", |
182 | | - }, |
183 | | - # dy-sidecar service labels |
184 | | - { |
185 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
186 | | - "swarm_stack_name": "devel-simcore", |
187 | | - "user_id": "5", |
188 | | - "uuid": "1f963626-66e1-43f1-a777-33955c08b909", |
189 | | - }, |
190 | | - # dy-sidecar container labels |
191 | | - { |
192 | | - "mem_limit": "1073741824", |
193 | | - "nano_cpus_limit": "4000000000", |
194 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
195 | | - "user_id": "5", |
196 | | - "uuid": "1f963626-66e1-43f1-a777-33955c08b909", |
197 | | - }, |
198 | | - # dy-proxy service labels |
199 | | - { |
200 | | - "dynamic-type": "dynamic-sidecar", |
201 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
202 | | - "swarm_stack_name": "devel-simcore", |
203 | | - "type": "dependency-v2", |
204 | | - "user_id": "5", |
205 | | - "uuid": "1f963626-66e1-43f1-a777-33955c08b909", |
206 | | - }, |
207 | | - # dy-proxy container labels |
208 | | - { |
209 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
210 | | - "user_id": "5", |
211 | | - "uuid": "1f963626-66e1-43f1-a777-33955c08b909", |
212 | | - }, |
213 | | - # dy-sidecar user-services labels |
214 | | - { |
215 | | - "product_name": "osparc", |
216 | | - "simcore_user_agent": "puppeteer", |
217 | | - "study_id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
218 | | - "user_id": "5", |
219 | | - "uuid": "1f963626-66e1-43f1-a777-33955c08b909", |
220 | | - }, |
221 | | - # modern both dynamic-sidecar services and computational services |
222 | | - { |
223 | | - "io.simcore.runtime.cpu-limit": "2.4", |
224 | | - "io.simcore.runtime.memory-limit": "1073741824", |
225 | | - "io.simcore.runtime.node-id": "1f963626-66e1-43f1-a777-33955c08b909", |
226 | | - "io.simcore.runtime.product-name": "osparc", |
227 | | - "io.simcore.runtime.project-id": "29f393fc-1410-47b3-b4b9-61dfce21a2a6", |
228 | | - "io.simcore.runtime.simcore-user-agent": "puppeteer", |
229 | | - "io.simcore.runtime.swarm-stack-name": "devel-osparc", |
230 | | - "io.simcore.runtime.user-id": "5", |
231 | | - }, |
232 | | - ] |
233 | | - }, |
234 | | - ) |
235 | | - |
236 | 37 |
|
237 | 38 | DockerNodeID: TypeAlias = Annotated[ |
238 | 39 | str, StringConstraints(strip_whitespace=True, pattern=re.compile(r"[a-zA-Z0-9]")) |
|
0 commit comments