From 7ad8a3705f191dc27296996c36cc1a8b055f6c1a Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 20 Jan 2015 18:39:52 +0000 Subject: [PATCH] add support for pull and rmi Signed-off-by: Victor Vieux --- api/README.md | 2 +- api/api.go | 30 +++++++++++++++++++++++++++++- cluster/cluster.go | 2 ++ cluster/swarm/cluster.go | 8 ++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/api/README.md b/api/README.md index 7c25d88b93..d1f7491962 100644 --- a/api/README.md +++ b/api/README.md @@ -18,7 +18,7 @@ GET "/containers/{name:.*}/attach/ws" POST "/commit" POST "/build" -POST "/images/create" +POST "/images/create" (pull implemented) POST "/images/load" POST "/images/{name:.*}/push" POST "/images/{name:.*}/tag" diff --git a/api/api.go b/api/api.go index f183213b79..a9e375e82b 100644 --- a/api/api.go +++ b/api/api.go @@ -247,6 +247,34 @@ func deleteContainers(c *context, w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } +// POST /images/create +func postImagesCreate(c *context, w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + + wf := NewWriteFlusher(w) + + if image := r.Form.Get("fromImage"); image != "" { //pull + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + + if tag := r.Form.Get("tag"); tag != "" { + image += ":" + tag + } + begin := func(name string) { + fmt.Fprintf(wf, "{%q:%q,%q:\"Pulling %s...\",%q:{}}", "id", name, "status", image, "progressDetail") + } + end := func(name string) { + fmt.Fprintf(wf, "{%q:%q,%q:\"Pulling %s... : downloaded\",%q:{}}", "id", name, "status", image, "progressDetail") + } + c.cluster.Pull(image, begin, end) + } else { //import + httpError(w, "Not supported in clustering mode.", http.StatusNotImplemented) + } +} + // GET /events func getEvents(c *context, w http.ResponseWriter, r *http.Request) { c.eventsHandler.Add(r.RemoteAddr, w) @@ -416,7 +444,7 @@ func createRouter(c *context, enableCors bool) *mux.Router { "/auth": proxyRandom, "/commit": notImplementedHandler, "/build": notImplementedHandler, - "/images/create": notImplementedHandler, + "/images/create": postImagesCreate, "/images/load": notImplementedHandler, "/images/{name:.*}/push": notImplementedHandler, "/images/{name:.*}/tag": notImplementedHandler, diff --git a/cluster/cluster.go b/cluster/cluster.go index 986c878bd4..899cec97ac 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -11,5 +11,7 @@ type Cluster interface { Containers() []*Container Container(IdOrName string) *Container + Pull(name string, begin, end func(string)) + Info() [][2]string } diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index 1603547320..9fb30a4147 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -186,6 +186,14 @@ func (c *Cluster) Image(IdOrName string) *cluster.Image { return nil } +func (c *Cluster) Pull(name string, begin, end func(string)) { + for _, node := range c.nodes { + begin(node.Name()) + node.Pull(name) + end(node.Name()) + } +} + // Containers returns all the containers in the cluster. func (c *Cluster) Containers() []*cluster.Container { c.RLock()