diff --git a/proxy/proxy.go b/proxy/proxy.go index 81d8e79c..dc6bcfcf 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -59,7 +59,8 @@ type Config struct { type wait struct { ident string - ch chan struct{} + ch chan error + done bool } type Proxy struct { @@ -296,19 +297,17 @@ func (proxy *Proxy) listen(protoAndAddr string) (net.Listener, string, error) { // weavedocker.ContainerObserver interface func (proxy *Proxy) ContainerStarted(ident string) { container, err := proxy.client.InspectContainer(ident) - if err != nil { - if _, ok := err.(*docker.NoSuchContainer); !ok { - Log.Warningf("unable to attach new container %s since inspecting it failed: %v", ident, err) + if err == nil { + if containerShouldAttach(container) { + err = proxy.attach(container, true) + } else if containerIsWeaveRouter(container) { + err = proxy.attachRouter(container) } - return } - // If this was a container we modified the entrypoint for, attach it to the network - if containerShouldAttach(container) { - proxy.attach(container, true) - } else if containerIsWeaveRouter(container) { - proxy.attachRouter(container) + if _, ok := err.(*docker.NoSuchContainer); err != nil && !ok { + Log.Warningf("unable to attach new container %s since inspecting it failed: %v", ident, err) } - proxy.notifyWaiters(container.ID) + proxy.notifyWaiters(ident, err) } func containerShouldAttach(container *docker.Container) bool { @@ -321,8 +320,7 @@ func containerIsWeaveRouter(container *docker.Container) bool { func (proxy *Proxy) createWait(r *http.Request, ident string) { proxy.Lock() - ch := make(chan struct{}) - proxy.waiters[r] = &wait{ident: ident, ch: ch} + proxy.waiters[r] = &wait{ident: ident, ch: make(chan error, 1)} proxy.Unlock() } @@ -332,19 +330,20 @@ func (proxy *Proxy) removeWait(r *http.Request) { proxy.Unlock() } -func (proxy *Proxy) notifyWaiters(ident string) { +func (proxy *Proxy) notifyWaiters(ident string, err error) { proxy.Lock() for _, wait := range proxy.waiters { - if ident == wait.ident && wait.ch != nil { + if ident == wait.ident && !wait.done { + wait.ch <- err close(wait.ch) - wait.ch = nil + wait.done = true } } proxy.Unlock() } -func (proxy *Proxy) waitForStart(r *http.Request) { - var ch chan struct{} +func (proxy *Proxy) waitForStart(r *http.Request) error { + var ch chan error proxy.Lock() wait, found := proxy.waiters[r] if found { @@ -353,8 +352,9 @@ func (proxy *Proxy) waitForStart(r *http.Request) { proxy.Unlock() if ch != nil { Log.Debugf("Wait for start of container %s", wait.ident) - <-ch + return <-ch } + return nil } func (proxy *Proxy) ContainerDied(ident string) { diff --git a/proxy/start_container_interceptor.go b/proxy/start_container_interceptor.go index 1d0d17df..e182a629 100644 --- a/proxy/start_container_interceptor.go +++ b/proxy/start_container_interceptor.go @@ -53,6 +53,5 @@ func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error { if r.StatusCode < 200 || r.StatusCode >= 300 { // Docker didn't do the start return nil } - i.proxy.waitForStart(r.Request) - return nil + return i.proxy.waitForStart(r.Request) } diff --git a/test/695_proxy_failure_modes_test.sh b/test/695_proxy_failure_modes_test.sh new file mode 100755 index 00000000..45679ae4 --- /dev/null +++ b/test/695_proxy_failure_modes_test.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +. ./config.sh + +start_suite "Proxy failure modes" + +# docker run should fail when weave router is not running +weave_on $HOST1 launch-proxy +assert_raises "proxy docker_on $HOST1 run --rm $SMALL_IMAGE true" 1 +assert_raises "proxy docker_on $HOST1 run --rm $SMALL_IMAGE true 2>&1 1>/dev/null | grep 'Error response from daemon: weave container is not present. Have you launched it?'" + +end_suite