-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
123 lines (103 loc) · 2.49 KB
/
main.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
package main
import (
"fmt"
"log"
"net"
"net/url"
"os"
"path"
"github.com/fsouza/go-dockerclient"
)
type Stoppable interface {
Stop()
}
var proxiedPorts map[int]Stoppable
var b2dhost string
func main() {
endpoint := os.Getenv("DOCKER_HOST")
if endpoint == "" {
fmt.Println("Could not find DOCKER_HOST. You have to set the environment.")
os.Exit(2)
}
certpath := os.Getenv("DOCKER_CERT_PATH")
if certpath == "" {
fmt.Println("Could not find DOCKER_CERT_PATH. You have to set the environment.")
os.Exit(2)
}
parsed, err := url.ParseRequestURI(endpoint)
if err != nil {
panic(err)
}
b2dhost, _, err = net.SplitHostPort(parsed.Host)
if err != nil {
panic(err)
}
//todo handle non tls connections (ENV DOCKER_TLS_VERIFY)
client, err := docker.NewTLSClient(endpoint,
path.Join(certpath, "cert.pem"),
path.Join(certpath, "key.pem"),
path.Join(certpath, "ca.pem"))
if err != nil {
panic(err)
}
//initial read of ports
proxiedPorts = make(map[int]Stoppable)
log.Printf("Started b2dProxy. Now watching Docker for open ports ...\n")
updateports(client)
//now listen for events to update ports
events := make(chan *docker.APIEvents)
err = client.AddEventListener(events)
if err != nil {
panic(err)
}
for {
<-events //it does't matter what kind of update, just refresh the ports
updateports(client)
}
}
func updateports(client *docker.Client) {
containers, err := client.ListContainers(docker.ListContainersOptions{All: true})
if err != nil {
panic(err)
}
currentports := findCurrentPorts(containers)
removeOldPorts(currentports)
addNewPorts(currentports)
}
func findCurrentPorts(containers []docker.APIContainers) map[int]string {
currentports := make(map[int]string)
for _, container := range containers {
for _, port := range container.Ports {
if port.PublicPort != 0 {
currentports[int(port.PublicPort)] = port.Type
}
}
}
return currentports
}
func removeOldPorts(currentports map[int]string) {
for port, proxy := range proxiedPorts {
if currentports[port] == "" {
proxy.Stop()
delete(proxiedPorts, port)
}
}
}
func addNewPorts(currentports map[int]string) {
for port, ptype := range currentports {
if proxiedPorts[port] == nil {
if ptype == "udp" {
forwarder := NewUDPForwarder(b2dhost, port)
err := forwarder.start()
if err == nil {
proxiedPorts[port] = forwarder
}
} else {
newPort, err := NewSinglePortProxy(b2dhost, port)
if err == nil {
proxiedPorts[port] = newPort
}
}
}
}
}