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.
- ScriptCollection/AnionBuildPlatform.py +206 -0
- ScriptCollection/{UpdateCertificates.py → CertificateUpdater.py} +149 -128
- ScriptCollection/Executables.py +868 -292
- ScriptCollection/GeneralUtilities.py +609 -107
- ScriptCollection/ImageUpdater.py +648 -0
- ScriptCollection/ProcessesRunner.py +41 -0
- ScriptCollection/ProgramRunnerBase.py +47 -42
- ScriptCollection/ProgramRunnerMock.py +2 -0
- ScriptCollection/ProgramRunnerPopen.py +57 -50
- ScriptCollection/ProgramRunnerSudo.py +108 -0
- ScriptCollection/SCLog.py +115 -0
- ScriptCollection/ScriptCollectionCore.py +2541 -1383
- ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py +95 -0
- ScriptCollection/TFCPS/Docker/__init__.py +0 -0
- ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py +8 -0
- ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py +6 -0
- ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py +7 -0
- ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py +485 -0
- ScriptCollection/TFCPS/DotNet/__init__.py +0 -0
- ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py +130 -0
- ScriptCollection/TFCPS/Flutter/__init__.py +0 -0
- ScriptCollection/TFCPS/Go/TFCPS_CodeUnitSpecific_Go.py +74 -0
- ScriptCollection/TFCPS/Go/__init__.py +0 -0
- ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py +131 -0
- ScriptCollection/TFCPS/NodeJS/__init__.py +0 -0
- ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py +227 -0
- ScriptCollection/TFCPS/Python/__init__.py +0 -0
- ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py +418 -0
- ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py +128 -0
- ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py +136 -0
- ScriptCollection/TFCPS/TFCPS_CreateRelease.py +95 -0
- ScriptCollection/TFCPS/TFCPS_Generic.py +43 -0
- ScriptCollection/TFCPS/TFCPS_MergeToMain.py +122 -0
- ScriptCollection/TFCPS/TFCPS_MergeToStable.py +350 -0
- ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py +47 -0
- ScriptCollection/TFCPS/TFCPS_Tools_General.py +1356 -0
- ScriptCollection/TFCPS/__init__.py +0 -0
- {ScriptCollection-3.3.23.dist-info → scriptcollection-4.0.78.dist-info}/METADATA +26 -21
- scriptcollection-4.0.78.dist-info/RECORD +43 -0
- {ScriptCollection-3.3.23.dist-info → scriptcollection-4.0.78.dist-info}/WHEEL +1 -1
- scriptcollection-4.0.78.dist-info/entry_points.txt +64 -0
- ScriptCollection/Hardening.py +0 -59
- ScriptCollection/ProgramRunnerEpew.py +0 -122
- ScriptCollection/TasksForCommonProjectStructure.py +0 -1170
- ScriptCollection-3.3.23.dist-info/RECORD +0 -15
- ScriptCollection-3.3.23.dist-info/entry_points.txt +0 -24
- {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()
|