ScriptCollection 3.3.23__py3-none-any.whl → 4.0.78__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. ScriptCollection/AnionBuildPlatform.py +206 -0
  2. ScriptCollection/{UpdateCertificates.py → CertificateUpdater.py} +149 -128
  3. ScriptCollection/Executables.py +868 -292
  4. ScriptCollection/GeneralUtilities.py +609 -107
  5. ScriptCollection/ImageUpdater.py +648 -0
  6. ScriptCollection/ProcessesRunner.py +41 -0
  7. ScriptCollection/ProgramRunnerBase.py +47 -42
  8. ScriptCollection/ProgramRunnerMock.py +2 -0
  9. ScriptCollection/ProgramRunnerPopen.py +57 -50
  10. ScriptCollection/ProgramRunnerSudo.py +108 -0
  11. ScriptCollection/SCLog.py +115 -0
  12. ScriptCollection/ScriptCollectionCore.py +2541 -1383
  13. ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py +95 -0
  14. ScriptCollection/TFCPS/Docker/__init__.py +0 -0
  15. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py +8 -0
  16. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py +6 -0
  17. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py +7 -0
  18. ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py +485 -0
  19. ScriptCollection/TFCPS/DotNet/__init__.py +0 -0
  20. ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py +130 -0
  21. ScriptCollection/TFCPS/Flutter/__init__.py +0 -0
  22. ScriptCollection/TFCPS/Go/TFCPS_CodeUnitSpecific_Go.py +74 -0
  23. ScriptCollection/TFCPS/Go/__init__.py +0 -0
  24. ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py +131 -0
  25. ScriptCollection/TFCPS/NodeJS/__init__.py +0 -0
  26. ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py +227 -0
  27. ScriptCollection/TFCPS/Python/__init__.py +0 -0
  28. ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py +418 -0
  29. ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py +128 -0
  30. ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py +136 -0
  31. ScriptCollection/TFCPS/TFCPS_CreateRelease.py +95 -0
  32. ScriptCollection/TFCPS/TFCPS_Generic.py +43 -0
  33. ScriptCollection/TFCPS/TFCPS_MergeToMain.py +122 -0
  34. ScriptCollection/TFCPS/TFCPS_MergeToStable.py +350 -0
  35. ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py +47 -0
  36. ScriptCollection/TFCPS/TFCPS_Tools_General.py +1356 -0
  37. ScriptCollection/TFCPS/__init__.py +0 -0
  38. {ScriptCollection-3.3.23.dist-info → scriptcollection-4.0.78.dist-info}/METADATA +26 -21
  39. scriptcollection-4.0.78.dist-info/RECORD +43 -0
  40. {ScriptCollection-3.3.23.dist-info → scriptcollection-4.0.78.dist-info}/WHEEL +1 -1
  41. scriptcollection-4.0.78.dist-info/entry_points.txt +64 -0
  42. ScriptCollection/Hardening.py +0 -59
  43. ScriptCollection/ProgramRunnerEpew.py +0 -122
  44. ScriptCollection/TasksForCommonProjectStructure.py +0 -1170
  45. ScriptCollection-3.3.23.dist-info/RECORD +0 -15
  46. ScriptCollection-3.3.23.dist-info/entry_points.txt +0 -24
  47. {ScriptCollection-3.3.23.dist-info → scriptcollection-4.0.78.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,648 @@
1
+ from abc import abstractmethod
2
+ import json
3
+ import re
4
+ from urllib.parse import quote
5
+ import yaml
6
+ import requests
7
+ from packaging import version as ve
8
+ from packaging.version import Version
9
+ from .GeneralUtilities import GeneralUtilities,VersionEcholon
10
+
11
+
12
+ class ImageUpdaterHelper:
13
+
14
+ @staticmethod
15
+ @GeneralUtilities.check_arguments
16
+ def _internal_filter_for_major_and_minor_versions(versions: list[Version], major: int, minor: int) -> Version:
17
+ return [v for v in versions if v.major == major and v.minor == minor]
18
+
19
+ @staticmethod
20
+ @GeneralUtilities.check_arguments
21
+ def _internal_filter_for_major_versions(versions: list[Version], major: int) -> Version:
22
+ return [v for v in versions if v.major == major]
23
+
24
+ @staticmethod
25
+ @GeneralUtilities.check_arguments
26
+ def _internal_get_latest_patch_version(newer_versions: list[Version], current_version: Version) -> Version:
27
+ candidates = ImageUpdaterHelper._internal_filter_for_major_and_minor_versions(newer_versions, current_version.major, current_version.minor)
28
+ if len(candidates) == 0:
29
+ return current_version
30
+ result = ImageUpdaterHelper.get_latest_version(candidates)
31
+ return result
32
+
33
+ @staticmethod
34
+ @GeneralUtilities.check_arguments
35
+ def _internal_get_latest_patch_or_latest_minor_version(newer_versions: list[Version], current_version: Version) -> Version:
36
+ candidates = ImageUpdaterHelper._internal_filter_for_major_versions(newer_versions, current_version.major)
37
+ if len(candidates) == 0:
38
+ return current_version
39
+ result = ImageUpdaterHelper.get_latest_version(candidates)
40
+ return result
41
+
42
+ @staticmethod
43
+ @GeneralUtilities.check_arguments
44
+ def _internal_get_latest_patch_or_latest_minor_or_next_major_version(newer_versions: list[Version], current_version: Version) -> Version:
45
+ candidates = ImageUpdaterHelper._internal_filter_for_major_versions(newer_versions, current_version.major+1)
46
+ if 0 < len(candidates):
47
+ result = ImageUpdaterHelper.get_latest_version(candidates)
48
+ return result
49
+ else:
50
+ candidates = ImageUpdaterHelper._internal_filter_for_major_versions(newer_versions, current_version.major)
51
+ if len(candidates) == 0:
52
+ return current_version
53
+ result = ImageUpdaterHelper.get_latest_version(candidates)
54
+ return result
55
+
56
+ @staticmethod
57
+ @GeneralUtilities.check_arguments
58
+ def filter_considering_echolon(newer_versions: list[Version], current_version: Version, version_echolon: VersionEcholon) -> Version:
59
+ if version_echolon == VersionEcholon.LatestPatch:
60
+ return ImageUpdaterHelper._internal_get_latest_patch_version(newer_versions, current_version)
61
+ elif version_echolon == VersionEcholon.LatestPatchOrLatestMinor:
62
+ return ImageUpdaterHelper._internal_get_latest_patch_or_latest_minor_version(newer_versions, current_version)
63
+ elif version_echolon == VersionEcholon.LatestPatchOrLatestMinorOrNextMajor:
64
+ return ImageUpdaterHelper._internal_get_latest_patch_or_latest_minor_or_next_major_version(newer_versions, current_version)
65
+ elif version_echolon == VersionEcholon.LatestVersion:
66
+ return ImageUpdaterHelper.get_latest_version(newer_versions)
67
+ else:
68
+ raise ValueError(f"Unknown version-echolon")
69
+
70
+ @staticmethod
71
+ @GeneralUtilities.check_arguments
72
+ def get_latest_version(versions: list[Version]) -> Version:
73
+ result = max(versions)
74
+ return result
75
+
76
+ @staticmethod
77
+ @GeneralUtilities.check_arguments
78
+ def get_latest_version_from_versiontrings(version_strings: list[str]) -> str:
79
+ parsed = [ve.parse(v) for v in version_strings]
80
+ result = max(parsed)
81
+ return str(result)
82
+
83
+ @staticmethod
84
+ @GeneralUtilities.check_arguments
85
+ def filter_for_newer_versions(comparison_version: Version, versions_to_filter: list[Version]) -> list[Version]:
86
+ result = [v for v in versions_to_filter if comparison_version < v]
87
+ return result
88
+
89
+ @staticmethod
90
+ @GeneralUtilities.check_arguments
91
+ def get_versions_in_docker_hub(image: str, search_string: str, filter_regex: str, maximal_amount_of_items_to_load: int = 250) -> list[Version]:#TODO add option to specify image source url
92
+ if "/" not in image:
93
+ image = f"library/{image}"
94
+ response = requests.get(f"https://hub.docker.com/v2/repositories/{quote(image)}/tags?name={quote(search_string)}&ordering=last_updated&page=1&page_size={str(maximal_amount_of_items_to_load)}", timeout=20, headers={'Cache-Control': 'no-cache'})
95
+ if response.status_code != 200:
96
+ raise ValueError(f"Failed to fetch data from Docker Hub: {response.status_code}")
97
+ response_text = response.text
98
+ data = json.loads(response_text)
99
+ tags: list[str] = [tag["name"] for tag in data["results"] if re.match(filter_regex, tag["name"])]
100
+ versions = [tag.split("-")[0] for tag in tags]
101
+ result = [ve.parse(v) for v in versions]
102
+ return result
103
+
104
+
105
+ class ConcreteImageUpdater:
106
+
107
+ @abstractmethod
108
+ @GeneralUtilities.check_arguments
109
+ def version_to_tag(self, version: Version) -> str:
110
+ raise NotImplementedError
111
+
112
+ @abstractmethod
113
+ @GeneralUtilities.check_arguments
114
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
115
+ raise NotImplementedError
116
+
117
+ @abstractmethod
118
+ @GeneralUtilities.check_arguments
119
+ def get_supported_images(self) -> list[str]:
120
+ raise NotImplementedError
121
+
122
+ @abstractmethod
123
+ @GeneralUtilities.check_arguments
124
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
125
+ raise NotImplementedError
126
+
127
+ @abstractmethod
128
+ @GeneralUtilities.check_arguments
129
+ def get_name(self, image: str, tag: str) -> str:
130
+ raise NotImplementedError
131
+
132
+
133
+ class ConcreteImageUpdaterForNginx(ConcreteImageUpdater):
134
+
135
+ @GeneralUtilities.check_arguments
136
+ def version_to_tag(self, version: Version) -> str:
137
+ return f"{version.major}.{version.minor}.{version.micro}"
138
+
139
+ @GeneralUtilities.check_arguments
140
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
141
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
142
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
143
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
144
+ return result
145
+
146
+ @GeneralUtilities.check_arguments
147
+ def get_supported_images(self) -> list[str]:
148
+ return ["nginx"]
149
+
150
+ @GeneralUtilities.check_arguments
151
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
152
+ return ve.parse(tag)
153
+
154
+ @abstractmethod
155
+ @GeneralUtilities.check_arguments
156
+ def get_name(self, image: str, tag: str) -> str:
157
+ return "Nginx"
158
+
159
+
160
+ class ConcreteImageUpdaterForWordpress(ConcreteImageUpdater):
161
+
162
+ @GeneralUtilities.check_arguments
163
+ def version_to_tag(self, version: Version) -> str:
164
+ return f"{version.major}.{version.minor}.{version.micro}"
165
+
166
+ @GeneralUtilities.check_arguments
167
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
168
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
169
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
170
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
171
+ return result
172
+
173
+ @GeneralUtilities.check_arguments
174
+ def get_supported_images(self) -> list[str]:
175
+ return ["wordpress"]
176
+
177
+ @GeneralUtilities.check_arguments
178
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
179
+ return ve.parse(tag)
180
+
181
+ @abstractmethod
182
+ @GeneralUtilities.check_arguments
183
+ def get_name(self, image: str, tag: str) -> str:
184
+ return "Wordpress"
185
+
186
+
187
+ class ConcreteImageUpdaterForGitLab(ConcreteImageUpdater):
188
+
189
+ @GeneralUtilities.check_arguments
190
+ def version_to_tag(self, version: Version) -> str:
191
+ return f"{version.major}.{version.minor}.{version.micro}-ce.0"
192
+
193
+ @GeneralUtilities.check_arguments
194
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
195
+ raise NotImplementedError
196
+
197
+ @GeneralUtilities.check_arguments
198
+ def get_supported_images(self) -> list[str]:
199
+ return ["gitlab/gitlab-ce", "gitlab/gitlab-ee"]
200
+
201
+ @GeneralUtilities.check_arguments
202
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
203
+ raise NotImplementedError
204
+
205
+ @abstractmethod
206
+ @GeneralUtilities.check_arguments
207
+ def get_name(self, image: str, tag: str) -> str:
208
+ return "GitLab"
209
+
210
+
211
+ class ConcreteImageUpdaterForRegistry(ConcreteImageUpdater):
212
+
213
+ @GeneralUtilities.check_arguments
214
+ def version_to_tag(self, version: Version) -> str:
215
+ return f"{version.major}.{version.minor}.{version.micro}"
216
+
217
+ @GeneralUtilities.check_arguments
218
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
219
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
220
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
221
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
222
+ return result
223
+
224
+ @abstractmethod
225
+ @GeneralUtilities.check_arguments
226
+ def get_supported_images(self) -> list[str]:
227
+ return ["registry"]
228
+
229
+ @GeneralUtilities.check_arguments
230
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
231
+ return ve.parse(tag)
232
+
233
+ @abstractmethod
234
+ @GeneralUtilities.check_arguments
235
+ def get_name(self, image: str, tag: str) -> str:
236
+ return "Registry"
237
+
238
+
239
+ class ConcreteImageUpdaterForPrometheus(ConcreteImageUpdater):
240
+
241
+ @GeneralUtilities.check_arguments
242
+ def version_to_tag(self, version: Version) -> str:
243
+ return f"v{version.major}.{version.minor}.{version.micro}"
244
+
245
+ @GeneralUtilities.check_arguments
246
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
247
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^v\\d+\\.\\d+\\.\\d+$", 999)
248
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
249
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
250
+ return result
251
+
252
+ @GeneralUtilities.check_arguments
253
+ def get_supported_images(self) -> list[str]:
254
+ return ["prom/prometheus"]
255
+
256
+ @GeneralUtilities.check_arguments
257
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
258
+ return ve.parse(tag[1:])
259
+
260
+ @abstractmethod
261
+ @GeneralUtilities.check_arguments
262
+ def get_name(self, image: str, tag: str) -> str:
263
+ return "Prometheus"
264
+
265
+
266
+ class ConcreteImageUpdaterForPrometheusBlackboxExporter(ConcreteImageUpdater):
267
+
268
+ @GeneralUtilities.check_arguments
269
+ def version_to_tag(self, version: Version) -> str:
270
+ return f"v{version.major}.{version.minor}.{version.micro}"
271
+
272
+ @GeneralUtilities.check_arguments
273
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
274
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^v\\d+\\.\\d+\\.\\d+$", 999)
275
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
276
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
277
+ return result
278
+
279
+ @GeneralUtilities.check_arguments
280
+ def get_supported_images(self) -> list[str]:
281
+ return ["prom/blackbox-exporter"]
282
+
283
+ @GeneralUtilities.check_arguments
284
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
285
+ return ve.parse(tag[1:])
286
+
287
+ @abstractmethod
288
+ @GeneralUtilities.check_arguments
289
+ def get_name(self, image: str, tag: str) -> str:
290
+ return "PrometheusBlackboxExporter"
291
+
292
+
293
+ class ConcreteImageUpdaterForPrometheusNginxExporter(ConcreteImageUpdater):
294
+
295
+ @GeneralUtilities.check_arguments
296
+ def version_to_tag(self, version: Version) -> str:
297
+ return f"v{version.major}.{version.minor}.{version.micro}"
298
+
299
+ @GeneralUtilities.check_arguments
300
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
301
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^v\\d+\\.\\d+\\.\\d+$", 999)
302
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
303
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
304
+ return result
305
+
306
+ @GeneralUtilities.check_arguments
307
+ def get_supported_images(self) -> list[str]:
308
+ return ["prom/nginx-prometheus-exporter"]
309
+
310
+ @GeneralUtilities.check_arguments
311
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
312
+ return ve.parse(tag[1:])
313
+
314
+ @abstractmethod
315
+ @GeneralUtilities.check_arguments
316
+ def get_name(self, image: str, tag: str) -> str:
317
+ return "NginxPrometheusExporter"
318
+
319
+
320
+ class ConcreteImageUpdaterForPrometheusNodeExporter(ConcreteImageUpdater):
321
+
322
+ @GeneralUtilities.check_arguments
323
+ def version_to_tag(self, version: Version) -> str:
324
+ return f"v{version.major}.{version.minor}.{version.micro}"
325
+
326
+ @GeneralUtilities.check_arguments
327
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
328
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^v\\d+\\.\\d+\\.\\d+$", 999)
329
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
330
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
331
+ return result
332
+
333
+ @GeneralUtilities.check_arguments
334
+ def get_supported_images(self) -> list[str]:
335
+ return ["prom/node-exporter"]
336
+
337
+ @GeneralUtilities.check_arguments
338
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
339
+ return ve.parse(tag[1:])
340
+
341
+ @abstractmethod
342
+ @GeneralUtilities.check_arguments
343
+ def get_name(self, image: str, tag: str) -> str:
344
+ return "PrometheusNodeExporter"
345
+
346
+
347
+ class ConcreteImageUpdaterForKeycloak(ConcreteImageUpdater):
348
+
349
+ @GeneralUtilities.check_arguments
350
+ def version_to_tag(self, version: Version) -> str:
351
+ raise NotImplementedError
352
+
353
+ @GeneralUtilities.check_arguments
354
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
355
+ raise NotImplementedError
356
+
357
+ @GeneralUtilities.check_arguments
358
+ def get_supported_images(self) -> list[str]:
359
+ return [] # TODO
360
+
361
+ @GeneralUtilities.check_arguments
362
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
363
+ raise NotImplementedError
364
+
365
+ @abstractmethod
366
+ @GeneralUtilities.check_arguments
367
+ def get_name(self, image: str, tag: str) -> str:
368
+ return "KeyCloak"
369
+
370
+
371
+ class ConcreteImageUpdaterForMariaDB(ConcreteImageUpdater):
372
+
373
+ @GeneralUtilities.check_arguments
374
+ def version_to_tag(self, version: Version) -> str:
375
+ return f"{version.major}.{version.minor}.{version.micro}"
376
+
377
+ @GeneralUtilities.check_arguments
378
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
379
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
380
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
381
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
382
+ return result
383
+
384
+ @GeneralUtilities.check_arguments
385
+ def get_supported_images(self) -> list[str]:
386
+ return ["mariadb"]
387
+
388
+ @GeneralUtilities.check_arguments
389
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
390
+ return ve.parse(tag)
391
+
392
+ @abstractmethod
393
+ @GeneralUtilities.check_arguments
394
+ def get_name(self, image: str, tag: str) -> str:
395
+ return "MariaDB"
396
+
397
+
398
+ class ConcreteImageUpdaterForPostgreSQL(ConcreteImageUpdater):
399
+
400
+ @GeneralUtilities.check_arguments
401
+ def version_to_tag(self, version: Version) -> str:
402
+ return f"{version.major}.{version.minor}"
403
+
404
+ @GeneralUtilities.check_arguments
405
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
406
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+$", 999)
407
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
408
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
409
+ return result
410
+
411
+ @GeneralUtilities.check_arguments
412
+ def get_supported_images(self) -> list[str]:
413
+ return ["postgres"]
414
+
415
+ @GeneralUtilities.check_arguments
416
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
417
+ return ve.parse(tag+".0")
418
+
419
+ @abstractmethod
420
+ @GeneralUtilities.check_arguments
421
+ def get_name(self, image: str, tag: str) -> str:
422
+ return "PostgreSQL"
423
+
424
+
425
+ class ConcreteImageUpdaterForAdminer(ConcreteImageUpdater):
426
+
427
+ @GeneralUtilities.check_arguments
428
+ def version_to_tag(self, version: Version) -> str:
429
+ return f"{version.major}.{version.minor}.{version.micro}"
430
+
431
+ @GeneralUtilities.check_arguments
432
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
433
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
434
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
435
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
436
+ return result
437
+
438
+ @GeneralUtilities.check_arguments
439
+ def get_supported_images(self) -> list[str]:
440
+ return ["adminer"]
441
+
442
+ @GeneralUtilities.check_arguments
443
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
444
+ return ve.parse(tag)
445
+
446
+ @abstractmethod
447
+ @GeneralUtilities.check_arguments
448
+ def get_name(self, image: str, tag: str) -> str:
449
+ return "Adminer"
450
+
451
+
452
+ class ConcreteImageUpdaterForGeneric(ConcreteImageUpdater):
453
+
454
+ @GeneralUtilities.check_arguments
455
+ def version_to_tag(self, version: Version) -> str:
456
+ return f"{version.major}.{version.minor}.{version.micro}"
457
+
458
+ @GeneralUtilities.check_arguments
459
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
460
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
461
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
462
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
463
+ return result
464
+
465
+ @GeneralUtilities.check_arguments
466
+ def get_supported_images(self) -> list[str]:
467
+ return [".*"]
468
+
469
+ @GeneralUtilities.check_arguments
470
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
471
+ return ve.parse(tag)
472
+
473
+ @abstractmethod
474
+ @GeneralUtilities.check_arguments
475
+ def get_name(self, image: str, tag: str) -> str:
476
+ return "Generic"
477
+
478
+
479
+ class ConcreteImageUpdaterForGenericV(ConcreteImageUpdater):
480
+
481
+ @GeneralUtilities.check_arguments
482
+ def version_to_tag(self, version: Version) -> str:
483
+ return f"v{version.major}.{version.minor}.{version.micro}"
484
+
485
+ @GeneralUtilities.check_arguments
486
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
487
+ versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^v\\d+\\.\\d+\\.\\d+$", 999)
488
+ newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
489
+ result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
490
+ return result
491
+
492
+ @GeneralUtilities.check_arguments
493
+ def get_supported_images(self) -> list[str]:
494
+ return [".*"]
495
+
496
+ @GeneralUtilities.check_arguments
497
+ def get_version_from_tag(self, image: str, tag: str) -> Version:
498
+ return ve.parse(tag[1:])
499
+
500
+ @abstractmethod
501
+ @GeneralUtilities.check_arguments
502
+ def get_name(self, image: str, tag: str) -> str:
503
+ return "GenericV"
504
+
505
+
506
+ class ImageUpdater:
507
+
508
+ updater: list[ConcreteImageUpdater] = None
509
+
510
+ def __init__(self):
511
+ self.updater = list[ConcreteImageUpdater]()
512
+
513
+ def add_default_mapper(self) -> None:
514
+ self.updater.append(ConcreteImageUpdaterForNginx())
515
+ self.updater.append(ConcreteImageUpdaterForWordpress())
516
+ self.updater.append(ConcreteImageUpdaterForGitLab())
517
+ self.updater.append(ConcreteImageUpdaterForRegistry())
518
+ self.updater.append(ConcreteImageUpdaterForPrometheus())
519
+ self.updater.append(ConcreteImageUpdaterForPrometheusBlackboxExporter())
520
+ self.updater.append(ConcreteImageUpdaterForPrometheusNginxExporter())
521
+ self.updater.append(ConcreteImageUpdaterForPrometheusNodeExporter())
522
+ self.updater.append(ConcreteImageUpdaterForKeycloak())
523
+ self.updater.append(ConcreteImageUpdaterForMariaDB())
524
+ self.updater.append(ConcreteImageUpdaterForPostgreSQL())
525
+ self.updater.append(ConcreteImageUpdaterForAdminer())
526
+
527
+ @GeneralUtilities.check_arguments
528
+ def check_service_for_newest_version(self, dockercompose_file: str, service_name: str) -> bool:
529
+ imagename, existing_tag, existing_version = self.get_current_version_of_service_from_docker_compose_file(dockercompose_file, service_name) # pylint:disable=unused-variable
530
+ newest_version, newest_tag = self.get_latest_version_of_image(imagename, VersionEcholon.LatestVersion, existing_version) # pylint:disable=unused-variable
531
+ if existing_version < newest_version:
532
+ GeneralUtilities.write_message_to_stdout(f"Service {service_name} with image {imagename} uses tag {existing_version}. The newest available version of this image is {newest_version}.")
533
+ return True
534
+ else:
535
+ return False
536
+
537
+ @GeneralUtilities.check_arguments
538
+ def check_for_newest_version(self, dockercompose_file: str, excluded_services: list[str] = []) -> bool:
539
+ all_services = self.get_services_from_docker_compose_file(dockercompose_file)
540
+ services_to_check = [service for service in all_services if service not in all_services]
541
+ newer_version_available: bool = False
542
+ for service_to_check in services_to_check:
543
+ if self.check_service_for_newest_version(dockercompose_file, service_to_check):
544
+ newer_version_available = True
545
+ return newer_version_available
546
+
547
+ @GeneralUtilities.check_arguments
548
+ def update_all_services_in_docker_compose_file(self, dockercompose_file: str, version_echolon: VersionEcholon, except_services: list[str] = [], updatertype: str = None):
549
+ all_services = self.get_services_from_docker_compose_file(dockercompose_file)
550
+ services_to_update = [service for service in all_services if service not in except_services]
551
+ self.update_services_in_docker_compose_file(dockercompose_file, services_to_update, version_echolon, updatertype)
552
+
553
+ @GeneralUtilities.check_arguments
554
+ def update_services_in_docker_compose_file(self, dockercompose_file: str, service_names: list[str], version_echolon: VersionEcholon, updatertype: str = None):
555
+ for service_name in service_names:
556
+ if self.service_has_image_information(dockercompose_file, service_name):
557
+ self.update_service_in_docker_compose_file(dockercompose_file, service_name, version_echolon, updatertype)
558
+
559
+ @GeneralUtilities.check_arguments
560
+ def service_has_image_information(self, dockercompose_file: str, service_name: str) -> bool:
561
+ with open(dockercompose_file, 'r', encoding="utf-8") as file:
562
+ compose_data = yaml.safe_load(file)
563
+ service = compose_data.get('services', {}).get(service_name, {})
564
+ image = service.get('image', None)
565
+ return image is not None
566
+
567
+ @GeneralUtilities.check_arguments
568
+ def update_service_in_docker_compose_file(self, dockercompose_file: str, service_name: str, version_echolon: VersionEcholon, updatertype: str = None):
569
+ imagename, existing_tag, existing_version = self.get_current_version_of_service_from_docker_compose_file(dockercompose_file, service_name) # pylint:disable=unused-variable
570
+ result = self.get_latest_version_of_image(imagename, version_echolon, existing_version, updatertype)
571
+ newest_version = result[0]
572
+ newest_tag = result[1]
573
+ # TODO write info to console if there is a newwer version available if versionecoholon==latest would have been chosen
574
+ if existing_version < newest_version:
575
+
576
+ with open(dockercompose_file, 'r', encoding="utf-8") as f:
577
+ compose_data = yaml.safe_load(f)
578
+
579
+ services = compose_data.get("services", {})
580
+ if service_name not in services:
581
+ raise ValueError(f"Service '{service_name}' not found.")
582
+
583
+ image = services[service_name].get("image")
584
+ if not image:
585
+ raise ValueError(f"Service '{service_name}' does not have an image-field.")
586
+
587
+ imagename = image.split(":")[0]
588
+ services[service_name]["image"] = imagename+":"+newest_tag
589
+
590
+ with open(dockercompose_file, 'w', encoding="utf-8") as f:
591
+ yaml.dump(compose_data, f, default_flow_style=False)
592
+
593
+ @GeneralUtilities.check_arguments
594
+ def get_current_version_of_service_from_docker_compose_file(self, dockercompose_file: str, service_name: str) -> tuple[str, str, Version]: # returns (image,existing_tag,existing_version)
595
+ with open(dockercompose_file, 'r', encoding="utf-8") as file:
596
+ compose_data = yaml.safe_load(file)
597
+ service = compose_data.get('services', {}).get(service_name, {})
598
+ image = str(service.get('image', None))
599
+ if image:
600
+ if ':' in image:
601
+ name, tag = image.rsplit(':', 1)
602
+ else:
603
+ name, tag = image, 'latest'
604
+ return name, tag, self.get_docker_version_from_tag(name, tag)
605
+ else:
606
+ raise ValueError(f"Service '{service_name}' in '{dockercompose_file}'")
607
+
608
+ @GeneralUtilities.check_arguments
609
+ def __get_updater_for_image(self, image: str) -> ConcreteImageUpdater:
610
+ for updater in self.updater:
611
+ for supported_image_regex in updater.get_supported_images():
612
+ r = re.compile("^"+supported_image_regex+"$")
613
+ if r.match(supported_image_regex):
614
+ return updater
615
+ raise ValueError(f"No updater available for image '{image}'")
616
+
617
+ @GeneralUtilities.check_arguments
618
+ def __get_updater_by_name(self, updater_name: str) -> ConcreteImageUpdater:
619
+ for updater in self.updater:
620
+ if updater.get_name() == updater_name:
621
+ return updater
622
+ raise ValueError(f"No updater available with name '{updater_name}'")
623
+
624
+ @GeneralUtilities.check_arguments
625
+ def get_docker_version_from_tag(self, image: str, tag: str) -> Version:
626
+ updater: ConcreteImageUpdater = self.__get_updater_for_image(image)
627
+ return updater.get_version_from_tag(image, tag)
628
+
629
+ @GeneralUtilities.check_arguments
630
+ def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version, updatertype: str = None) -> tuple[Version, str]:
631
+
632
+ updater: ConcreteImageUpdater = None
633
+ if updatertype is None:
634
+ self.__get_updater_for_image(image)
635
+ else:
636
+ self.__get_updater_by_name(updatertype)
637
+
638
+ newest_version: Version = updater.get_latest_version_of_image(image, version_echolon, current_version)
639
+ newest_tag: str = updater.version_to_tag(newest_version)
640
+ return (newest_version, newest_tag)
641
+
642
+ @GeneralUtilities.check_arguments
643
+ def get_services_from_docker_compose_file(self, dockercompose_file: str) -> list[str]:
644
+ with open(dockercompose_file, 'r', encoding="utf-8") as f:
645
+ compose_data = yaml.safe_load(f)
646
+ services = compose_data.get('services', {})
647
+ result = list(services.keys())
648
+ return result
@@ -0,0 +1,41 @@
1
+ import psutil
2
+ from .ScriptCollectionCore import ScriptCollectionCore
3
+
4
+ # runs multiple processes in parallel and terminate all if at least one is terminated
5
+
6
+
7
+ class ProcessStartInformation:
8
+ workingdirectory: str = None
9
+ program: str = None
10
+ arguments: str = None
11
+
12
+ def __init__(self, workingdirectory: str, program: str, arguments: str):
13
+ self.workingdirectory = workingdirectory
14
+ self.program = program
15
+ self.arguments = arguments
16
+
17
+
18
+ class ProcessesRunner:
19
+ sc: ScriptCollectionCore
20
+ processes: list[ProcessStartInformation]
21
+
22
+ def __init__(self, processes: list[ProcessStartInformation]):
23
+ self.sc = ScriptCollectionCore()
24
+ self.processes = processes
25
+
26
+ def run(self):
27
+ pids: list[int] = list[int]()
28
+ for processstartinfo in self.processes:
29
+ pids.append(self.sc.run_program_async(processstartinfo.program, processstartinfo.argumentss, processstartinfo.workingdirectory))
30
+ enabled = True
31
+ while enabled:
32
+ for pid in pids:
33
+ if not psutil.pid_exists(pid):
34
+ enabled = False
35
+ # one program terminate so exit and terminate all now
36
+ processes = psutil.process_iter()
37
+ for pid in pids:
38
+ if psutil.pid_exists(pid):
39
+ for proc in processes:
40
+ if proc.pid == pid:
41
+ proc.kill()