opentf-toolkit-nightly 0.59.0.dev1200__py3-none-any.whl → 0.59.0.dev1211__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.
- opentf/commons/__init__.py +2 -0
- opentf/schemas/opentestfactory.org/v1/ExecutionResult.json +1 -17
- opentf/schemas/opentestfactory.org/v1alpha1/ExecutionResult.json +1 -17
- opentf/toolkit/channels.py +80 -32
- {opentf_toolkit_nightly-0.59.0.dev1200.dist-info → opentf_toolkit_nightly-0.59.0.dev1211.dist-info}/METADATA +1 -1
- {opentf_toolkit_nightly-0.59.0.dev1200.dist-info → opentf_toolkit_nightly-0.59.0.dev1211.dist-info}/RECORD +9 -9
- {opentf_toolkit_nightly-0.59.0.dev1200.dist-info → opentf_toolkit_nightly-0.59.0.dev1211.dist-info}/WHEEL +1 -1
- {opentf_toolkit_nightly-0.59.0.dev1200.dist-info → opentf_toolkit_nightly-0.59.0.dev1211.dist-info}/LICENSE +0 -0
- {opentf_toolkit_nightly-0.59.0.dev1200.dist-info → opentf_toolkit_nightly-0.59.0.dev1211.dist-info}/top_level.txt +0 -0
opentf/commons/__init__.py
CHANGED
|
@@ -68,6 +68,7 @@ REASON_STATUS = {
|
|
|
68
68
|
'Created': 201,
|
|
69
69
|
'Accepted': 202,
|
|
70
70
|
'NoContent': 204,
|
|
71
|
+
'PartialContent': 206,
|
|
71
72
|
'BadRequest': 400,
|
|
72
73
|
'Unauthorized': 401,
|
|
73
74
|
'PaymentRequired': 402,
|
|
@@ -75,6 +76,7 @@ REASON_STATUS = {
|
|
|
75
76
|
'NotFound': 404,
|
|
76
77
|
'AlreadyExists': 409,
|
|
77
78
|
'Conflict': 409,
|
|
79
|
+
'RangeNotSatisfiable': 416,
|
|
78
80
|
'Invalid': 422,
|
|
79
81
|
'TooManyRequests': 429, # https://datatracker.ietf.org/doc/html/rfc6585
|
|
80
82
|
'InternalError': 500,
|
|
@@ -101,23 +101,7 @@
|
|
|
101
101
|
"type": "object",
|
|
102
102
|
"patternProperties": {
|
|
103
103
|
"^[a-zA-Z0-9_]+$": {
|
|
104
|
-
"
|
|
105
|
-
{
|
|
106
|
-
"type": "string"
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
"type": "object",
|
|
110
|
-
"properties": {
|
|
111
|
-
"value": {
|
|
112
|
-
"type": "string"
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
"required": [
|
|
116
|
-
"value"
|
|
117
|
-
],
|
|
118
|
-
"additionalProperties": false
|
|
119
|
-
}
|
|
120
|
-
]
|
|
104
|
+
"type": "string"
|
|
121
105
|
}
|
|
122
106
|
},
|
|
123
107
|
"minProperties": 1
|
|
@@ -101,23 +101,7 @@
|
|
|
101
101
|
"type": "object",
|
|
102
102
|
"patternProperties": {
|
|
103
103
|
"^[a-zA-Z0-9_]+$": {
|
|
104
|
-
"
|
|
105
|
-
{
|
|
106
|
-
"type": "string"
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
"type": "object",
|
|
110
|
-
"properties": {
|
|
111
|
-
"value": {
|
|
112
|
-
"type": "string"
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
"required": [
|
|
116
|
-
"value"
|
|
117
|
-
],
|
|
118
|
-
"additionalProperties": false
|
|
119
|
-
}
|
|
120
|
-
]
|
|
104
|
+
"type": "string"
|
|
121
105
|
}
|
|
122
106
|
},
|
|
123
107
|
"minProperties": 1
|
opentf/toolkit/channels.py
CHANGED
|
@@ -19,6 +19,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
|
19
19
|
|
|
20
20
|
from shlex import quote
|
|
21
21
|
|
|
22
|
+
import fnmatch
|
|
22
23
|
import ntpath
|
|
23
24
|
import os
|
|
24
25
|
import re
|
|
@@ -36,6 +37,7 @@ from opentf.toolkit import core
|
|
|
36
37
|
SETOUTPUT_COMMAND = re.compile(r'^::set-output\s+name=([a-zA-Z_][a-zA-Z0-9_-]*)::(.*)$')
|
|
37
38
|
ATTACH_COMMAND = re.compile(r'^::attach(\s+.*?)?::(.*?)\s*$')
|
|
38
39
|
UPLOAD_COMMAND = re.compile(r'^::upload(\s+.*?)?::(.*?)\s*$')
|
|
40
|
+
DOWNLOAD_COMMAND = re.compile(r'^::download(\s+.*?)?::(.*?)\s*$')
|
|
39
41
|
DEBUG_COMMAND = re.compile(r'^::debug::(.*)$')
|
|
40
42
|
WARNING_COMMAND = re.compile(r'^::warning(\s+(.*)+)?::(.*)$')
|
|
41
43
|
ERROR_COMMAND = re.compile(r'^::error(\s+(.*)+)?::(.*)$')
|
|
@@ -127,8 +129,10 @@ REMOVE_WORKSPACE = 2
|
|
|
127
129
|
MOVE_TO_WORKSPACE = 3
|
|
128
130
|
|
|
129
131
|
HOOKS_ANNOTATIONS = 'opentestfactory.org/hooks'
|
|
132
|
+
|
|
130
133
|
OPENTF_VARIABLES_TYPE = 'application/vnd.opentestfactory.opentf-variables'
|
|
131
134
|
OPENTF_VARIABLES_REGEX = re.compile(r'^(export|set)\s(\"?.+)$')
|
|
135
|
+
OPENTF_VARIABLES_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_]+$')
|
|
132
136
|
|
|
133
137
|
## os helpers
|
|
134
138
|
|
|
@@ -195,6 +199,18 @@ def _make_attachment_url(
|
|
|
195
199
|
return url, uuid
|
|
196
200
|
|
|
197
201
|
|
|
202
|
+
def _get_cmd_params(args: str, logs: List[str]):
|
|
203
|
+
details = {}
|
|
204
|
+
if args:
|
|
205
|
+
for parameter in args.strip().split(','):
|
|
206
|
+
if '=' not in parameter:
|
|
207
|
+
logs.append(f'ERROR,Invalid workflow command parameter: {parameter}.')
|
|
208
|
+
return 2
|
|
209
|
+
key, _, value = parameter.strip().partition('=')
|
|
210
|
+
details[key] = value
|
|
211
|
+
return details
|
|
212
|
+
|
|
213
|
+
|
|
198
214
|
## masks helpers
|
|
199
215
|
|
|
200
216
|
|
|
@@ -221,26 +237,29 @@ def _as_log(line: str, jobstate: JobState):
|
|
|
221
237
|
return mask(line, jobstate).rstrip()
|
|
222
238
|
|
|
223
239
|
|
|
224
|
-
def _get_opentf_variables(path: str):
|
|
240
|
+
def _get_opentf_variables(path: str) -> Dict[str, str]:
|
|
225
241
|
variables = {}
|
|
226
242
|
with open(path, 'r') as f:
|
|
227
|
-
|
|
228
|
-
for line in content:
|
|
243
|
+
for line in f.readlines():
|
|
229
244
|
if '=' not in line:
|
|
230
245
|
continue
|
|
231
246
|
line = line.strip()
|
|
232
247
|
if set_export := OPENTF_VARIABLES_REGEX.match(line):
|
|
233
|
-
|
|
234
|
-
if
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
key
|
|
239
|
-
variables[key] = value
|
|
248
|
+
line = set_export.group(2)
|
|
249
|
+
if line.startswith('"'):
|
|
250
|
+
line = line[1:-1]
|
|
251
|
+
key, _, value = line.partition('=')
|
|
252
|
+
if OPENTF_VARIABLES_NAME_REGEX.match(key):
|
|
253
|
+
variables[key] = value
|
|
240
254
|
return variables
|
|
241
255
|
|
|
242
256
|
|
|
243
|
-
def process_opentf_variables(result: Dict[str, Any]):
|
|
257
|
+
def process_opentf_variables(result: Dict[str, Any]) -> None:
|
|
258
|
+
"""Process OPENTF_VARIABLES attachment if available.
|
|
259
|
+
|
|
260
|
+
If OPENTF_VARIABLES is in the attachments, move its content to
|
|
261
|
+
the variables field of the result.
|
|
262
|
+
"""
|
|
244
263
|
if attachments := result['metadata'].get('attachments'):
|
|
245
264
|
variables = {}
|
|
246
265
|
for path, data in attachments.copy().items():
|
|
@@ -288,6 +307,7 @@ def process_upload(result: Dict[str, Any]):
|
|
|
288
307
|
'name': result['metadata'].get('step_id'),
|
|
289
308
|
'namespace': result['metadata']['namespace'],
|
|
290
309
|
'workflow_id': result['metadata']['workflow_id'],
|
|
310
|
+
'job_id': result['metadata']['job_id'],
|
|
291
311
|
}
|
|
292
312
|
return make_event(WORKFLOWRESULT, metadata=metadata, attachments=upload)
|
|
293
313
|
|
|
@@ -311,8 +331,8 @@ def process_output(
|
|
|
311
331
|
- stderr: a list of strings
|
|
312
332
|
- jobstate: a JobState object
|
|
313
333
|
- context: a dictionary, channelhandler context
|
|
314
|
-
-
|
|
315
|
-
-
|
|
334
|
+
- _get: a function copying a remote file to a local path
|
|
335
|
+
- _put: a function copying a local file to a remote environment
|
|
316
336
|
|
|
317
337
|
# Returned value
|
|
318
338
|
|
|
@@ -335,26 +355,24 @@ def process_output(
|
|
|
335
355
|
May raise exceptions.
|
|
336
356
|
"""
|
|
337
357
|
|
|
358
|
+
def _get_targeted_path(remote_path: str):
|
|
359
|
+
working_directory = core.join_path(
|
|
360
|
+
metadata['job_id'], event.get('working-directory'), is_windows
|
|
361
|
+
)
|
|
362
|
+
return core.join_path(working_directory, remote_path, is_windows)
|
|
363
|
+
|
|
338
364
|
def _attach(remote: str, args: str, is_artefact: bool = False):
|
|
339
365
|
if is_windows:
|
|
340
366
|
remote = ntpath.normpath(remote)
|
|
341
367
|
try:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
for parameter in args.strip().split(','):
|
|
345
|
-
if '=' not in parameter:
|
|
346
|
-
logs.append(
|
|
347
|
-
f'ERROR,Invalid workflow command parameter: {parameter}.'
|
|
348
|
-
)
|
|
349
|
-
return 2
|
|
350
|
-
key, _, value = parameter.strip().partition('=')
|
|
351
|
-
details[key] = value
|
|
368
|
+
if (params := _get_cmd_params(args, logs)) == 2:
|
|
369
|
+
return 2
|
|
352
370
|
attachment_url, uuid = _make_attachment_url(
|
|
353
|
-
metadata, remote, separator, is_artefact, name=
|
|
371
|
+
metadata, remote, separator, is_artefact, name=params.get('name')
|
|
354
372
|
)
|
|
355
|
-
|
|
373
|
+
params['uuid'] = uuid
|
|
356
374
|
_get(remote, attachment_url)
|
|
357
|
-
attachments_metadata[attachment_url] =
|
|
375
|
+
attachments_metadata[attachment_url] = params
|
|
358
376
|
attachments.append(attachment_url)
|
|
359
377
|
return resp
|
|
360
378
|
except Exception as err:
|
|
@@ -362,12 +380,7 @@ def process_output(
|
|
|
362
380
|
return 2
|
|
363
381
|
|
|
364
382
|
def _putfile(remote_path: str, data: str):
|
|
365
|
-
|
|
366
|
-
metadata['job_id'], event.get('working-directory'), is_windows
|
|
367
|
-
)
|
|
368
|
-
targeted_remote_path = core.join_path(
|
|
369
|
-
working_directory, remote_path, is_windows
|
|
370
|
-
)
|
|
383
|
+
targeted_remote_path = _get_targeted_path(remote_path)
|
|
371
384
|
try:
|
|
372
385
|
file_ = f'/tmp/in_{metadata["workflow_id"]}_{data}'
|
|
373
386
|
if not os.path.exists(file_):
|
|
@@ -381,6 +394,36 @@ def process_output(
|
|
|
381
394
|
)
|
|
382
395
|
return 2
|
|
383
396
|
|
|
397
|
+
def _download(remote_path: str, args: str):
|
|
398
|
+
if not (artifacts := event['metadata'].get('artifacts')):
|
|
399
|
+
logs.append('ERROR,No artifacts available at workflow level.')
|
|
400
|
+
return 2
|
|
401
|
+
try:
|
|
402
|
+
targeted_remote_path = _get_targeted_path(remote_path)
|
|
403
|
+
if (params := _get_cmd_params(args, logs)) == 2:
|
|
404
|
+
return 2
|
|
405
|
+
filename, pattern = params.get('file'), params.get('pattern')
|
|
406
|
+
for artifact in artifacts:
|
|
407
|
+
artifact_name = artifact.split('_')[-1]
|
|
408
|
+
if filename and filename == artifact_name:
|
|
409
|
+
if not remote_path:
|
|
410
|
+
targeted_remote_path = core.join_path(
|
|
411
|
+
targeted_remote_path, artifact_name, is_windows
|
|
412
|
+
)
|
|
413
|
+
_put(targeted_remote_path, artifact)
|
|
414
|
+
continue
|
|
415
|
+
if pattern and fnmatch.fnmatch(artifact_name, pattern):
|
|
416
|
+
pattern_path = core.join_path(
|
|
417
|
+
targeted_remote_path, artifact_name, is_windows
|
|
418
|
+
)
|
|
419
|
+
_put(pattern_path, artifact)
|
|
420
|
+
return resp
|
|
421
|
+
except Exception as err:
|
|
422
|
+
logs.append(
|
|
423
|
+
f'ERROR,Could not send artifacts to remote path {remote_path}: {err}.'
|
|
424
|
+
)
|
|
425
|
+
return 2
|
|
426
|
+
|
|
384
427
|
metadata: Dict[str, Any] = event['metadata']
|
|
385
428
|
is_windows: bool = metadata['channel_os'] == 'windows'
|
|
386
429
|
separator = '\\' if is_windows else '/'
|
|
@@ -402,6 +445,8 @@ def process_output(
|
|
|
402
445
|
elif wcmd := UPLOAD_COMMAND.match(line):
|
|
403
446
|
has_artefacts = True
|
|
404
447
|
resp = _attach(wcmd.group(2), wcmd.group(1), is_artefact=True)
|
|
448
|
+
elif wcmd := DOWNLOAD_COMMAND.match(line):
|
|
449
|
+
resp = _download(wcmd.group(2), wcmd.group(1))
|
|
405
450
|
elif wcmd := PUT_FILE_COMMAND.match(line):
|
|
406
451
|
resp = _putfile(wcmd.group(2), wcmd.group(1))
|
|
407
452
|
elif wcmd := SETOUTPUT_COMMAND.match(line):
|
|
@@ -416,6 +461,9 @@ def process_output(
|
|
|
416
461
|
for line in stderr:
|
|
417
462
|
logs.append(mask(line, jobstate).rstrip())
|
|
418
463
|
|
|
464
|
+
if metadata.get('artifacts'):
|
|
465
|
+
del metadata['artifacts']
|
|
466
|
+
|
|
419
467
|
result = make_event(EXECUTIONRESULT, metadata=metadata, status=resp)
|
|
420
468
|
|
|
421
469
|
if outputs:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opentf-toolkit-nightly
|
|
3
|
-
Version: 0.59.0.
|
|
3
|
+
Version: 0.59.0.dev1211
|
|
4
4
|
Summary: OpenTestFactory Orchestrator Toolkit
|
|
5
5
|
Home-page: https://gitlab.com/henixdevelopment/open-source/opentestfactory/python-toolkit
|
|
6
6
|
Author: Martin Lafaix
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
opentf/commons/__init__.py,sha256=
|
|
1
|
+
opentf/commons/__init__.py,sha256=JLif958eOnOeJSQ6bLF-Dpr_aFJ3JtxHrjvUe_KbzEc,22579
|
|
2
2
|
opentf/commons/auth.py,sha256=bM2Z3kxm2Wku1lKXaRAIg37LHvXWAXIZIqjplDfN2P8,15899
|
|
3
3
|
opentf/commons/config.py,sha256=dyus4K5Zdmcftc3Y9Z1YRkzA1KwiRLHoeAlg2_A49QM,7876
|
|
4
4
|
opentf/commons/datasources.py,sha256=GSbjrYnZQup2B3r7T7l3C_o6R2jS13nQiu6dRitoenk,26194
|
|
@@ -9,7 +9,7 @@ opentf/commons/selectors.py,sha256=DEpLgRAr5HXSpSYI4liXP2hLUTvOSexFa9Vfa1xIQTk,7
|
|
|
9
9
|
opentf/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
opentf/schemas/abac.opentestfactory.org/v1alpha1/Policy.json,sha256=JXsfNAPSEYggeyaDutSQBeG38o4Bmcr70dPLWWeqIh8,2105
|
|
11
11
|
opentf/schemas/opentestfactory.org/v1/ExecutionCommand.json,sha256=UtmAlTaYdPSZDeQnx-ocX8IonyEPWoNmgDkHwQwQxWE,4126
|
|
12
|
-
opentf/schemas/opentestfactory.org/v1/ExecutionResult.json,sha256=
|
|
12
|
+
opentf/schemas/opentestfactory.org/v1/ExecutionResult.json,sha256=u0n-WYXNX9d0cEyu2D4tegU35k2Gf3eA6PGs9Uz4QDg,3275
|
|
13
13
|
opentf/schemas/opentestfactory.org/v1/GeneratorResult.json,sha256=sOwieyDWi6UZR7X29R9IjOR87ruSRQ4U6CM2_yT81Zk,16607
|
|
14
14
|
opentf/schemas/opentestfactory.org/v1/ProviderCommand.json,sha256=EU4kvEKxlqpH2IkLZ1HdBealuG6C0YzPkAtI7dNrfHg,4427
|
|
15
15
|
opentf/schemas/opentestfactory.org/v1/ProviderResult.json,sha256=Ej4zhCE3rCqCGKcaeAoIHwSJTV_7fw-rAxhJ52qA-Gs,9641
|
|
@@ -24,7 +24,7 @@ opentf/schemas/opentestfactory.org/v1alpha1/ChannelHandlerHooks.json,sha256=6K6m
|
|
|
24
24
|
opentf/schemas/opentestfactory.org/v1alpha1/EventBusConfig.json,sha256=2aIYtA07qRoauKNy-MH25Kzg1l1Q1fjY9_4YIvlyYgw,2174
|
|
25
25
|
opentf/schemas/opentestfactory.org/v1alpha1/ExecutionCommand.json,sha256=Tsqy0imNqO6Qg6B_Yw-4OeNer3xpURv-ZDaYUoZ-l1c,2702
|
|
26
26
|
opentf/schemas/opentestfactory.org/v1alpha1/ExecutionError.json,sha256=tz8ZggvjSkP2S9ln77Js03LkTnMCTuRVkC1Z3w8uI8k,1347
|
|
27
|
-
opentf/schemas/opentestfactory.org/v1alpha1/ExecutionResult.json,sha256=
|
|
27
|
+
opentf/schemas/opentestfactory.org/v1alpha1/ExecutionResult.json,sha256=UeWc4TfRY3G1CnMapFxXWRunaXzZdxOIle3DxURSf-A,3287
|
|
28
28
|
opentf/schemas/opentestfactory.org/v1alpha1/GeneratorCommand.json,sha256=uxbqDhP4newgz-85TnGKbchx448QEQ8WB5PXpcJy2ME,1754
|
|
29
29
|
opentf/schemas/opentestfactory.org/v1alpha1/GeneratorResult.json,sha256=LkHLGt2uam1Q5Ux0zP_O9oFgxBMCjD3Th3BsfsXxd1g,6633
|
|
30
30
|
opentf/schemas/opentestfactory.org/v1alpha1/InsightCollector.json,sha256=emE0My2cYBRnfA8L3_eY8yOXbSErV4TlwmQbRCgT4O8,16770
|
|
@@ -56,10 +56,10 @@ opentf/schemas/opentestfactory.org/v1beta2/ServiceConfig.json,sha256=rEvK2YWL5lG
|
|
|
56
56
|
opentf/scripts/launch_java_service.sh,sha256=S0jAaCuv2sZy0Gf2NGBuPX-eD531rcM-b0fNyhmzSjw,2423
|
|
57
57
|
opentf/scripts/startup.py,sha256=sggwEpMx7PTaSgYzs-2uCF5YZzpsncMyTlfF_G60CrE,21518
|
|
58
58
|
opentf/toolkit/__init__.py,sha256=mYeJPZ92ulbTBItqEsZgF4nnuRh6G19QPY3Jxc92ifc,23028
|
|
59
|
-
opentf/toolkit/channels.py,sha256=
|
|
59
|
+
opentf/toolkit/channels.py,sha256=kXgygE4mBw1AihdwWWlONMvN4yhbBmML4ytxb1Bgskg,23384
|
|
60
60
|
opentf/toolkit/core.py,sha256=cscUkwdwvLkerqMRL05dgtKJ42QbBQQc28kRBiyZM9o,9883
|
|
61
|
-
opentf_toolkit_nightly-0.59.0.
|
|
62
|
-
opentf_toolkit_nightly-0.59.0.
|
|
63
|
-
opentf_toolkit_nightly-0.59.0.
|
|
64
|
-
opentf_toolkit_nightly-0.59.0.
|
|
65
|
-
opentf_toolkit_nightly-0.59.0.
|
|
61
|
+
opentf_toolkit_nightly-0.59.0.dev1211.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
62
|
+
opentf_toolkit_nightly-0.59.0.dev1211.dist-info/METADATA,sha256=Bhy1y4tVEqY9xVWE2JeEh192VHscQWYd-3OgaZGmNbg,1940
|
|
63
|
+
opentf_toolkit_nightly-0.59.0.dev1211.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
|
64
|
+
opentf_toolkit_nightly-0.59.0.dev1211.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
|
|
65
|
+
opentf_toolkit_nightly-0.59.0.dev1211.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|