Use dockerpty instead for pseudo-tty behaviour.

Signed-off-by: Chris Corbyn <chris@w3style.co.uk>
This commit is contained in:
Chris Corbyn 2014-06-25 13:54:57 +00:00
parent 256dccc554
commit 3770aac1af
3 changed files with 4 additions and 142 deletions

View File

@ -6,6 +6,7 @@ import re
import signal
from inspect import getdoc
import dockerpty
from .. import __version__
from ..project import NoSuchService, ConfigurationError
@ -18,7 +19,6 @@ from .utils import yesno
from ..packages.docker.errors import APIError
from .errors import UserError
from .docopt_command import NoSuchCommand
from .socketclient import SocketClient
log = logging.getLogger(__name__)
@ -240,9 +240,8 @@ class TopLevelCommand(Command):
service.start_container(container, ports=None, one_off=True)
print(container.name)
else:
with self._attach_to_container(container.id, raw=tty) as c:
service.start_container(container, ports=None, one_off=True)
c.run()
service.start_container(container, ports=None, one_off=True)
dockerpty.start(self.client, container.id)
exit_code = container.wait()
if options['--rm']:
log.info("Removing %s..." % container.name)
@ -341,17 +340,5 @@ class TopLevelCommand(Command):
print("Gracefully stopping... (press Ctrl+C again to force)")
self.project.stop(service_names=service_names)
def _attach_to_container(self, container_id, raw=False):
socket_in = self.client.attach_socket(container_id, params={'stdin': 1, 'stream': 1})
socket_out = self.client.attach_socket(container_id, params={'stdout': 1, 'logs': 1, 'stream': 1})
socket_err = self.client.attach_socket(container_id, params={'stderr': 1, 'logs': 1, 'stream': 1})
return SocketClient(
socket_in=socket_in,
socket_out=socket_out,
socket_err=socket_err,
raw=raw,
)
def list_containers(containers):
return ", ".join(c.name for c in containers)

View File

@ -1,126 +0,0 @@
from __future__ import print_function
# Adapted from https://github.com/benthor/remotty/blob/master/socketclient.py
import sys
import tty
import fcntl
import os
import termios
import threading
import errno
import logging
log = logging.getLogger(__name__)
class SocketClient:
def __init__(self,
socket_in=None,
socket_out=None,
socket_err=None,
raw=True,
):
self.socket_in = socket_in
self.socket_out = socket_out
self.socket_err = socket_err
self.raw = raw
self.stdin_fileno = sys.stdin.fileno()
def __enter__(self):
self.create()
return self
def __exit__(self, type, value, trace):
self.destroy()
def create(self):
if os.isatty(sys.stdin.fileno()):
self.settings = termios.tcgetattr(sys.stdin.fileno())
else:
self.settings = None
if self.socket_in is not None:
self.set_blocking(sys.stdin, False)
self.set_blocking(sys.stdout, True)
self.set_blocking(sys.stderr, True)
if self.raw:
tty.setraw(sys.stdin.fileno())
def set_blocking(self, file, blocking):
fd = file.fileno()
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
flags = (flags & ~os.O_NONBLOCK) if blocking else (flags | os.O_NONBLOCK)
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
def run(self):
if self.socket_in is not None:
self.start_background_thread(target=self.send, args=(self.socket_in, sys.stdin))
recv_threads = []
if self.socket_out is not None:
recv_threads.append(self.start_background_thread(target=self.recv, args=(self.socket_out, sys.stdout)))
if self.socket_err is not None:
recv_threads.append(self.start_background_thread(target=self.recv, args=(self.socket_err, sys.stderr)))
for t in recv_threads:
t.join()
def start_background_thread(self, **kwargs):
thread = threading.Thread(**kwargs)
thread.daemon = True
thread.start()
return thread
def recv(self, socket, stream):
try:
while True:
chunk = socket.recv(4096)
if chunk:
stream.write(chunk)
stream.flush()
else:
break
except Exception as e:
log.debug(e)
def send(self, socket, stream):
while True:
chunk = stream.read(1)
if chunk == '':
socket.close()
break
else:
try:
socket.send(chunk)
except Exception as e:
if hasattr(e, 'errno') and e.errno == errno.EPIPE:
break
else:
raise e
def destroy(self):
if self.settings is not None:
termios.tcsetattr(self.stdin_fileno, termios.TCSADRAIN, self.settings)
sys.stdout.flush()
if __name__ == '__main__':
import websocket
if len(sys.argv) != 2:
sys.stderr.write("Usage: python socketclient.py WEBSOCKET_URL\n")
sys.exit(1)
url = sys.argv[1]
socket = websocket.create_connection(url)
print("connected\r")
with SocketClient(socket, interactive=True) as client:
client.run()

View File

@ -3,3 +3,4 @@ PyYAML==3.10
requests==2.2.1
texttable==0.8.1
websocket-client==0.11.0
dockerpty==0.0.8