-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsdocker.go
154 lines (129 loc) · 3.99 KB
/
sdocker.go
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
package main
import "os"
import "log"
import "fmt"
import "flag"
import "os/exec"
import "strings"
import "syscall"
import "net/url"
import "io/ioutil"
func main() {
// Run a nested docker command and return its exit status
status := run()
os.Exit(status)
}
func run() int {
// Used to turn on debugging output
verbose := false
if os.Getenv("SDOCKER_DEBUG") != "" {
verbose = true
}
// Parse command line flags (we will forward these to the
// underlying docker process)
flag.Parse()
// Get the existing value for DOCKER_HOST
dh := os.Getenv("DOCKER_HOST")
// Check if it is empty
if dh != "" {
// ...and if it as URL
dhurl, err := url.Parse(dh)
// ...and if uses the ssh scheme (otherwise, we do absolutely nothing)
if err == nil && dhurl.Scheme == "ssh" {
// Get hostname information and split it at the ":" if present
hostname := strings.Split(dhurl.Host, ":")
// Now extract out the remote host and remote port number
host := hostname[0]
rport := "4243" // This is the default if no remote port is specified
if len(hostname) == 2 {
host = hostname[0]
rport = hostname[1]
} else if len(hostname) > 2 {
log.Fatalf("Unable to determine hostname and port from '%s'", dhurl.Host)
}
// Now assume the (same) default to open here on the localhost
lport := "4243"
if dhurl.Path != "" {
// Unless there is a path component in the DOCKER_HOST. In that
// case, use the path as the port number. Odd choice for a port
// number, but nothing else seems better.
lport = dhurl.Path[1:]
}
// Finally, see if they specified a user
user := ""
if dhurl.User != nil {
user = dhurl.User.Username()
}
// Now, we need to start building args for the call to 'ssh'
dest := host
if user != "" {
dest = fmt.Sprintf("%s@%s", user, host)
}
// Create a temporary file to use as the socket control file
tmp, err := ioutil.TempFile("", "sdocker_")
if err != nil {
log.Fatal(err.Error())
}
// We don't need the actual file, just the name.
os.Remove(tmp.Name())
if verbose {
log.Printf("Tunnel from localhost:%s to %s:%s", lport, dest, rport)
}
// This command starts the socket
start := exec.Command("ssh", "-M", "-S", tmp.Name(),
"-fnNT", "-L", fmt.Sprintf("%s:localhost:%s", lport, rport), dest)
terr := start.Run()
// If it fails, we exit
if terr != nil {
log.Fatalf("Unable to open tunnel: %v", terr)
}
// This will clean everything up when we are done
defer func() {
// Close ssh tunnel
stop := exec.Command("ssh", "-S", tmp.Name(),
"-O", "exit", dest)
err = stop.Run()
if err != nil {
log.Printf("Error closing tunnel: %v", err)
}
if verbose {
log.Printf("Tunnel closed and control socket file removed")
}
}()
// Now formulate the value of DOCKER_HOST to pass to our nested
// invocation of docker
ndh := fmt.Sprintf("tcp://localhost:%s", lport)
if verbose {
log.Printf("Running nested docker command with DOCKER_HOST='%s'", ndh)
}
// ...and assign it to the environment
os.Setenv("DOCKER_HOST", ndh)
}
}
// Here is where we call the nested docker command
cmd := exec.Command("docker", flag.Args()...)
// We completely connect stdin, stdout and stderr error so this
// command looks just like the nested docker process
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
// We need to set the environment in case it has changed
cmd.Env = os.Environ()
// Now run the command and extract the exit status one way...
if err := cmd.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
waitStatus := exitError.Sys().(syscall.WaitStatus)
return waitStatus.ExitStatus()
}
}
waitStatus := cmd.ProcessState.Sys().(syscall.WaitStatus)
if cmd.Process == nil {
fmt.Printf("Error running subordinate docker command (is it in your path?)\n")
return 1
}
/*
state, _ := cmd.Process.Wait()
waitStatus := state.Sys().(syscall.WaitStatus)
*/
return waitStatus.ExitStatus()
}