From 5347098defaf4671205c1f2317d83b0f18b39a59 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 2 Feb 2016 16:46:37 -0800 Subject: [PATCH] support disconnect -f and use random engine Signed-off-by: Victor Vieux --- api/handlers.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++-- api/primary.go | 4 ++-- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/api/handlers.go b/api/handlers.go index e34ac36f75..296be12cc2 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -881,8 +881,64 @@ func ping(c *context, w http.ResponseWriter, r *http.Request) { w.Write([]byte{'O', 'K'}) } -// Proxy network to container operations, including connect/disconnect request -func proxyNetworkContainerOperation(c *context, w http.ResponseWriter, r *http.Request) { +// POST /networks/{networkid:.*}/disconnect +func proxyNetworkDisconnect(c *context, w http.ResponseWriter, r *http.Request) { + var networkid = mux.Vars(r)["networkid"] + network := c.cluster.Networks().Uniq().Get(networkid) + if network == nil { + httpError(w, fmt.Sprintf("No such network: %s", networkid), http.StatusNotFound) + return + } + // Set the network ID in the proxied URL path. + r.URL.Path = strings.Replace(r.URL.Path, networkid, network.ID, 1) + + // make a copy of r.Body + buf, _ := ioutil.ReadAll(r.Body) + bodyCopy := ioutil.NopCloser(bytes.NewBuffer(buf)) + defer bodyCopy.Close() + // restore r.Body stream as it'll be read again + r.Body = ioutil.NopCloser(bytes.NewBuffer(buf)) + + // Extract container info from r.Body copy + var disconnect dockerclient.NetworkDisconnect + if err := json.NewDecoder(bodyCopy).Decode(&disconnect); err != nil { + httpError(w, fmt.Sprintf("Container is not specified"), http.StatusNotFound) + return + } + + var engine *cluster.Engine + + if disconnect.Force && network.Scope == "global" { + randomEngine, err := c.cluster.RANDOMENGINE() + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + engine = randomEngine + } else { + container := c.cluster.Container(disconnect.Container) + if container == nil { + httpError(w, fmt.Sprintf("No such container: %s", disconnect.Container), http.StatusNotFound) + return + } + engine = container.Engine + } + + cb := func(resp *http.Response) { + // force fresh networks on this engine + engine.RefreshNetworks() + } + + // request is forwarded to the container's address + err := proxyAsync(c.tlsConfig, engine.Addr, w, r, cb) + engine.CheckConnectionErr(err) + if err != nil { + httpError(w, err.Error(), http.StatusNotFound) + } +} + +// POST /networks/{networkid:.*}/connect +func proxyNetworkConnect(c *context, w http.ResponseWriter, r *http.Request) { var networkid = mux.Vars(r)["networkid"] network := c.cluster.Networks().Uniq().Get(networkid) if network == nil { diff --git a/api/primary.go b/api/primary.go index e01626bff3..598e4a78a1 100644 --- a/api/primary.go +++ b/api/primary.go @@ -80,8 +80,8 @@ var routes = map[string]map[string]handler{ "/exec/{execid:.*}/start": postExecStart, "/exec/{execid:.*}/resize": proxyContainer, "/networks/create": postNetworksCreate, - "/networks/{networkid:.*}/connect": proxyNetworkContainerOperation, - "/networks/{networkid:.*}/disconnect": proxyNetworkContainerOperation, + "/networks/{networkid:.*}/connect": proxyNetworkConnect, + "/networks/{networkid:.*}/disconnect": proxyNetworkDisconnect, "/volumes/create": postVolumesCreate, }, "PUT": {