def start(self, **kwargs): """ Present the PTY of the container inside the current process. This will take over the current process' TTY until the container's PTY is closed. """ pty_stdin, pty_stdout, pty_stderr = self.sockets() mappings = [ (pty_stdout, io.Stream(sys.stdout)), (pty_stderr, io.Stream(sys.stderr)), ] if self.interactive: mappings.insert(0, (io.Stream(sys.stdin), pty_stdin)) pumps = [io.Pump(a, b) for (a, b) in mappings if a and b] if not self.container_info()['State']['Running']: self.client.start(self.container, **kwargs) flags = [p.set_blocking(False) for p in pumps] try: with WINCHHandler(self): self._hijack_tty(pumps) finally: if flags: for (pump, flag) in zip(pumps, flags): io.set_blocking(pump, flag)
def start(self, sockets=None, **kwargs): """ Present the PTY of the container inside the current process. This will take over the current process' TTY until the container's PTY is closed. """ pty_stdin, pty_stdout, pty_stderr = sockets or self.sockets() pumps = [] if pty_stdin and self.interactive: pumps.append( io.Pump(io.Stream(self.stdin), pty_stdin, wait_for_output=False)) if pty_stdout: pumps.append( io.Pump(pty_stdout, io.Stream(self.stdout), propagate_close=False)) if pty_stderr: pumps.append( io.Pump(pty_stderr, io.Stream(self.stderr), propagate_close=False)) if not self._container_info()['State']['Running']: self.client.start(self.container, **kwargs) return pumps
def start(self, sockets=None, **kwargs): """ Present the PTY of the container inside the current process. This will take over the current process' TTY until the container's PTY is closed. """ pty_stdin, pty_stdout, pty_stderr = sockets or self.sockets() pumps = [] if pty_stdin and self.interactive: # if stdin isn't a TTY then this is probably an SSH session # so wait for the EOF to happen before considering the Pump closed. pumps.append( io.Pump(io.Stream(self.stdin), pty_stdin, wait_for_output=not sys.stdin.isatty())) if pty_stdout: pumps.append( io.Pump(pty_stdout, io.Stream(self.stdout), propagate_close=False)) if pty_stderr: pumps.append( io.Pump(pty_stderr, io.Stream(self.stderr), propagate_close=False)) if not self._container_info()['State']['Running']: self.client.start(self.container, **kwargs) return pumps
def start(self, sockets=None, **kwargs): """ start execution """ stream = sockets or self.sockets() pumps = [] if self.interactive: pumps.append(io.Pump(io.Stream(self.stdin), stream, wait_for_output=False)) pumps.append(io.Pump(stream, io.Stream(self.stdout), propagate_close=False)) # FIXME: since exec_start returns a single socket, how do we # distinguish between stdout and stderr? # pumps.append(io.Pump(stream, io.Stream(self.stderr), propagate_close=False)) return pumps
def sockets(self): """ Return a single socket which is processing all I/O to exec """ socket = self.client.api.exec_start(self.exec_id, socket=True, tty=self.interactive) stream = io.Stream(socket) if self.is_process_tty(): return stream else: return io.Demuxer(stream)
def test_close_with_pending_data(self): a, b = socket.socketpair() a = WriteLimitedWrapper(a, 5) stream = io.Stream(a) stream.write(b'123456789') stream.close() expect(is_fd_closed(a.fileno())).to(be_false) stream.do_write() expect(is_fd_closed(a.fileno())).to(be_true)
def start(self, **kwargs): """ Present the PTY of the container inside the current process. This will take over the current process' TTY until the container's PTY is closed. """ pty_stdin, pty_stdout, pty_stderr = self.sockets() pumps = [] if pty_stdin and self.interactive: pumps.append( io.Pump(io.Stream(self.stdin), pty_stdin, wait_for_output=False)) if pty_stdout: pumps.append( io.Pump(pty_stdout, io.Stream(self.stdout), propagate_close=False)) if pty_stderr: pumps.append( io.Pump(pty_stderr, io.Stream(self.stderr), propagate_close=False)) if not self.container_info()['State']['Running']: self.client.start(self.container, **kwargs) flags = [p.set_blocking(False) for p in pumps] try: with WINCHHandler(self): self._hijack_tty(pumps) finally: if flags: for (pump, flag) in zip(pumps, flags): io.set_blocking(pump, flag)
def attach_socket(key): if info['Config']['Attach{0}'.format(key.capitalize())]: socket = self.client.api.attach_socket( self.container.name, {key: 1, 'stream': 1, 'logs': self.logs}, ) stream = io.Stream(socket) if info['Config']['Tty']: return stream else: return io.Demuxer(stream) else: return None
def test_partial_writes(self): a, b = socket.socketpair() a = WriteLimitedWrapper(a, 5) stream = io.Stream(a) written = stream.write(b'123456789') expect(written).to(equal(9)) read = b.recv(1024) expect(read).to(equal(b'12345')) expect(stream.needs_write()).to(be_true) stream.do_write() read = b.recv(1024) expect(read).to(equal(b'6789')) expect(stream.needs_write()).to(be_false)
def test_read_from_file(self): with tempfile.TemporaryFile() as f: stream = io.Stream(f) f.write(b'test') f.seek(0) expect(stream.read(32)).to(equal(b'test'))
def test_repr(self): fd = StringIO() stream = io.Stream(fd) expect(repr(stream)).to(equal("Stream(%s)" % fd))
def test_write_returns_none_when_no_data(self): stream = io.Stream(StringIO()) expect(stream.write('')).to(be_none)
def test_read_from_socket(self): a, b = socket.socketpair() a.send(b'test') stream = io.Stream(b) expect(stream.read(32)).to(equal(b'test'))
def test_fileno_delegates_to_file_descriptor(self): stream = io.Stream(sys.stdout) expect(stream.fileno()).to(equal(sys.stdout.fileno()))
def test_write_to_socket(self): a, b = socket.socketpair() stream = io.Stream(a) stream.write(b'test') expect(b.recv(32)).to(equal(b'test'))
def test_write_returns_length_written(self): with tempfile.TemporaryFile() as f: stream = io.Stream(f) expect(stream.write(b'test')).to(equal(4))
def test_write_to_file(self): with tempfile.TemporaryFile() as f: stream = io.Stream(f) stream.write(b'test') f.seek(0) expect(f.read(32)).to(equal(b'test'))
def test_read_returns_empty_string_at_eof(self): with tempfile.TemporaryFile() as f: stream = io.Stream(f) expect(stream.read(32)).to(equal(b''))
def test_close(self): a, b = socket.socketpair() stream = io.Stream(a) stream.close() expect(is_fd_closed(a.fileno())).to(be_true)