diff --git a/proxy/client.go b/proxy/client.go index ac52cd49..08e0a59f 100644 --- a/proxy/client.go +++ b/proxy/client.go @@ -33,7 +33,7 @@ func (c *client) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } if err != nil { - http.Error(w, "Unable to create proxied request", http.StatusInternalServerError) + http.Error(w, "Unable to intercept request", http.StatusInternalServerError) Warning.Print("Error intercepting request: ", err) return } @@ -49,7 +49,7 @@ func (c *client) ServeHTTP(w http.ResponseWriter, r *http.Request) { resp, err := client.Do(req) if err != nil && err != httputil.ErrPersistEOF { - http.Error(w, fmt.Sprintf("Could not make request to target: %s", err.Error()), http.StatusInternalServerError) + http.Error(w, fmt.Sprintf("Could not make request to target: %v", err), http.StatusInternalServerError) Warning.Print("Error forwarding request: ", err) return } diff --git a/proxy/create_container_interceptor.go b/proxy/create_container_interceptor.go index 12d04df9..d08cb2d8 100644 --- a/proxy/create_container_interceptor.go +++ b/proxy/create_container_interceptor.go @@ -34,7 +34,7 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) (*http.Re } if _, ok := weaveCIDRsFromConfig(container.Config); ok { - i.addToVolumesFrom(container.HostConfig, "weaveproxy") + container.HostConfig.VolumesFrom = append(container.HostConfig.VolumesFrom, "weaveproxy") if err := i.setWeaveWaitEntrypoint(container.Config); err != nil { return nil, err } @@ -53,10 +53,6 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) (*http.Re return r, nil } -func (i *createContainerInterceptor) addToVolumesFrom(config *docker.HostConfig, mounts ...string) { - config.VolumesFrom = append(config.VolumesFrom, mounts...) -} - func (i *createContainerInterceptor) setWeaveWaitEntrypoint(container *docker.Config) error { var image *docker.Config if !configHasEntrypoint(container) || !configHasCmd(container) { @@ -104,6 +100,6 @@ func (i *createContainerInterceptor) setWeaveDNS(container *createContainerReque return nil } -func (i *createContainerInterceptor) InterceptResponse(res *http.Response) (*http.Response, error) { - return res, nil +func (i *createContainerInterceptor) InterceptResponse(r *http.Response) (*http.Response, error) { + return r, nil } diff --git a/proxy/proxy.go b/proxy/proxy.go index a87fc90c..7681230e 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -11,6 +11,11 @@ import ( . "github.com/weaveworks/weave/common" ) +var ( + containerCreateRegexp = regexp.MustCompile("/v[0-9\\.]*/containers/create") + containerStartRegexp = regexp.MustCompile("^/v[0-9\\.]*/containers/[^/]*/(re)?start$") +) + type Proxy struct { Dial func() (net.Conn, error) client *docker.Client @@ -36,9 +41,18 @@ func NewProxy(targetURL string, withDNS bool) (*Proxy, error) { if err != nil { return nil, err } + + targetAddr := "" + switch u.Scheme { + case "tcp": + targetAddr = u.Host + case "unix": + targetAddr = u.Path + } + return &Proxy{ Dial: func() (net.Conn, error) { - return net.Dial(targetNetwork(u), targetAddress(u)) + return net.Dial(u.Scheme, targetAddr) }, client: client, withDNS: withDNS, @@ -46,60 +60,21 @@ func NewProxy(targetURL string, withDNS bool) (*Proxy, error) { }, nil } -func targetNetwork(u *url.URL) string { - return u.Scheme -} - -func targetAddress(u *url.URL) (addr string) { - switch u.Scheme { - case "tcp": - addr = u.Host - case "unix": - addr = u.Path - } - return -} - -func isWeaveStatus(r *http.Request) bool { - return strings.HasPrefix(r.URL.Path, "/weave") -} - -func isCreateContainer(r *http.Request) bool { - ok, err := regexp.MatchString("/v[0-9\\.]*/containers/create", r.URL.Path) - return err == nil && ok -} - -func isStartContainer(r *http.Request) bool { - ok, err := regexp.MatchString("^/v[0-9\\.]*/containers/[^/]*/(re)?start$", r.URL.Path) - return err == nil && ok -} - func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { Info.Printf("%s %s", r.Method, r.URL) + path := r.URL.Path switch { - case isCreateContainer(r): - proxy.createContainer(w, r) - case isStartContainer(r): - proxy.startContainer(w, r) - case isWeaveStatus(r): - proxy.weaveStatus(w, r) + case containerCreateRegexp.MatchString(path): + proxy.serveWithInterceptor(&createContainerInterceptor{proxy.client, proxy.withDNS, proxy.dockerBridgeIP}, w, r) + case containerStartRegexp.MatchString(path): + proxy.serveWithInterceptor(&startContainerInterceptor{proxy.client, proxy.withDNS}, w, r) + case strings.HasPrefix(path, "/weave"): + w.WriteHeader(http.StatusOK) default: - proxy.proxyRequest(w, r) + proxy.serveWithInterceptor(&nullInterceptor{}, w, r) } } -func (proxy *Proxy) weaveStatus(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) -} - -func (proxy *Proxy) createContainer(w http.ResponseWriter, r *http.Request) { - newClient(proxy.Dial, &createContainerInterceptor{proxy.client, proxy.withDNS, proxy.dockerBridgeIP}).ServeHTTP(w, r) -} - -func (proxy *Proxy) startContainer(w http.ResponseWriter, r *http.Request) { - newClient(proxy.Dial, &startContainerInterceptor{proxy.client, proxy.withDNS}).ServeHTTP(w, r) -} - -func (proxy *Proxy) proxyRequest(w http.ResponseWriter, r *http.Request) { - newClient(proxy.Dial, &nullInterceptor{}).ServeHTTP(w, r) +func (proxy *Proxy) serveWithInterceptor(i interceptor, w http.ResponseWriter, r *http.Request) { + newClient(proxy.Dial, i).ServeHTTP(w, r) } diff --git a/proxy/start_container_interceptor.go b/proxy/start_container_interceptor.go index c7fa4b8b..4049a107 100644 --- a/proxy/start_container_interceptor.go +++ b/proxy/start_container_interceptor.go @@ -9,6 +9,8 @@ import ( . "github.com/weaveworks/weave/common" ) +var containerIDRegexp = regexp.MustCompile("^/v[0-9\\.]*/containers/([^/]*)/.*") + type startContainerInterceptor struct { client *docker.Client withDNS bool @@ -18,39 +20,33 @@ func (i *startContainerInterceptor) InterceptRequest(r *http.Request) (*http.Req return r, nil } -func (i *startContainerInterceptor) InterceptResponse(res *http.Response) (*http.Response, error) { - containerID := containerFromPath(res.Request.URL.Path) +func (i *startContainerInterceptor) InterceptResponse(r *http.Response) (*http.Response, error) { + containerID := "" + if subs := containerIDRegexp.FindStringSubmatch(r.Request.URL.Path); subs == nil { + Warning.Printf("No container id found in request with path %s", r.Request.URL.Path) + return r, nil + } else { + containerID = subs[1] + } container, err := i.client.InspectContainer(containerID) if err != nil { - Warning.Print("Error Inspecting Container: ", err) - return res, nil + Warning.Printf("Error inspecting container %s: %v", containerID, err) + return r, nil } - if cidrs, ok := weaveCIDRsFromConfig(container.Config); ok { - Info.Printf("Container %s was started with CIDR \"%s\"", containerID, strings.Join(cidrs, " ")) - if err := i.attachContainerToWeave(containerID, cidrs); err != nil { - Warning.Print("Attaching container to weave failed: ", err) - return res, nil - } - } else { + cidrs, ok := weaveCIDRsFromConfig(container.Config) + if !ok { Debug.Print("No Weave CIDR, ignoring") + return r, nil } - - return res, nil -} - -func containerFromPath(path string) string { - if subs := regexp.MustCompile("^/v[0-9\\.]*/containers/([^/]*)/.*").FindStringSubmatch(path); subs != nil { - return subs[1] - } - return "" -} - -func (i *startContainerInterceptor) attachContainerToWeave(containerID string, cidrs []string) error { + Info.Printf("Container %s was started with CIDR \"%s\"", containerID, strings.Join(cidrs, " ")) args := []string{"attach"} args = append(args, cidrs...) args = append(args, containerID) - _, err := callWeave(args...) - return err + if _, err := callWeave(args...); err != nil { + Warning.Printf("Attaching container %s to weave failed: %v", containerID, err) + return r, nil + } + return r, nil }