-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdocker
executable file
·156 lines (125 loc) · 4.2 KB
/
docker
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env python
from __future__ import print_function
from contextlib import closing
import json
import os
import socket
import subprocess
import sys
try:
from urllib2 import urlopen, URLError
except:
from urllib.request import urlopen
from urllib.error import URLError
try:
from ConfigParser import ConfigParser
except:
from configparser import ConfigParser
def load_config(filepath):
cfg = ConfigParser()
with open(CONF_PATH) as conf:
cfg.readfp(conf)
return [(s[0].strip(), s[1].strip()) for s in cfg.items('dockers')]
CONF_PATH = os.path.join(
os.environ['HOME'],
'.dewya'
)
DOCKERS = load_config(CONF_PATH)
FORWARD_PORT = 4243
def getch():
"""Get single character from user.
http://code.activestate.com/recipes/134892/
"""
import sys
import tty
import termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def forward_port(docker_uri):
"""Forward local port to remote unix domain socket."""
host, port = docker_uri[6:], FORWARD_PORT
# execute unix=>tcp port forwarding on server
socat_cmd = 'ssh -f {} "socat {} {}" &>/dev/null'.format(
host,
'TCP4-LISTEN\:{},fork,reuseaddr'.format(port),
'UNIX-CONNECT\:/var/run/docker.sock',
)
subprocess.call(socat_cmd, shell=True)
# kill previous instance (fight with dangling connections)
kill_cmd = "kill `pgrep -f 'ssh -fN -L{port}.*{host}'` &>/dev/null".format(
port=port,
host=host
),
subprocess.call(kill_cmd, shell=True)
# execute port forwarding in background
forward_cmd = 'ssh -fN -L4243:127.0.0.1:{port} {host} &>/dev/null'.format(
port=port,
host=host
),
subprocess.call(forward_cmd, shell=True)
return 'tcp://localhost:{}'.format(port)
def main():
if not sys.stdout.isatty() or not sys.stdin.isatty():
print('dewya cannot be used in pipes', file=sys.stderr)
return -3
# if connection already configured in environment
if 'DOCKER_HOST' in os.environ:
docker_uri = os.environ['DOCKER_HOST']
os.environ['DOCKER_PS1'] = docker_uri
else:
for num, (name, addr) in enumerate(DOCKERS):
print('{}. {} ({})'.format(num, name, addr))
# read the id of awaited docker from user
num = None
while True:
num = ord(getch())
if num in [3, 4]:
return -1
elif num > 47 and num < (48 + len(DOCKERS)):
num -= 48
break
print(
'Please press {}'.format(
','.join(map(str, xrange(len(DOCKERS))))
)
)
docker_uri = DOCKERS[num][1]
os.environ['DOCKER_PS1'] = DOCKERS[num][0]
# forward port for "remote" docker
if docker_uri.startswith('ssh:'):
docker_uri = forward_port(docker_uri)
# check docker availability and fetch version
url = 'http://{}/version'.format(docker_uri[6:])
version = None
try:
with closing(urlopen(url, timeout=5)) as r:
version = json.loads(r.read().decode('utf-8'))['Version']
except (socket.timeout, URLError):
print('docker connection failed', file=sys.stderr)
return -2
# set path to real docker bin
client_path = '/usr/local/Cellar/docker/{}/bin'.format(version)
os.environ['PATH'] = '{}:{}'.format(client_path, os.environ['PATH'])
# configure env for docker client
os.environ['DOCKER_HOST'] = docker_uri
# ... and some nifty addon for shell prompt
ps1_docker = '\[\e[1;34m\]$DOCKER_PS1\[\e[00m\]|'
os.environ['PS1'] = ps1_docker + os.environ['PS1']
# re-create requested command and run it
docker_bin = '{}/docker'.format(client_path)
args = [docker_bin]
args.extend(sys.argv[1:])
subprocess.call(args)
# ... and start subshell
shell = os.environ['SHELL']
os.execl(shell, shell)
if __name__ == '__main__':
if not len(DOCKERS):
print('Please create config file ~/.dewya', file=sys.stderr)
sys.exit(main())