gluetool 3.3__tar.gz → 3.4__tar.gz
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.
- {gluetool-3.3 → gluetool-3.4}/PKG-INFO +1 -1
- {gluetool-3.3 → gluetool-3.4}/gluetool/glue.py +10 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_tool.py +66 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tool.py +31 -1
- {gluetool-3.3 → gluetool-3.4}/pyproject.toml +2 -2
- {gluetool-3.3 → gluetool-3.4}/README.rst +0 -0
- {gluetool-3.3 → gluetool-3.4}/assets/html-log/prism.css +0 -0
- {gluetool-3.3 → gluetool-3.4}/assets/html-log/prism.js +0 -0
- {gluetool-3.3 → gluetool-3.4}/assets/html-log/semantic.min.css +0 -0
- {gluetool-3.3 → gluetool-3.4}/assets/html-log/semantic.min.js +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/__init__.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/action.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/color.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/help.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/html_log.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/log.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/proxy.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/py.typed +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/__init__.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/option_default.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/shared_defined.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/unknown_option.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/result.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/sentry.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/__init__.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_config_root_a +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_config_root_b +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_not_unicode +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroota/config/data_config_root_a +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configrootb/config/data_config_root_b +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/conftest.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_action.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_core.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_error.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_eval_context.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_help.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_json.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_load_yaml.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_log_exception.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_logging.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_module_discovery.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_new_xml_element.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_normalize_option.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_option.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_parse_config.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_pipeline_step.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_render_template.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_requests.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_result.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_run_command.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_run_modules.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_treat_url.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_utils.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_wait.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/utils.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool/version.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool_modules/__init__.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool_modules/bash_completion.py +0 -0
- {gluetool-3.3 → gluetool-3.4}/gluetool_modules/yaml_pipeline.py +0 -0
|
@@ -1788,6 +1788,15 @@ class Glue(Configurable):
|
|
|
1788
1788
|
'action': 'store_true',
|
|
1789
1789
|
'default': False
|
|
1790
1790
|
},
|
|
1791
|
+
'sigterm-timeout': {
|
|
1792
|
+
'help': """
|
|
1793
|
+
Time, in seconds, to wait for a child process to exit after sending it ``SIGTERM``,
|
|
1794
|
+
before resorting to ``SIGKILL``. Takes precedence over the ``GLUETOOL_SIGTERM_TIMEOUT``
|
|
1795
|
+
environment variable (Default: 60).
|
|
1796
|
+
""",
|
|
1797
|
+
'type': int,
|
|
1798
|
+
'default': None
|
|
1799
|
+
},
|
|
1791
1800
|
}),
|
|
1792
1801
|
('Output control', {
|
|
1793
1802
|
('c', 'colors'): {
|
|
@@ -2510,6 +2519,7 @@ class Glue(Configurable):
|
|
|
2510
2519
|
* GLUETOOL_TRACING_SERVICE_NAME (string) - name of the trace produced by tool execution
|
|
2511
2520
|
* GLUETOOL_TRACING_REPORTING_HOST (string) - a hostname where tracing collector listens
|
|
2512
2521
|
* GLUETOOL_TRACING_REPORTING_PORT (int) - a port on which tracing collector listens
|
|
2522
|
+
* GLUETOOL_SIGTERM_TIMEOUT (int) - seconds to wait for a child to exit after SIGTERM before SIGKILL
|
|
2513
2523
|
""").format(module_dirs, data_dirs, module_config_dirs)
|
|
2514
2524
|
|
|
2515
2525
|
self._parse_args(args,
|
|
@@ -175,3 +175,69 @@ def test_signal(monkeypatch, log, tested_signal, exception, terminate_process_tr
|
|
|
175
175
|
assert log.match(levelno=logging.WARNING, message=warnmsg)
|
|
176
176
|
assert log.match(levelno=logging.DEBUG, message='Exiting with status 0')
|
|
177
177
|
assert log.match(levelno=logging.INFO, message='gluetool some-version')
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def test_sigterm_timeout_default(monkeypatch):
|
|
181
|
+
monkeypatch.delenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, raising=False)
|
|
182
|
+
|
|
183
|
+
assert gluetool.tool.sigterm_timeout() == gluetool.tool.DEFAULT_SIGTERM_TIMEOUT
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@pytest.mark.parametrize('value,expected', [
|
|
187
|
+
('0', 0),
|
|
188
|
+
('1', 1),
|
|
189
|
+
('120', 120),
|
|
190
|
+
], ids=['zero', 'one', 'custom'])
|
|
191
|
+
def test_sigterm_timeout_envvar(monkeypatch, value, expected):
|
|
192
|
+
monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, value)
|
|
193
|
+
|
|
194
|
+
assert gluetool.tool.sigterm_timeout() == expected
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def test_sigterm_timeout_envvar_invalid(monkeypatch):
|
|
198
|
+
monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, 'not-a-number')
|
|
199
|
+
|
|
200
|
+
with pytest.raises(ValueError):
|
|
201
|
+
gluetool.tool.sigterm_timeout()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_sigterm_timeout_option_overrides_envvar(monkeypatch):
|
|
205
|
+
# The `sigterm-timeout` option (command line or configuration file) takes precedence over the env variable.
|
|
206
|
+
monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, '30')
|
|
207
|
+
|
|
208
|
+
glue = MagicMock()
|
|
209
|
+
glue.option = MagicMock(return_value=90)
|
|
210
|
+
|
|
211
|
+
assert gluetool.tool.sigterm_timeout(glue) == 90
|
|
212
|
+
glue.option.assert_called_once_with('sigterm-timeout')
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_sigterm_timeout_option_unset_falls_back_to_envvar(monkeypatch):
|
|
216
|
+
# When the option is not set, the env variable is used.
|
|
217
|
+
monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, '30')
|
|
218
|
+
|
|
219
|
+
glue = MagicMock()
|
|
220
|
+
glue.option = MagicMock(return_value=None)
|
|
221
|
+
|
|
222
|
+
assert gluetool.tool.sigterm_timeout(glue) == 30
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def test_sigterm_timeout_option_unset_falls_back_to_default(monkeypatch):
|
|
226
|
+
# When neither the option nor the env variable is set, the default is used.
|
|
227
|
+
monkeypatch.delenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, raising=False)
|
|
228
|
+
|
|
229
|
+
glue = MagicMock()
|
|
230
|
+
glue.option = MagicMock(return_value=None)
|
|
231
|
+
|
|
232
|
+
assert gluetool.tool.sigterm_timeout(glue) == gluetool.tool.DEFAULT_SIGTERM_TIMEOUT
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_sigterm_timeout_option_from_cmdline(monkeypatch):
|
|
236
|
+
# The `sigterm-timeout` option is wired into the command-line parser and parsed as an integer.
|
|
237
|
+
monkeypatch.delenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, raising=False)
|
|
238
|
+
|
|
239
|
+
glue = NonLoadingGlue()
|
|
240
|
+
glue._parse_args(['--sigterm-timeout', '120'])
|
|
241
|
+
|
|
242
|
+
assert glue.option('sigterm-timeout') == 120
|
|
243
|
+
assert gluetool.tool.sigterm_timeout(glue) == 120
|
|
@@ -44,6 +44,36 @@ DEFAULT_GLUETOOL_CONFIG_PATHS = [
|
|
|
44
44
|
|
|
45
45
|
DEFAULT_SIGTERM_TIMEOUT = 60
|
|
46
46
|
|
|
47
|
+
# Environment variable overriding the time (in seconds) ``gluetool`` waits for a child process to exit after
|
|
48
|
+
# sending it ``SIGTERM`` before resorting to ``SIGKILL``.
|
|
49
|
+
SIGTERM_TIMEOUT_ENVVAR = 'GLUETOOL_SIGTERM_TIMEOUT'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def sigterm_timeout(glue: Optional['gluetool.glue.Glue'] = None) -> int:
|
|
53
|
+
"""
|
|
54
|
+
Return the time, in seconds, ``gluetool`` waits for a child process to exit after sending it ``SIGTERM``
|
|
55
|
+
before resorting to ``SIGKILL``.
|
|
56
|
+
|
|
57
|
+
The value is resolved with the following precedence:
|
|
58
|
+
|
|
59
|
+
1. the ``sigterm-timeout`` option (set on the command line or in a configuration file),
|
|
60
|
+
2. the :py:data:`SIGTERM_TIMEOUT_ENVVAR` environment variable,
|
|
61
|
+
3. :py:data:`DEFAULT_SIGTERM_TIMEOUT`.
|
|
62
|
+
|
|
63
|
+
:param glue: ``Glue`` instance to read the ``sigterm-timeout`` option from. When not provided, the option
|
|
64
|
+
is skipped and the value is resolved from the environment variable or the default.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
if glue is not None:
|
|
68
|
+
option = glue.option('sigterm-timeout')
|
|
69
|
+
if option is not None:
|
|
70
|
+
return cast(int, option)
|
|
71
|
+
|
|
72
|
+
if SIGTERM_TIMEOUT_ENVVAR in os.environ:
|
|
73
|
+
return int(os.environ[SIGTERM_TIMEOUT_ENVVAR])
|
|
74
|
+
|
|
75
|
+
return DEFAULT_SIGTERM_TIMEOUT
|
|
76
|
+
|
|
47
77
|
|
|
48
78
|
def handle_exc(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
49
79
|
|
|
@@ -305,7 +335,7 @@ Will try to submit it to Sentry but giving up on everything else.
|
|
|
305
335
|
child.terminate()
|
|
306
336
|
|
|
307
337
|
try:
|
|
308
|
-
child.wait(timeout=
|
|
338
|
+
child.wait(timeout=sigterm_timeout(Glue))
|
|
309
339
|
|
|
310
340
|
except psutil.TimeoutExpired:
|
|
311
341
|
Glue.warn("Sending SIGKILL to child process '{}' (PID {})".format(child.name(), child.pid))
|
|
@@ -4,7 +4,7 @@ dynamic = ["version"]
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "gluetool"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.4"
|
|
8
8
|
description = "Python framework for constructing command-line pipelines."
|
|
9
9
|
authors = [
|
|
10
10
|
"Milos Prchlik <mprchlik@redhat.com>",
|
|
@@ -108,7 +108,7 @@ opentelemetry-sdk = "^1.40.0"
|
|
|
108
108
|
opentelemetry-exporter-otlp-proto-grpc = "^1.40.0"
|
|
109
109
|
|
|
110
110
|
[tool.poetry-dynamic-versioning]
|
|
111
|
-
enable =
|
|
111
|
+
enable = false
|
|
112
112
|
|
|
113
113
|
[build-system]
|
|
114
114
|
requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_not_unicode
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|