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.
@@ -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
- "oneOf": [
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
- "oneOf": [
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
@@ -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
- content = f.readlines()
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
- expr = set_export.group(2)
234
- if expr.startswith('"'):
235
- expr = expr[1:-1]
236
- key, _, value = expr.partition('=')
237
- else:
238
- key, _, value = line.partition('=')
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
- - attach: a function copying a remote file to a local path
315
- - put: a function copying a local file to a remote environment
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
- details = {}
343
- if args:
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=details.get('name')
371
+ metadata, remote, separator, is_artefact, name=params.get('name')
354
372
  )
355
- details['uuid'] = uuid
373
+ params['uuid'] = uuid
356
374
  _get(remote, attachment_url)
357
- attachments_metadata[attachment_url] = details
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
- working_directory = core.join_path(
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.dev1200
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=JYQXTyvKTcU2Blu6AUzR0FfEHSqSUrqldqLDpSf_K_k,22520
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=Etws3d5Ph6dYjQnBqNefLVFnDTYajcKFEbgXFSdD-Ks,3863
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=kG-oXCVoHb0b72aYK7HR1OEFJrIKfMtWREfffqDFpYU,3875
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=Whbt1nClU2QjKi-3DQE0rHa9yyFkdrLLJ-htyltg6qE,21385
59
+ opentf/toolkit/channels.py,sha256=kXgygE4mBw1AihdwWWlONMvN4yhbBmML4ytxb1Bgskg,23384
60
60
  opentf/toolkit/core.py,sha256=cscUkwdwvLkerqMRL05dgtKJ42QbBQQc28kRBiyZM9o,9883
61
- opentf_toolkit_nightly-0.59.0.dev1200.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
62
- opentf_toolkit_nightly-0.59.0.dev1200.dist-info/METADATA,sha256=JZPw_iSlLF4A2gYG4WyWhlHqZU_CmoLf6--KyuvQsII,1940
63
- opentf_toolkit_nightly-0.59.0.dev1200.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
64
- opentf_toolkit_nightly-0.59.0.dev1200.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
65
- opentf_toolkit_nightly-0.59.0.dev1200.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5