-
Notifications
You must be signed in to change notification settings - Fork 290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
exceptions: change error message for CommandFailedError #1652
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
from re import sub | ||
|
||
from teuthology.orchestra.run_helper import Raw | ||
|
||
|
||
class BranchNotFoundError(ValueError): | ||
def __init__(self, branch, repo=None): | ||
self.branch = branch | ||
|
@@ -50,21 +55,30 @@ class CommandFailedError(Exception): | |
""" | ||
Exception thrown on command failure | ||
""" | ||
def __init__(self, command, exitstatus, node=None, label=None): | ||
self.command = command | ||
def __init__(self, cmd, exitstatus, node=None, label=None): | ||
self.cmd = cmd | ||
Comment on lines
+58
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why renaming
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Lesser effort to type, and easier to keep statements under 79 characters which in turn saves us from hard to read split-over-several-line statements . |
||
self.exitstatus = exitstatus | ||
self.node = node | ||
self.label = label | ||
|
||
def __str__(self): | ||
if isinstance(self.cmd, (list, tuple)): | ||
cmd = [str(Raw) if isinstance(x, Raw) else x | ||
for x in self.cmd] | ||
cmd = ' '.join(self.cmd) | ||
elif isinstance(self.cmd, str): | ||
cmd = sub(r'Raw\([\'"](.*)[\'"]\)', r'\1', self.cmd) | ||
else: | ||
raise RuntimeError('variable "self.cmd" is not str, list or tuple') | ||
|
||
prefix = "Command failed" | ||
if self.label: | ||
prefix += " ({label})".format(label=self.label) | ||
if self.node: | ||
prefix += " on {node}".format(node=self.node) | ||
return "{prefix} with status {status}: {cmd!r}".format( | ||
status=self.exitstatus, | ||
cmd=self.command, | ||
cmd=cmd, | ||
prefix=prefix, | ||
) | ||
|
||
|
@@ -74,7 +88,7 @@ def fingerprint(self): | |
Used by sentry instead of grouping by backtrace. | ||
""" | ||
return [ | ||
self.label or self.command, | ||
self.label or self.cmd, | ||
'exit status {}'.format(self.exitstatus), | ||
'{{ type }}', | ||
] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
""" | ||
Contains classes that "help" RemoteProcess and rest of the code in run.py | ||
|
||
This module was started as it was needed that Raw and quote be separated from | ||
teuthology.orchestra.run so that these can be imported in | ||
teuthology.exceptions without causing circular dependency. | ||
""" | ||
|
||
from pipes import quote as pipes_quote | ||
|
||
|
||
class Raw(object): | ||
""" | ||
Raw objects are passed to remote objects and are not processed locally. | ||
""" | ||
def __init__(self, value): | ||
self.value = value | ||
|
||
def __repr__(self): | ||
return '{cls}({value!r})'.format( | ||
cls=self.__class__.__name__, | ||
value=self.value, | ||
) | ||
|
||
def __eq__(self, value): | ||
return self.value == value | ||
|
||
def __str__(self, value): | ||
return str(value) | ||
|
||
|
||
def quote(args): | ||
""" | ||
Internal quote wrapper. | ||
""" | ||
def _quote(args): | ||
""" | ||
Handle quoted string, testing for raw charaters. | ||
""" | ||
for a in args: | ||
if isinstance(a, Raw): | ||
yield a.value | ||
else: | ||
yield pipes_quote(a) | ||
|
||
if isinstance(args, list): | ||
return ' '.join(_quote(args)) | ||
else: | ||
return args | ||
|
||
|
||
class Sentinel(object): | ||
""" | ||
Sentinel -- used to define PIPE file-like object. | ||
""" | ||
def __init__(self, name): | ||
self.name = name | ||
|
||
def __str__(self): | ||
return self.name | ||
|
||
|
||
PIPE = Sentinel('PIPE') | ||
|
||
|
||
class KludgeFile(object): | ||
""" | ||
Wrap Paramiko's ChannelFile in a way that lets ``f.close()`` | ||
actually cause an EOF for the remote command. | ||
""" | ||
def __init__(self, wrapped): | ||
self._wrapped = wrapped | ||
|
||
def __getattr__(self, name): | ||
return getattr(self._wrapped, name) | ||
|
||
def close(self): | ||
""" | ||
Close and shutdown. | ||
""" | ||
self._wrapped.close() | ||
self._wrapped.channel.shutdown_write() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From one side this might seem useful for a user to copy and paste command,
but from another point of view, it is bad for debugging, it will be not possible to figure out what
exactly command was before it got to the Exception. Also, the next line joining command with spaces is absolutely not the same as it makes it quoted inside run methods, which makes it hard to reproduce issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how would figuring out become difficult since parameter would be printed as it is (at least individually). For example,
['ls', 'dir1']
would becomels dir1
. I have grepped plenty times and either don't make much of a difference.Same as what?
Umm... are you referring to this line when you say "quoted inside run methods"? I think there's no nice way around that but printing as string definitely takes away effort of deleting a dozen inverted commas every time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I mean the quotation thing.
Also, if you want to get the exact command, it is already printed in the logs, you just need to find the place where debug is printing the command out before the execution.