/
start_container_interceptor.go
76 lines (70 loc) · 2.37 KB
/
start_container_interceptor.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
package proxy
import (
"net/http"
"strings"
)
type startContainerInterceptor struct{ proxy *Proxy }
func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
container, err := inspectContainerInPath(i.proxy.client, r.URL.Path)
if err != nil {
return err
}
// If the client has sent some JSON which might be a HostConfig, add our
// parameters back into it, otherwise Docker will consider them overwritten
if containerShouldAttach(container) && r.Header.Get("Content-Type") == "application/json" && r.ContentLength > 0 {
params := map[string]interface{}{}
if err := unmarshalRequestBody(r, ¶ms); err != nil {
return err
}
// HostConfig can be sent either as a struct named HostConfig, or unnamed at top level
var hostConfig map[string]interface{}
if subParam, found := params["HostConfig"]; found {
if typecast, ok := subParam.(map[string]interface{}); ok {
hostConfig = typecast
}
// We can't reliably detect what Docker will see as a top-level HostConfig,
// so just assume any parameter at top level indicates there is one.
} else if len(params) > 0 {
hostConfig = params
}
if hostConfig != nil {
networkMode, err := jsonObject(hostConfig).String("NetworkMode")
if err != nil {
return err
}
if strings.HasPrefix(networkMode, "container:") || networkMode == "host" {
if err := addVolume(hostConfig, i.proxy.weaveWaitNoopVolume, "/w", "ro"); err != nil {
return err
}
} else {
if i.proxy.NoMulticastRoute {
if err := addVolume(hostConfig, i.proxy.weaveWaitNomcastVolume, "/w", "ro"); err != nil {
return err
}
} else {
if err := addVolume(hostConfig, i.proxy.weaveWaitVolume, "/w", "ro"); err != nil {
return err
}
}
if !i.proxy.WithoutDNS {
if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, i.proxy.DNSDomain); err != nil {
return err
}
}
}
// Note we marshal the original top-level dictionary to avoid disturbing anything else
if err := marshalRequestBody(r, params); err != nil {
return err
}
}
}
i.proxy.createWait(r, container.ID)
return nil
}
func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error {
defer i.proxy.removeWait(r.Request)
if r.StatusCode < 200 || r.StatusCode >= 300 { // Docker didn't do the start
return nil
}
return i.proxy.waitForStart(r.Request)
}