opentf-toolkit-nightly 0.57.0.dev1039__py3-none-any.whl → 0.57.0.dev1051__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 -2
- opentf/commons/pubsub.py +48 -0
- opentf/toolkit/__init__.py +37 -9
- {opentf_toolkit_nightly-0.57.0.dev1039.dist-info → opentf_toolkit_nightly-0.57.0.dev1051.dist-info}/METADATA +1 -1
- {opentf_toolkit_nightly-0.57.0.dev1039.dist-info → opentf_toolkit_nightly-0.57.0.dev1051.dist-info}/RECORD +8 -8
- {opentf_toolkit_nightly-0.57.0.dev1039.dist-info → opentf_toolkit_nightly-0.57.0.dev1051.dist-info}/LICENSE +0 -0
- {opentf_toolkit_nightly-0.57.0.dev1039.dist-info → opentf_toolkit_nightly-0.57.0.dev1051.dist-info}/WHEEL +0 -0
- {opentf_toolkit_nightly-0.57.0.dev1039.dist-info → opentf_toolkit_nightly-0.57.0.dev1051.dist-info}/top_level.txt +0 -0
opentf/commons/__init__.py
CHANGED
|
@@ -43,7 +43,7 @@ from .auth import (
|
|
|
43
43
|
get_user_accessible_namespaces,
|
|
44
44
|
is_user_authorized,
|
|
45
45
|
)
|
|
46
|
-
from .pubsub import make_event, publish, subscribe, unsubscribe
|
|
46
|
+
from .pubsub import make_dispatchqueue, make_event, publish, subscribe, unsubscribe
|
|
47
47
|
from .schemas import *
|
|
48
48
|
|
|
49
49
|
|
|
@@ -550,7 +550,7 @@ def run_app(app: Flask) -> None:
|
|
|
550
550
|
app.logger.info(f'Serving on http://{context["host"]}:{context["port"]}')
|
|
551
551
|
_app = app
|
|
552
552
|
|
|
553
|
-
serve(_app, host=context['host'], port=context['port'])
|
|
553
|
+
serve(_app, host=context['host'], port=context['port'], server_name=app.name)
|
|
554
554
|
|
|
555
555
|
|
|
556
556
|
########################################################################
|
opentf/commons/pubsub.py
CHANGED
|
@@ -17,8 +17,11 @@
|
|
|
17
17
|
from typing import Any, Dict, Optional
|
|
18
18
|
|
|
19
19
|
import sys
|
|
20
|
+
import threading
|
|
20
21
|
|
|
21
22
|
from datetime import datetime
|
|
23
|
+
from queue import Queue
|
|
24
|
+
from time import sleep
|
|
22
25
|
|
|
23
26
|
|
|
24
27
|
from requests import delete, post, Response
|
|
@@ -105,6 +108,51 @@ def _do(req, path: str, eventbus: Dict[str, Any], **kwargs) -> Response:
|
|
|
105
108
|
)
|
|
106
109
|
|
|
107
110
|
|
|
111
|
+
def _dispatch_events(dispatch_queue: Queue, app) -> None:
|
|
112
|
+
"""Async event dispatch thread handler."""
|
|
113
|
+
delay = 0
|
|
114
|
+
while True:
|
|
115
|
+
try:
|
|
116
|
+
publication = dispatch_queue.get()
|
|
117
|
+
try:
|
|
118
|
+
publish(publication, app.config['CONTEXT'])
|
|
119
|
+
delay = 0
|
|
120
|
+
except Exception:
|
|
121
|
+
dispatch_queue.put(publication)
|
|
122
|
+
delay = min(2 * delay + 0.2, 60)
|
|
123
|
+
sleep(delay)
|
|
124
|
+
except Exception as err:
|
|
125
|
+
app.logger.error(f'Internal error while dispatching publication: {err}.')
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def make_dispatchqueue(app) -> Queue:
|
|
129
|
+
"""Make an asynchronous dispatch queue.
|
|
130
|
+
|
|
131
|
+
Handles publication failures by waiting for an increasing delay and
|
|
132
|
+
re-attempting publication.
|
|
133
|
+
|
|
134
|
+
The delay is at most 60 seconds.
|
|
135
|
+
|
|
136
|
+
# Required parameters
|
|
137
|
+
|
|
138
|
+
- app: a flask app
|
|
139
|
+
|
|
140
|
+
# Returned value
|
|
141
|
+
|
|
142
|
+
A _queue_. Events pushed to this queue will be published.
|
|
143
|
+
"""
|
|
144
|
+
queue = Queue()
|
|
145
|
+
app.logger.debug('Starting events dispatch thread.')
|
|
146
|
+
try:
|
|
147
|
+
threading.Thread(
|
|
148
|
+
target=_dispatch_events, args=[queue, app], daemon=True
|
|
149
|
+
).start()
|
|
150
|
+
return queue
|
|
151
|
+
except Exception as err:
|
|
152
|
+
app.logger.error('Cound not start events dispatch thread: %s.', str(err))
|
|
153
|
+
sys.exit(2)
|
|
154
|
+
|
|
155
|
+
|
|
108
156
|
def subscribe(
|
|
109
157
|
kind: Optional[str],
|
|
110
158
|
target: str,
|
opentf/toolkit/__init__.py
CHANGED
|
@@ -296,22 +296,26 @@ def _dispatch_providercommand(plugin, handler: Handler, body: Dict[str, Any]) ->
|
|
|
296
296
|
def _dispatch_executioncommand(_, handler: Handler, body: Dict[str, Any]):
|
|
297
297
|
"""Channel plugin dispatcher."""
|
|
298
298
|
try:
|
|
299
|
-
|
|
299
|
+
handler(body)
|
|
300
300
|
except Exception as err:
|
|
301
|
-
|
|
302
|
-
core.publish_error(msg)
|
|
303
|
-
return make_status_response('InternalError', msg)
|
|
301
|
+
core.publish_error(f'Unexpected execution error: {err}.')
|
|
304
302
|
|
|
305
303
|
|
|
306
|
-
def _dispatch_generatorcommand(
|
|
304
|
+
def _dispatch_generatorcommand(plugin, handler: Handler, body: Dict[str, Any]):
|
|
307
305
|
"""Generator plugin dispatcher."""
|
|
308
306
|
try:
|
|
307
|
+
labels = body['metadata'].get('labels', {})
|
|
308
|
+
plugin.logger.debug(
|
|
309
|
+
'Calling generator %s (%s/%s@%s).',
|
|
310
|
+
handler.__name__,
|
|
311
|
+
labels.get('opentestfactory.org/categoryPrefix', '_'),
|
|
312
|
+
labels.get('opentestfactory.org/category', '_'),
|
|
313
|
+
labels.get('opentestfactory.org/categoryVersion', '_'),
|
|
314
|
+
)
|
|
309
315
|
inputs: Dict[str, Any] = body.get('with', {})
|
|
310
316
|
core.publish_generatorresult(handler(inputs))
|
|
311
317
|
except Exception as err:
|
|
312
|
-
|
|
313
|
-
core.publish_error(msg)
|
|
314
|
-
return make_status_response('InternalError', msg)
|
|
318
|
+
core.publish_error(f'Unexpected execution error: {err}.')
|
|
315
319
|
|
|
316
320
|
|
|
317
321
|
########################################################################
|
|
@@ -544,6 +548,7 @@ def make_plugin(
|
|
|
544
548
|
descriptor=None,
|
|
545
549
|
schema=None,
|
|
546
550
|
configfile=None,
|
|
551
|
+
args: Optional[Any] = None,
|
|
547
552
|
):
|
|
548
553
|
"""Create and return a new plugin service.
|
|
549
554
|
|
|
@@ -559,6 +564,11 @@ def make_plugin(
|
|
|
559
564
|
- Add publication handler
|
|
560
565
|
- Create service (not started)
|
|
561
566
|
|
|
567
|
+
Some 'optional' parameters are required for some publin types:
|
|
568
|
+
|
|
569
|
+
`args` is required for channel handlers. It must be a list of one
|
|
570
|
+
element that implements the `__contains__` interface.
|
|
571
|
+
|
|
562
572
|
# Required parameters
|
|
563
573
|
|
|
564
574
|
- name: a string
|
|
@@ -572,6 +582,7 @@ def make_plugin(
|
|
|
572
582
|
by default)
|
|
573
583
|
- schema: a string or None (None by default)
|
|
574
584
|
- configfile: a string or None (None by default)
|
|
585
|
+
- args: a list or None (None by default)
|
|
575
586
|
|
|
576
587
|
# Raised exceptions
|
|
577
588
|
|
|
@@ -589,6 +600,19 @@ def make_plugin(
|
|
|
589
600
|
except Exception as err:
|
|
590
601
|
return make_status_response('BadRequest', f'Could not parse body: {err}.')
|
|
591
602
|
|
|
603
|
+
if channel:
|
|
604
|
+
try:
|
|
605
|
+
channel_id = body['metadata'].get('channel_id')
|
|
606
|
+
if channel_id and channel_id not in args[0]:
|
|
607
|
+
return make_status_response(
|
|
608
|
+
'OK', 'Job not handled by this channel plugin.'
|
|
609
|
+
)
|
|
610
|
+
except KeyError:
|
|
611
|
+
return make_status_response(
|
|
612
|
+
'BadRequest',
|
|
613
|
+
f'Not a valid {kind} request: Missing metadata section',
|
|
614
|
+
)
|
|
615
|
+
|
|
592
616
|
valid, extra = validate_schema(kind, body)
|
|
593
617
|
if not valid:
|
|
594
618
|
return make_status_response(
|
|
@@ -608,7 +632,7 @@ def make_plugin(
|
|
|
608
632
|
elif provider:
|
|
609
633
|
_dispatch_providercommand(plugin, provider, body)
|
|
610
634
|
elif channel:
|
|
611
|
-
|
|
635
|
+
_dispatch_executioncommand(plugin, channel, body)
|
|
612
636
|
elif generator:
|
|
613
637
|
_dispatch_generatorcommand(plugin, generator, body)
|
|
614
638
|
else:
|
|
@@ -624,6 +648,10 @@ def make_plugin(
|
|
|
624
648
|
raise ValueError(
|
|
625
649
|
"'descriptor', if specified, must be a dictionary or a list of dictionaries."
|
|
626
650
|
)
|
|
651
|
+
if channel and (not isinstance(args, list) or len(args) != 1):
|
|
652
|
+
raise ValueError(
|
|
653
|
+
"'args' is required for channel plugins and must be a list of one element."
|
|
654
|
+
)
|
|
627
655
|
|
|
628
656
|
kind = (
|
|
629
657
|
EXECUTIONCOMMAND
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opentf-toolkit-nightly
|
|
3
|
-
Version: 0.57.0.
|
|
3
|
+
Version: 0.57.0.dev1051
|
|
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,9 +1,9 @@
|
|
|
1
|
-
opentf/commons/__init__.py,sha256=
|
|
1
|
+
opentf/commons/__init__.py,sha256=Uq-7WvkMoBiF3C1KnhwIL4LCKpT8EvomnuG4MBYpIhs,21994
|
|
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=4ye-TMtaE88O8GVcWx-FtKXOC8aIZLteR6wfIr7Do8U,25232
|
|
5
5
|
opentf/commons/expressions.py,sha256=jM_YKXVOFhvOE2aE2IuacuvxhIsOYTFs2oQkpcbWR6g,19645
|
|
6
|
-
opentf/commons/pubsub.py,sha256=
|
|
6
|
+
opentf/commons/pubsub.py,sha256=Y3vOeGNcI4_-uYwBy2grxmn1Oq5r89tyRZZX3mjgiAA,7254
|
|
7
7
|
opentf/commons/schemas.py,sha256=YSCvlmqc7satt-OqIoYXnmhOyo9h8wIpNyKaBAY4u9c,4039
|
|
8
8
|
opentf/commons/selectors.py,sha256=DEpLgRAr5HXSpSYI4liXP2hLUTvOSexFa9Vfa1xIQTk,7134
|
|
9
9
|
opentf/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -46,11 +46,11 @@ opentf/schemas/opentestfactory.org/v1beta1/Workflow.json,sha256=QZ8mM9PhzsI9gTmw
|
|
|
46
46
|
opentf/schemas/opentestfactory.org/v1beta2/ServiceConfig.json,sha256=rEvK2YWL5lG94_qYgR_GnLWNsaQhaQ-2kuZdWJr5NnY,3517
|
|
47
47
|
opentf/scripts/launch_java_service.sh,sha256=S0jAaCuv2sZy0Gf2NGBuPX-eD531rcM-b0fNyhmzSjw,2423
|
|
48
48
|
opentf/scripts/startup.py,sha256=Da2zo93pBWbdRmj-wgekgLcF94rpNc3ZkbvR8R0w8XY,21279
|
|
49
|
-
opentf/toolkit/__init__.py,sha256=
|
|
49
|
+
opentf/toolkit/__init__.py,sha256=0265hKrPC2trSQcTEIiobFCUzeXGRLbIm-T30NP-Kio,23216
|
|
50
50
|
opentf/toolkit/channels.py,sha256=6xcVKHUK2FdyVKIQmPQbakngfVuQDzCcD_lInOdKpro,17171
|
|
51
51
|
opentf/toolkit/core.py,sha256=Uc5cRwyi6bs7WVmgvQLTvEa6bXjZ3KfCKWHSdIeUy98,9621
|
|
52
|
-
opentf_toolkit_nightly-0.57.0.
|
|
53
|
-
opentf_toolkit_nightly-0.57.0.
|
|
54
|
-
opentf_toolkit_nightly-0.57.0.
|
|
55
|
-
opentf_toolkit_nightly-0.57.0.
|
|
56
|
-
opentf_toolkit_nightly-0.57.0.
|
|
52
|
+
opentf_toolkit_nightly-0.57.0.dev1051.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
53
|
+
opentf_toolkit_nightly-0.57.0.dev1051.dist-info/METADATA,sha256=dlte0IlbCdEPnhzDEE5pyG-A3PxBkdB0No4Ubh64BB8,1951
|
|
54
|
+
opentf_toolkit_nightly-0.57.0.dev1051.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
55
|
+
opentf_toolkit_nightly-0.57.0.dev1051.dist-info/top_level.txt,sha256=_gPuE6GTT6UNXy1DjtmQSfCcZb_qYA2vWmjg7a30AGk,7
|
|
56
|
+
opentf_toolkit_nightly-0.57.0.dev1051.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|