1
+ import contextlib
1
2
import re
3
+ from typing import Any , ClassVar , Final
2
4
3
5
from models_library .generated_models .docker_rest_api import Task
4
6
from models_library .products import ProductName
5
7
from models_library .projects import ProjectID
6
8
from models_library .projects_nodes import NodeID
7
9
from models_library .users import UserID
8
- from pydantic import BaseModel , ConstrainedStr , Field
10
+ from pydantic import (
11
+ BaseModel ,
12
+ ByteSize ,
13
+ ConstrainedStr ,
14
+ Field ,
15
+ ValidationError ,
16
+ parse_obj_as ,
17
+ root_validator ,
18
+ )
9
19
10
20
from .basic_regex import DOCKER_GENERIC_TAG_KEY_RE , DOCKER_LABEL_KEY_REGEX
11
21
@@ -21,29 +31,176 @@ class DockerGenericTag(ConstrainedStr):
21
31
regex : re .Pattern [str ] | None = DOCKER_GENERIC_TAG_KEY_RE
22
32
23
33
24
- class SimcoreServiceDockerLabelKeys (BaseModel ):
25
- # NOTE: in a next PR, this should be moved to packages models-library and used
26
- # all over, and aliases should use io.simcore.service.*
27
- # https://github.com/ITISFoundation/osparc-simcore/issues/3638
34
+ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX : Final [str ] = "io.simcore.runtime."
35
+ _BACKWARDS_COMPATIBILITY_SIMCORE_RUNTIME_DOCKER_LABELS_MAP : Final [dict [str , str ]] = {
36
+ "node_id" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } node-id" ,
37
+ "product_name" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } product-name" ,
38
+ "project_id" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } project-id" ,
39
+ "simcore_user_agent" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } simcore-user-agent" ,
40
+ "study_id" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } project-id" ,
41
+ "user_id" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } user-id" ,
42
+ "uuid" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } node-id" ,
43
+ "mem_limit" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } memory-limit" ,
44
+ "swarm_stack_name" : f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } swarm-stack-name" ,
45
+ }
46
+ _UNDEFINED_LABEL_VALUE_STR : Final [str ] = "undefined"
47
+ _UNDEFINED_LABEL_VALUE_INT : Final [str ] = "0"
28
48
29
- user_id : UserID = Field (..., alias = "user_id" )
30
- project_id : ProjectID = Field (..., alias = "study_id" )
31
- node_id : NodeID = Field (..., alias = "uuid" )
32
49
33
- product_name : ProductName = "opsarc"
34
- simcore_user_agent : str = ""
50
+ def to_simcore_runtime_docker_label_key (key : str ) -> DockerLabelKey :
51
+ return DockerLabelKey (
52
+ f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } { key .replace ('_' , '-' ).lower ()} "
53
+ )
35
54
36
- def to_docker_labels (self ) -> dict [str , str ]:
55
+
56
+ class StandardSimcoreDockerLabels (BaseModel ):
57
+ """
58
+ Represents the standard label on oSparc created containers (not yet services)
59
+ In order to create this object in code, please use construct() method!
60
+ """
61
+
62
+ user_id : UserID = Field (..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } user-id" )
63
+ project_id : ProjectID = Field (
64
+ ..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } project-id"
65
+ )
66
+ node_id : NodeID = Field (..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } node-id" )
67
+
68
+ product_name : ProductName = Field (
69
+ ..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } product-name"
70
+ )
71
+ simcore_user_agent : str = Field (
72
+ ..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } simcore-user-agent"
73
+ )
74
+
75
+ swarm_stack_name : str = Field (
76
+ ..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } swarm-stack-name"
77
+ )
78
+
79
+ memory_limit : ByteSize = Field (
80
+ ..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } memory-limit"
81
+ )
82
+ cpu_limit : float = Field (
83
+ ..., alias = f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } cpu-limit"
84
+ )
85
+
86
+ @root_validator (pre = True )
87
+ @classmethod
88
+ def _backwards_compatibility (cls , values : dict [str , Any ]) -> dict [str , Any ]:
89
+ # NOTE: this is necessary for dy-sidecar and legacy service until they are adjusted
90
+ if mapped_values := {
91
+ _BACKWARDS_COMPATIBILITY_SIMCORE_RUNTIME_DOCKER_LABELS_MAP [k ]: v
92
+ for k , v in values .items ()
93
+ if k in _BACKWARDS_COMPATIBILITY_SIMCORE_RUNTIME_DOCKER_LABELS_MAP
94
+ }:
95
+ # these values were sometimes omitted, so let's provide some defaults
96
+ for key in ["product-name" , "simcore-user-agent" , "swarm-stack-name" ]:
97
+ mapped_values .setdefault (
98
+ f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } { key } " ,
99
+ _UNDEFINED_LABEL_VALUE_STR ,
100
+ )
101
+
102
+ mapped_values .setdefault (
103
+ f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } memory-limit" ,
104
+ _UNDEFINED_LABEL_VALUE_INT ,
105
+ )
106
+
107
+ def _convert_nano_cpus_to_cpus (nano_cpu : str ) -> str :
108
+ with contextlib .suppress (ValidationError ):
109
+ return f"{ parse_obj_as (float , nano_cpu ) / (1.0 * 10 ** 9 ):.2f} "
110
+ return _UNDEFINED_LABEL_VALUE_INT
111
+
112
+ mapped_values .setdefault (
113
+ f"{ _SIMCORE_RUNTIME_DOCKER_LABEL_PREFIX } cpu-limit" ,
114
+ _convert_nano_cpus_to_cpus (
115
+ values .get ("nano_cpus_limit" , _UNDEFINED_LABEL_VALUE_INT )
116
+ ),
117
+ )
118
+ return mapped_values
119
+ return values
120
+
121
+ def to_simcore_runtime_docker_labels (self ) -> dict [DockerLabelKey , str ]:
37
122
"""returns a dictionary of strings as required by docker"""
38
- std_export = self .dict (by_alias = True )
39
- return {k : f"{ v } " for k , v in sorted (std_export .items ())}
123
+ return {
124
+ to_simcore_runtime_docker_label_key (k ): f"{ v } "
125
+ for k , v in sorted (self .dict ().items ())
126
+ }
40
127
41
128
@classmethod
42
- def from_docker_task (cls , docker_task : Task ) -> "SimcoreServiceDockerLabelKeys " :
129
+ def from_docker_task (cls , docker_task : Task ) -> "StandardSimcoreDockerLabels " :
43
130
assert docker_task .Spec # nosec
44
131
assert docker_task .Spec .ContainerSpec # nosec
45
132
task_labels = docker_task .Spec .ContainerSpec .Labels or {}
46
133
return cls .parse_obj (task_labels )
47
134
48
135
class Config :
49
136
allow_population_by_field_name = True
137
+ schema_extra : ClassVar [dict [str , Any ]] = {
138
+ "examples" : [
139
+ # legacy service labels
140
+ {
141
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
142
+ "swarm_stack_name" : "devel-simcore" ,
143
+ "user_id" : "5" ,
144
+ "uuid" : "1f963626-66e1-43f1-a777-33955c08b909" ,
145
+ },
146
+ # legacy container labels
147
+ {
148
+ "mem_limit" : "1073741824" ,
149
+ "nano_cpus_limit" : "4000000000" ,
150
+ "node_id" : "1f963626-66e1-43f1-a777-33955c08b909" ,
151
+ "simcore_user_agent" : "puppeteer" ,
152
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
153
+ "swarm_stack_name" : "devel-simcore" ,
154
+ "user_id" : "5" ,
155
+ },
156
+ # dy-sidecar service labels
157
+ {
158
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
159
+ "swarm_stack_name" : "devel-simcore" ,
160
+ "user_id" : "5" ,
161
+ "uuid" : "1f963626-66e1-43f1-a777-33955c08b909" ,
162
+ },
163
+ # dy-sidecar container labels
164
+ {
165
+ "mem_limit" : "1073741824" ,
166
+ "nano_cpus_limit" : "4000000000" ,
167
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
168
+ "user_id" : "5" ,
169
+ "uuid" : "1f963626-66e1-43f1-a777-33955c08b909" ,
170
+ },
171
+ # dy-proxy service labels
172
+ {
173
+ "dynamic-type" : "dynamic-sidecar" ,
174
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
175
+ "swarm_stack_name" : "devel-simcore" ,
176
+ "type" : "dependency-v2" ,
177
+ "user_id" : "5" ,
178
+ "uuid" : "1f963626-66e1-43f1-a777-33955c08b909" ,
179
+ },
180
+ # dy-proxy container labels
181
+ {
182
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
183
+ "user_id" : "5" ,
184
+ "uuid" : "1f963626-66e1-43f1-a777-33955c08b909" ,
185
+ },
186
+ # dy-sidecar user-services labels
187
+ {
188
+ "product_name" : "osparc" ,
189
+ "simcore_user_agent" : "puppeteer" ,
190
+ "study_id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
191
+ "user_id" : "5" ,
192
+ "uuid" : "1f963626-66e1-43f1-a777-33955c08b909" ,
193
+ },
194
+ # modern both dynamic-sidecar services and computational services
195
+ {
196
+ "io.simcore.runtime.cpu-limit" : "2.4" ,
197
+ "io.simcore.runtime.memory-limit" : "1073741824" ,
198
+ "io.simcore.runtime.node-id" : "1f963626-66e1-43f1-a777-33955c08b909" ,
199
+ "io.simcore.runtime.product-name" : "osparc" ,
200
+ "io.simcore.runtime.project-id" : "29f393fc-1410-47b3-b4b9-61dfce21a2a6" ,
201
+ "io.simcore.runtime.simcore-user-agent" : "puppeteer" ,
202
+ "io.simcore.runtime.swarm-stack-name" : "devel-osparc" ,
203
+ "io.simcore.runtime.user-id" : "5" ,
204
+ },
205
+ ]
206
+ }
0 commit comments