shutil.copyfileobj(src, fdst)
fdst.close()
-
-def copy_file_to(f, destinations, host):
- for dst in destinations:
- if hasattr(dst, 'log'):
- # looks like a Logger to me; not using isinstance to make life
- # easier for unit tests
- copy_to_log(f, dst, host)
- else:
- shutil.copyfileobj(f, dst)
+def copy_file_to(f, dst, host):
+ if hasattr(dst, 'log'):
+ # looks like a Logger to me; not using isinstance to make life
+ # easier for unit tests
+ handler = copy_to_log
+ return handler(f, dst, host)
+ else:
+ handler = shutil.copyfileobj
+ return handler(f, dst)
class CommandFailedError(Exception):
- def __init__(self, command, exitstatus, node, stderr):
+ def __init__(self, command, exitstatus, node=None):
self.command = command
self.exitstatus = exitstatus
self.node = node
- self.stderr = stderr
def __str__(self):
- return "Command failed on {node} with status {status}: {command!r}\nstderr output: {stderr}".format(
+ return "Command failed on {node} with status {status}: {command!r}".format(
node=self.node,
status=self.exitstatus,
command=self.command,
- stderr=self.stderr
- )
+ )
class CommandCrashedError(Exception):
if name is None:
name = host
- err_buffer = StringIO()
-
g_err = None
if stderr is not PIPE:
- err_outputs = [err_buffer, logger.getChild('err')]
- if stderr is not None:
- err_outputs.append(stderr)
- g_err = gevent.spawn(copy_file_to, r.stderr, err_outputs, name)
+ if stderr is None:
+ stderr = logger.getChild('err')
+ g_err = gevent.spawn(copy_file_to, r.stderr, stderr, name)
r.stderr = stderr
else:
assert not wait, "Using PIPE for stderr without wait=False would deadlock."
if stdout is not PIPE:
if stdout is None:
stdout = logger.getChild('out')
- g_out = gevent.spawn(copy_file_to, r.stdout, [stdout], name)
+ g_out = gevent.spawn(copy_file_to, r.stdout, stdout, name)
r.stdout = stdout
else:
assert not wait, "Using PIPE for stdout without wait=False would deadlock."
# signal; sadly SSH does not tell us which signal
raise CommandCrashedError(command=r.command)
if status != 0:
- raise CommandFailedError(command=r.command, exitstatus=status, node=name, stderr=err_buffer.getvalue())
+ raise CommandFailedError(command=r.command, exitstatus=status, node=name)
return status
if wait:
transport.expects('getpeername').with_args().returns(('HOST', 22))
cmd = ssh.expects('exec_command')
cmd.with_args("foo 'bar baz'")
-
- # The I/O channels of the SSH child process
in_ = fudge.Fake('ChannelFile(stdin)')
out = fudge.Fake('ChannelFile(stdout)')
err = fudge.Fake('ChannelFile(stderr)')
in_chan = fudge.Fake('channel')
in_chan.expects('shutdown_write').with_args()
in_.has_attr(channel=in_chan)
-
- # The values we expect to see from the SSH child process
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
out.expects('xreadlines').with_args().returns(['foo', 'bar'])
err.expects('xreadlines').with_args().returns(['bad'])
-
- # The outputs we will expect to see child output forwarded to
logger = fudge.Fake('logger')
log_err = fudge.Fake('log_err')
logger.expects('getChild').with_args('err').returns(log_err)
logger.expects('getChild').with_args('out').returns(log_out)
log_out.expects('log').with_args(logging.INFO, '[HOST]: foo')
log_out.expects('log').with_args(logging.INFO, '[HOST]: bar')
-
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
channel.expects('recv_exit_status').with_args().returns(0)
out.expects('read').with_args().returns('foo\nb')
out.expects('read').with_args().returns('ar\n')
out.expects('read').with_args().returns('')
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
err.expects('xreadlines').with_args().returns(['bad'])
logger = fudge.Fake('logger')
log_err = fudge.Fake('log_err')
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
)
assert e.command == 'foo'
assert e.exitstatus == 42
- assert str(e) == """Command failed on HOST with status 42: 'foo'
-stderr output: bad"""
+ assert str(e) == "Command failed on HOST with status 42: 'foo'"
@fudge.with_fakes
def test_run_status_bad_nocheck(self):
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
r.exitstatus.get,
)
assert e.exitstatus == 42
- assert str(e) == """Command failed on HOST with status 42: 'foo'
-stderr output: bad"""
+ assert str(e) == "Command failed on HOST with status 42: 'foo'"
@fudge.with_fakes
def test_run_stdin_pipe(self):
cmd.returns((in_, out, err))
out.expects('xreadlines').with_args().returns([])
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)
out.expects('read').with_args().returns('two')
out.expects('read').with_args().returns('')
err.expects('xreadlines').with_args().returns([])
- err.expects('read').with_args().returns("bad").expects('read').with_args().returns(None)
logger = fudge.Fake('logger').is_a_stub()
channel = fudge.Fake('channel')
out.has_attr(channel=channel)