Skip to content

Commit 29067ef

Browse files
committed
attempt to handle rose rsync can_pull errors better
handle no file error with useful error message Apply suggestions from code review Co-authored-by: Ronnie Dutta <61982285+MetRonnie@users.noreply.github.com> Response to review move error messaging into error class
1 parent 0454361 commit 29067ef

File tree

5 files changed

+70
-3
lines changed

5 files changed

+70
-3
lines changed

changes.d/2892.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Give the user more information about rsync file handler failure.

metomi/rose/config_processors/fileinstall.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,12 +891,15 @@ def parse(self, loc, conf_tree):
891891
if handler is None:
892892
raise ValueError(f"don't support scheme {loc.scheme}")
893893
else:
894-
# Scheme not specified in the configuration.
894+
# Try to get the scheme by parsing loc name, e.g. git:some-url
895895
scheme = urlparse(loc.name).scheme
896896
if scheme:
897897
handler = self.get_handler(scheme)
898898
if handler is None:
899+
# Try to guess the scheme using the ``can_handle`` method
900+
# from each handler in turn:
899901
handler = self.guess_handler(loc)
902+
900903
if handler is None:
901904
raise ValueError(f"don't know how to process {loc.name}")
902905
else:

metomi/rose/loc_handlers/rsync.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
# -----------------------------------------------------------------------------
1717
"""A handler of locations on remote hosts."""
1818

19+
from io import TextIOWrapper
20+
from textwrap import indent
1921
from time import sleep, time
2022

2123
from metomi.rose.loc_handlers.rsync_remote_check import (
@@ -24,6 +26,58 @@
2426
from metomi.rose.popen import RosePopenError
2527

2628

29+
class PreRsyncCheckError(Exception):
30+
"""Error to raise if we assume the loc is for use with rsync,
31+
but attempting to use it as an rsync loc fails."""
32+
BASE_MESSAGE = (
33+
'Rose tried all other file install handlers and'
34+
' decided this must be an Rsync handler.\n\t'
35+
)
36+
37+
def __init__(self, dict_, cmd=None):
38+
for key, value in dict_.items():
39+
if isinstance(value, TextIOWrapper):
40+
setattr(self, key, value.read())
41+
else:
42+
setattr(self, key, value)
43+
44+
# Convert command into something the debugger can try:
45+
try:
46+
self.cmd = ' '.join(cmd)
47+
except TypeError:
48+
self.cmd = cmd
49+
50+
# Handle ``test -e nonexistant`` where no useful error is
51+
# provided:
52+
if (
53+
self.returncode == 1
54+
and self.stderr == ''
55+
and self.stdout == ''
56+
):
57+
self.stderr = f'File "{cmd[-1]}" does not exist.'
58+
59+
if self.returncode == 255:
60+
host = dict_['args'][dict_['args'].index('-n') + 1]
61+
self.message = (
62+
self.BASE_MESSAGE
63+
+ 'If it is then host'
64+
f' "{host}"'
65+
' is uncontactable (ssh 255 error).'
66+
)
67+
else:
68+
self.message = (
69+
self.BASE_MESSAGE
70+
+ f'`{self.cmd}` failed with:'
71+
+ indent(
72+
f'\nreturncode: {self.returncode}'
73+
f'\nstdout: {self.stdout}'
74+
f'\nstderr: {self.stderr}',
75+
prefix=' ',
76+
)
77+
)
78+
super().__init__(self.message)
79+
80+
2781
class RsyncLocHandler:
2882
"""Handler of locations on remote hosts."""
2983

@@ -53,7 +107,10 @@ def can_pull(self, loc):
53107
except RosePopenError:
54108
return False
55109
else:
56-
return proc.wait() == 0
110+
if proc.wait() == 0:
111+
return True
112+
else:
113+
raise PreRsyncCheckError(proc.__dict__, cmd=cmd)
57114

58115
def parse(self, loc, _):
59116
"""Set loc.scheme, loc.loc_type, loc.paths."""

metomi/rose/scheme_handler.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ def __init__(
9797
if handler is None:
9898
handler = class_(*args, **kwargs)
9999
self.handlers[scheme] = handler
100+
101+
if 'rsync' in self.handlers:
102+
# rsync handler should always be at the end of the list:
103+
self.handlers['rsync'] = self.handlers.pop('rsync')
104+
100105
finally:
101106
os.chdir(cwd)
102107
sys.path.pop(0)

t/rose-app-run/05-file.t

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ run_fail "$TEST_KEY" rose app-run --config=../config -q \
7070
--define='[file:hello4]source=stuff:ing'
7171
file_cmp "$TEST_KEY.out" "$TEST_KEY.out" </dev/null
7272
file_cmp "$TEST_KEY.err" "$TEST_KEY.err" <<'__CONTENT__'
73-
[FAIL] file:hello4=source=stuff:ing: don't know how to process stuff:ing
73+
[FAIL] Rose tried all other file install handlers and decided this must be an Rsync handler.
74+
[FAIL] If it is then host "stuff" is uncontactable (ssh 255 error).
7475
__CONTENT__
7576
test_teardown
7677
#-------------------------------------------------------------------------------

0 commit comments

Comments
 (0)