diff --git a/api/api.go b/api/api.go index a201f9d9d2..a1d23a8158 100644 --- a/api/api.go +++ b/api/api.go @@ -15,7 +15,6 @@ import ( log "github.com/Sirupsen/logrus" dockerfilters "github.com/docker/docker/pkg/parsers/filters" "github.com/docker/swarm/cluster" - "github.com/docker/swarm/cluster/swarm" "github.com/docker/swarm/scheduler/filter" "github.com/docker/swarm/version" "github.com/gorilla/mux" @@ -261,32 +260,50 @@ func getEvents(c *context, w http.ResponseWriter, r *http.Request) { c.eventsHandler.Wait(r.RemoteAddr) } -// GET /_ping -func ping(c *context, w http.ResponseWriter, r *http.Request) { - w.Write([]byte{'O', 'K'}) -} - -// Proxy a request to the right node and do a force refresh -func proxyContainerAndForceRefresh(c *context, w http.ResponseWriter, r *http.Request) { - container, err := getContainerFromVars(c, mux.Vars(r)) - if err != nil { - httpError(w, err.Error(), http.StatusNotFound) +// POST /containers/{name:.*}/exec +func postContainersExec(c *context, w http.ResponseWriter, r *http.Request) { + name := mux.Vars(r)["name"] + container := c.cluster.Container(name) + if container == nil { + httpError(w, fmt.Sprintf("No such container %s", name), http.StatusNotFound) return } - cb := func(resp *http.Response) { - if resp.StatusCode == http.StatusCreated { - log.Debugf("[REFRESH CONTAINER] --> %s", container.Id) - if n, ok := container.Node.(*swarm.Node); ok { - n.RefreshContainer(container.Id, true) - } - } - } + client, scheme := newClientAndScheme(c.tlsConfig) - if err := proxyAsync(c.tlsConfig, container.Node.Addr(), w, r, cb); err != nil { + resp, err := client.Post(scheme+"://"+container.Node.Addr()+"/containers/"+container.Id+"/exec", "application/json", r.Body) + if err != nil { httpError(w, err.Error(), http.StatusInternalServerError) + return } + // cleanup + defer resp.Body.Close() + defer closeIdleConnections(client) + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + + id := struct{ Id string }{} + + if err := json.Unmarshal(data, &id); err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + + // add execID to the container, so the later exec/start will work + container.Info.ExecIDs = append(container.Info.ExecIDs, id.Id) + + w.Header().Set("Content-Type", "application/json") + w.Write(data) +} + +// GET /_ping +func ping(c *context, w http.ResponseWriter, r *http.Request) { + w.Write([]byte{'O', 'K'}) } // Proxy a request to the right node @@ -415,7 +432,7 @@ func createRouter(c *context, enableCors bool) *mux.Router { "/containers/{name:.*}/resize": proxyContainer, "/containers/{name:.*}/attach": proxyHijack, "/containers/{name:.*}/copy": proxyContainer, - "/containers/{name:.*}/exec": proxyContainerAndForceRefresh, + "/containers/{name:.*}/exec": postContainersExec, "/exec/{execid:.*}/start": proxyHijack, "/exec/{execid:.*}/resize": proxyContainer, }, diff --git a/api/utils.go b/api/utils.go index feb094a212..ce11af27cb 100644 --- a/api/utils.go +++ b/api/utils.go @@ -57,7 +57,7 @@ func closeIdleConnections(client *http.Client) { } } -func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request, callback func(*http.Response)) error { +func proxy(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request) error { // Use a new client for each request client, scheme := newClientAndScheme(tlsConfig) // RequestURI may not be sent to client @@ -72,10 +72,6 @@ func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *ht return err } - if callback != nil { - callback(resp) - } - copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) io.Copy(NewWriteFlusher(w), resp.Body) @@ -87,10 +83,6 @@ func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *ht return nil } -func proxy(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request) error { - return proxyAsync(tlsConfig, addr, w, r, nil) -} - func hijack(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request) error { if parts := strings.SplitN(addr, "://", 2); len(parts) == 2 { addr = parts[1]