Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes.d/2892.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Give the user more information about rsync file handler failure.
5 changes: 4 additions & 1 deletion metomi/rose/config_processors/fileinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,12 +891,15 @@ def parse(self, loc, conf_tree):
if handler is None:
raise ValueError(f"don't support scheme {loc.scheme}")
else:
# Scheme not specified in the configuration.
# Try to get the scheme by parsing loc name, e.g. git:some-url
scheme = urlparse(loc.name).scheme
if scheme:
handler = self.get_handler(scheme)
if handler is None:
# Try to guess the scheme using the ``can_handle`` method
# from each handler in turn:
handler = self.guess_handler(loc)

if handler is None:
raise ValueError(f"don't know how to process {loc.name}")
else:
Expand Down
69 changes: 68 additions & 1 deletion metomi/rose/loc_handlers/rsync.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# -----------------------------------------------------------------------------
"""A handler of locations on remote hosts."""

from io import TextIOWrapper
from textwrap import indent
from time import sleep, time

from metomi.rose.loc_handlers.rsync_remote_check import (
Expand All @@ -24,6 +26,68 @@
from metomi.rose.popen import RosePopenError


class PreRsyncCheckError(Exception):
"""Error to raise if we assume the loc is for use with rsync,
but attempting to use it as an rsync loc fails."""
BASE_MESSAGE = (
'Rose tried all other file install handlers and'
' decided this must be an Rsync handler.\n\t'
)

def __init__(self, dict_, cmd=None, loc=None):
for key, value in dict_.items():
if isinstance(value, TextIOWrapper):
setattr(self, key, value.read())
else:
setattr(self, key, value)

# Convert command into something the debugger can try:
try:
self.cmd = ' '.join(cmd)
except TypeError:
self.cmd = cmd

# Handle ``test -e nonexistant`` where no useful error is
# provided:
message = ''
for used_by in loc.used_by_names:
message += (
f'file:{used_by}={loc.action_key}={loc.name}'
': don\'t know how to process stuff:ing\n'
)
if (
self.returncode == 1
and self.stderr == ''
and self.stdout == ''
):
self.stderr = f'File "{cmd[-1]}" does not exist.'

if self.returncode == 255:
host = dict_['args'][dict_['args'].index('-n') + 1]
self.mod_msg = (
message
+ self.BASE_MESSAGE
+ 'If it is then host'
f' "{host}"'
' is uncontactable (ssh 255 error).'
)
else:
self.mod_msg = (
message
+ self.BASE_MESSAGE
+ f'`{self.cmd}` failed with:'
+ indent(
f'\nreturncode: {self.returncode}'
f'\nstdout: {self.stdout}'
f'\nstderr: {self.stderr}',
prefix=' ',
)
)

def __str__(self):
return self.mod_msg


class RsyncLocHandler:
"""Handler of locations on remote hosts."""

Expand Down Expand Up @@ -53,7 +117,10 @@ def can_pull(self, loc):
except RosePopenError:
return False
else:
return proc.wait() == 0
if proc.wait() == 0:
return True
else:
raise PreRsyncCheckError(proc.__dict__, cmd=cmd, loc=loc)

def parse(self, loc, _):
"""Set loc.scheme, loc.loc_type, loc.paths."""
Expand Down
5 changes: 5 additions & 0 deletions metomi/rose/scheme_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ def __init__(
if handler is None:
handler = class_(*args, **kwargs)
self.handlers[scheme] = handler

if 'rsync' in self.handlers:
# rsync handler should always be at the end of the list:
self.handlers['rsync'] = self.handlers.pop('rsync')

finally:
os.chdir(cwd)
sys.path.pop(0)
Expand Down
2 changes: 2 additions & 0 deletions t/rose-app-run/05-file.t
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ run_fail "$TEST_KEY" rose app-run --config=../config -q \
file_cmp "$TEST_KEY.out" "$TEST_KEY.out" </dev/null
file_cmp "$TEST_KEY.err" "$TEST_KEY.err" <<'__CONTENT__'
[FAIL] file:hello4=source=stuff:ing: don't know how to process stuff:ing
[FAIL] Rose tried all other file install handlers and decided this must be an Rsync handler.
[FAIL] If it is then host "stuff" is uncontactable (ssh 255 error).
__CONTENT__
test_teardown
#-------------------------------------------------------------------------------
Expand Down
Loading