From 63339c026dc5f7ba1053ca33812e859cca151d83 Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Tue, 20 Oct 2015 11:46:13 +0100 Subject: [PATCH] [proxy] return errors when attaching new containers I had implemented this with a promise, but was informed that as waitForStart is only called once, we are safe to just put the error into the channel. --- proxy/proxy.go | 26 ++++++++++++++------------ proxy/start_container_interceptor.go | 3 +-- test/695_proxy_failure_modes_test.sh | 12 ++++++++++++ 3 files changed, 27 insertions(+), 14 deletions(-) create mode 100755 test/695_proxy_failure_modes_test.sh diff --git a/proxy/proxy.go b/proxy/proxy.go index 81d8e79c..7b88f745 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 { @@ -304,11 +305,11 @@ func (proxy *Proxy) ContainerStarted(ident string) { } // If this was a container we modified the entrypoint for, attach it to the network if containerShouldAttach(container) { - proxy.attach(container, true) + err = proxy.attach(container, true) } else if containerIsWeaveRouter(container) { - proxy.attachRouter(container) + err = proxy.attachRouter(container) } - proxy.notifyWaiters(container.ID) + proxy.notifyWaiters(container.ID, err) } func containerShouldAttach(container *docker.Container) bool { @@ -321,8 +322,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 +332,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 +354,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