Skip to content

Commit 4d17bb1

Browse files
committed
Improve error message for cylc clean remote timeout
1 parent 043b5e4 commit 4d17bb1

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

cylc/flow/clean.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def remote_clean(
384384
remote_clean_cmd(platform=platforms[0]), target, platforms
385385
)
386386
)
387-
failed_targets: Dict[str, PlatformError] = {}
387+
failed_targets: Dict[str, Union[PlatformError, str]] = {}
388388
# Handle subproc pool results almost concurrently:
389389
while queue:
390390
item = queue.popleft()
@@ -395,7 +395,12 @@ def remote_clean(
395395
out, err = item.proc.communicate()
396396
if out:
397397
LOG.info(f"[{item.install_target}]\n{out}")
398-
if ret_code:
398+
if ret_code == 124:
399+
failed_targets[item.install_target] = (
400+
f"cylc clean timed out after {timeout}s. You can increase "
401+
"this timeout using the --timeout option."
402+
)
403+
elif ret_code:
399404
this_platform = item.platforms.pop(0)
400405
excp = PlatformError(
401406
PlatformError.MSG_TIDY,
@@ -423,9 +428,9 @@ def remote_clean(
423428
LOG.debug(f"[{item.install_target}]\n{err}")
424429
sleep(0.2)
425430
if failed_targets:
426-
for target, excp in failed_targets.items():
431+
for target, info in failed_targets.items():
427432
LOG.error(
428-
f"Could not clean {id_} on install target: {target}\n{excp}"
433+
f"Could not clean {id_} on install target: {target}\n{info}"
429434
)
430435
raise CylcError(f"Remote clean failed for {id_}")
431436

tests/functional/cylc-clean/01-remote.t

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ SSH_CMD="$(cylc config -d -i "[platforms][${CYLC_TEST_PLATFORM}]ssh command") ${
2525
if ! $SSH_CMD command -v 'tree' > '/dev/null'; then
2626
skip_all "'tree' command not available on remote host ${CYLC_TEST_HOST}"
2727
fi
28-
set_test_number 10
28+
set_test_number 12
2929

3030
# Generate random name for symlink dirs to avoid any clashes with other tests
3131
SYM_NAME="$(mktemp -u)"
@@ -108,7 +108,13 @@ __TREE__
108108

109109
# -----------------------------------------------------------------------------
110110

111-
TEST_NAME="cylc-clean"
111+
TEST_NAME="cylc-clean-timeout"
112+
run_fail "$TEST_NAME" cylc clean --timeout 'PT0,1S' "$WORKFLOW_NAME"
113+
dump_std "$TEST_NAME"
114+
grep_ok 'cylc clean timed out after 0.1s' "${TEST_NAME}.stderr"
115+
116+
117+
TEST_NAME="cylc-clean-ok"
112118
run_ok "$TEST_NAME" cylc clean "$WORKFLOW_NAME"
113119
dump_std "$TEST_NAME"
114120

tests/unit/test_clean.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -970,25 +970,35 @@ def mocked_remote_clean_cmd_side_effect(id_, platform, timeout, rm_dirs):
970970
('PT1M2S', '62.0')]
971971
)
972972
def test_remote_clean__timeout(
973-
monkeymock: MonkeyMock, monkeypatch: pytest.MonkeyPatch,
974-
timeout: str, expected: str,
973+
monkeymock: MonkeyMock,
974+
monkeypatch: pytest.MonkeyPatch,
975+
caplog: pytest.LogCaptureFixture,
976+
timeout: str,
977+
expected: str,
975978
):
976-
"""Test that remote_clean() accepts a timeout in ISO 8601 format or
977-
number of seconds."""
979+
"""Test remote_clean() timeout.
980+
981+
- It should accept ISO 8601 format or number of seconds.
982+
- It should give a sensible error message for return code 124.
983+
"""
984+
caplog.set_level(logging.ERROR, CYLC_LOG)
978985
mock_remote_clean_cmd = monkeymock(
979986
'cylc.flow.clean._remote_clean_cmd',
980987
spec=_remote_clean_cmd,
981988
return_value=mock.Mock(
982-
spec=Popen, poll=lambda: 0, communicate=lambda: ('', '')
989+
spec=Popen, poll=lambda: 124, communicate=lambda: ('', '')
983990
)
984991
)
985992
monkeypatch.setattr(
986993
'cylc.flow.clean.get_install_target_to_platforms_map',
987994
lambda *a, **k: {'picard': [PLATFORMS['stargazer']]}
988995
)
989996

990-
cylc_clean.remote_clean('blah', 'blah', timeout)
991-
assert mock_remote_clean_cmd.call_args.kwargs['timeout'] == expected
997+
with pytest.raises(CylcError):
998+
cylc_clean.remote_clean('blah', 'blah', timeout)
999+
_, kwargs = mock_remote_clean_cmd.call_args
1000+
assert kwargs['timeout'] == expected
1001+
assert f"cylc clean timed out after {expected}s" in caplog.text
9921002

9931003

9941004
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)