From ccc32635d5f6bc72f909682f41f83b80197abfb6 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Fri, 10 Apr 2015 18:20:34 +0800 Subject: [PATCH 01/13] Add support Load Image Signed-off-by: Xian Chaobo --- api/handlers.go | 37 +++++++++++++++++++++++++++++++++++++ cluster/cluster.go | 6 ++++++ cluster/engine.go | 14 ++++++++++++++ cluster/swarm/cluster.go | 25 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/api/handlers.go b/api/handlers.go index 0671064982..98ea62f728 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -10,6 +10,9 @@ import ( "sort" "strconv" "strings" + "os" + "io" + "path" dockerfilters "github.com/docker/docker/pkg/parsers/filters" "github.com/docker/swarm/cluster" @@ -270,6 +273,40 @@ func postImagesCreate(c *context, w http.ResponseWriter, r *http.Request) { } } +// POST /images/load +func postImagesLoad(c *context, w http.ResponseWriter, r *http.Request) { + //cache tar file + tmpImageDir, err := ioutil.TempDir("", "docker-import-") + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + defer os.RemoveAll(tmpImageDir) + + repoTarFile := path.Join(tmpImageDir, "repo.tar") + tarFile, err := os.Create(repoTarFile) + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + if _, err := io.Copy(tarFile, r.Body); err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + tarFile.Close() + + // call cluster to load image on every node + wf := NewWriteFlusher(w) + callback := func(what, status string) { + if status == "" { + fmt.Fprintf(wf, "%s:Loading Image...\n", what) + } else { + fmt.Fprintf(wf, "%s:Loading Image... %s\n", what,status) + } + } + c.cluster.Load(repoTarFile, callback) +} + // GET /events func getEvents(c *context, w http.ResponseWriter, r *http.Request) { c.eventsHandler.Add(r.RemoteAddr, w) diff --git a/cluster/cluster.go b/cluster/cluster.go index 3b0beaab7d..4fb1a9891d 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -33,6 +33,12 @@ type Cluster interface { // `status` is the current status, like "", "in progress" or "downloaded Pull(name string, callback func(what, status string)) + // Load images + // `callback` can be called multiple time + // `what` is what is being loaded + // `status` is the current status, like "", "in progress" or "loaded" + Load(tarFile string, callback func(what, status string)) + // Return some info about the cluster, like nb or containers / images // It is pretty open, so the implementation decides what to return. Info() [][2]string diff --git a/cluster/engine.go b/cluster/engine.go index 81d26bc0e4..9b7084094c 100644 --- a/cluster/engine.go +++ b/cluster/engine.go @@ -8,6 +8,7 @@ import ( "strings" "sync" "time" + "os" log "github.com/Sirupsen/logrus" "github.com/samalba/dockerclient" @@ -411,6 +412,19 @@ func (e *Engine) Pull(image string) error { return nil } +// Load an image on the engine +func (e *Engine) Load(tarFile string) error { + file, err := os.Open(tarFile) + if err != nil { + return err + } + + if err := e.client.LoadImage(file); err != nil { + return err + } + return nil +} + // RegisterEventHandler registers an event handler. func (e *Engine) RegisterEventHandler(h EventHandler) error { if e.eventHandler != nil { diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index 1ebd529463..dac0385db3 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -238,6 +238,31 @@ func (c *Cluster) Pull(name string, callback func(what, status string)) { wg.Wait() } +// Load image +func (c *Cluster) Load(tarFile string, callback func(what, status string)) { + size := len(c.engines) + done := make(chan bool, size) + for _, n := range c.engines { + go func(nn *cluster.Engine) { + if callback != nil { + callback(nn.Name, "") + } + err := nn.Load(tarFile) + if callback != nil { + if err != nil { + callback(nn.Name, err.Error()) + } else { + callback(nn.Name, "loaded") + } + } + done <- true + }(n) + } + for i := 0; i < size; i++ { + <-done + } +} + // Containers returns all the containers in the cluster. func (c *Cluster) Containers() []*cluster.Container { c.RLock() From 34e0c78d1d75fe2e7c265f2789088bbfc2cc17bb Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Fri, 10 Apr 2015 19:08:00 +0800 Subject: [PATCH 02/13] gofmt check Signed-off-by: Xian Chaobo --- api/handlers.go | 64 ++++++++++++++++++++-------------------- cluster/cluster.go | 10 +++---- cluster/engine.go | 18 +++++------ cluster/swarm/cluster.go | 42 +++++++++++++------------- 4 files changed, 67 insertions(+), 67 deletions(-) diff --git a/api/handlers.go b/api/handlers.go index 98ea62f728..142210157d 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -4,15 +4,15 @@ import ( "bytes" "encoding/json" "fmt" + "io" "io/ioutil" "net/http" + "os" + "path" "runtime" "sort" "strconv" "strings" - "os" - "io" - "path" dockerfilters "github.com/docker/docker/pkg/parsers/filters" "github.com/docker/swarm/cluster" @@ -275,36 +275,36 @@ func postImagesCreate(c *context, w http.ResponseWriter, r *http.Request) { // POST /images/load func postImagesLoad(c *context, w http.ResponseWriter, r *http.Request) { - //cache tar file - tmpImageDir, err := ioutil.TempDir("", "docker-import-") - if err != nil { - httpError(w, err.Error(), http.StatusInternalServerError) - return - } - defer os.RemoveAll(tmpImageDir) + //cache tar file + tmpImageDir, err := ioutil.TempDir("", "docker-import-") + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + defer os.RemoveAll(tmpImageDir) - repoTarFile := path.Join(tmpImageDir, "repo.tar") - tarFile, err := os.Create(repoTarFile) - if err != nil { - httpError(w, err.Error(), http.StatusInternalServerError) - return - } - if _, err := io.Copy(tarFile, r.Body); err != nil { - httpError(w, err.Error(), http.StatusInternalServerError) - return - } - tarFile.Close() - - // call cluster to load image on every node - wf := NewWriteFlusher(w) - callback := func(what, status string) { - if status == "" { - fmt.Fprintf(wf, "%s:Loading Image...\n", what) - } else { - fmt.Fprintf(wf, "%s:Loading Image... %s\n", what,status) - } - } - c.cluster.Load(repoTarFile, callback) + repoTarFile := path.Join(tmpImageDir, "repo.tar") + tarFile, err := os.Create(repoTarFile) + if err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + if _, err := io.Copy(tarFile, r.Body); err != nil { + httpError(w, err.Error(), http.StatusInternalServerError) + return + } + tarFile.Close() + + // call cluster to load image on every node + wf := NewWriteFlusher(w) + callback := func(what, status string) { + if status == "" { + fmt.Fprintf(wf, "%s:Loading Image...\n", what) + } else { + fmt.Fprintf(wf, "%s:Loading Image... %s\n", what, status) + } + } + c.cluster.Load(repoTarFile, callback) } // GET /events diff --git a/cluster/cluster.go b/cluster/cluster.go index 4fb1a9891d..63ded4a30c 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -33,11 +33,11 @@ type Cluster interface { // `status` is the current status, like "", "in progress" or "downloaded Pull(name string, callback func(what, status string)) - // Load images - // `callback` can be called multiple time - // `what` is what is being loaded - // `status` is the current status, like "", "in progress" or "loaded" - Load(tarFile string, callback func(what, status string)) + // Load images + // `callback` can be called multiple time + // `what` is what is being loaded + // `status` is the current status, like "", "in progress" or "loaded" + Load(tarFile string, callback func(what, status string)) // Return some info about the cluster, like nb or containers / images // It is pretty open, so the implementation decides what to return. diff --git a/cluster/engine.go b/cluster/engine.go index 9b7084094c..f36c04ef58 100644 --- a/cluster/engine.go +++ b/cluster/engine.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" "net" + "os" "strings" "sync" "time" - "os" log "github.com/Sirupsen/logrus" "github.com/samalba/dockerclient" @@ -414,15 +414,15 @@ func (e *Engine) Pull(image string) error { // Load an image on the engine func (e *Engine) Load(tarFile string) error { - file, err := os.Open(tarFile) - if err != nil { - return err - } + file, err := os.Open(tarFile) + if err != nil { + return err + } - if err := e.client.LoadImage(file); err != nil { - return err - } - return nil + if err := e.client.LoadImage(file); err != nil { + return err + } + return nil } // RegisterEventHandler registers an event handler. diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index dac0385db3..ada1e8c0e8 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -240,27 +240,27 @@ func (c *Cluster) Pull(name string, callback func(what, status string)) { // Load image func (c *Cluster) Load(tarFile string, callback func(what, status string)) { - size := len(c.engines) - done := make(chan bool, size) - for _, n := range c.engines { - go func(nn *cluster.Engine) { - if callback != nil { - callback(nn.Name, "") - } - err := nn.Load(tarFile) - if callback != nil { - if err != nil { - callback(nn.Name, err.Error()) - } else { - callback(nn.Name, "loaded") - } - } - done <- true - }(n) - } - for i := 0; i < size; i++ { - <-done - } + size := len(c.engines) + done := make(chan bool, size) + for _, n := range c.engines { + go func(nn *cluster.Engine) { + if callback != nil { + callback(nn.Name, "") + } + err := nn.Load(tarFile) + if callback != nil { + if err != nil { + callback(nn.Name, err.Error()) + } else { + callback(nn.Name, "loaded") + } + } + done <- true + }(n) + } + for i := 0; i < size; i++ { + <-done + } } // Containers returns all the containers in the cluster. From b4dd3e32e49fbf149f0fe6fe285f5bd54234a177 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Sat, 11 Apr 2015 00:03:13 +0800 Subject: [PATCH 03/13] update Godeps Signed-off-by: Xian Chaobo --- Godeps/Godeps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 578f0bd51e..05a72b8d35 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -60,7 +60,7 @@ }, { "ImportPath": "github.com/samalba/dockerclient", - "Rev": "c37a52f55ab5a9edb9ffd4cf6e78692962b29b8d" + "Rev": "578f4b4d729fb23a8ffade2f7e3f335a964fea0c" }, { "ImportPath": "github.com/samuel/go-zookeeper/zk", From 6ad2a7847c49bdd84b08a2867fc898c4fe58b20b Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Tue, 14 Apr 2015 19:05:21 +0800 Subject: [PATCH 04/13] stream load and output nothing if load successfully Signed-off-by: Xian Chaobo --- api/handlers.go | 24 +-------------------- cluster/cluster.go | 3 ++- cluster/engine.go | 11 +++------- cluster/swarm/cluster.go | 45 ++++++++++++++++++++++++++++++++-------- 4 files changed, 42 insertions(+), 41 deletions(-) diff --git a/api/handlers.go b/api/handlers.go index 142210157d..c438140fc2 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -4,11 +4,8 @@ import ( "bytes" "encoding/json" "fmt" - "io" "io/ioutil" "net/http" - "os" - "path" "runtime" "sort" "strconv" @@ -275,25 +272,6 @@ func postImagesCreate(c *context, w http.ResponseWriter, r *http.Request) { // POST /images/load func postImagesLoad(c *context, w http.ResponseWriter, r *http.Request) { - //cache tar file - tmpImageDir, err := ioutil.TempDir("", "docker-import-") - if err != nil { - httpError(w, err.Error(), http.StatusInternalServerError) - return - } - defer os.RemoveAll(tmpImageDir) - - repoTarFile := path.Join(tmpImageDir, "repo.tar") - tarFile, err := os.Create(repoTarFile) - if err != nil { - httpError(w, err.Error(), http.StatusInternalServerError) - return - } - if _, err := io.Copy(tarFile, r.Body); err != nil { - httpError(w, err.Error(), http.StatusInternalServerError) - return - } - tarFile.Close() // call cluster to load image on every node wf := NewWriteFlusher(w) @@ -304,7 +282,7 @@ func postImagesLoad(c *context, w http.ResponseWriter, r *http.Request) { fmt.Fprintf(wf, "%s:Loading Image... %s\n", what, status) } } - c.cluster.Load(repoTarFile, callback) + c.cluster.Load(r.Body, callback) } // GET /events diff --git a/cluster/cluster.go b/cluster/cluster.go index 63ded4a30c..d1dbb2aa77 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -2,6 +2,7 @@ package cluster import ( "github.com/samalba/dockerclient" + "io" ) // Cluster is exported @@ -37,7 +38,7 @@ type Cluster interface { // `callback` can be called multiple time // `what` is what is being loaded // `status` is the current status, like "", "in progress" or "loaded" - Load(tarFile string, callback func(what, status string)) + Load(imageReader io.Reader, callback func(what, status string)) // Return some info about the cluster, like nb or containers / images // It is pretty open, so the implementation decides what to return. diff --git a/cluster/engine.go b/cluster/engine.go index f36c04ef58..72d2699851 100644 --- a/cluster/engine.go +++ b/cluster/engine.go @@ -4,8 +4,8 @@ import ( "crypto/tls" "errors" "fmt" + "io" "net" - "os" "strings" "sync" "time" @@ -413,13 +413,8 @@ func (e *Engine) Pull(image string) error { } // Load an image on the engine -func (e *Engine) Load(tarFile string) error { - file, err := os.Open(tarFile) - if err != nil { - return err - } - - if err := e.client.LoadImage(file); err != nil { +func (e *Engine) Load(reader io.Reader) error { + if err := e.client.LoadImage(reader); err != nil { return err } return nil diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index ada1e8c0e8..7c12f073de 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -3,6 +3,7 @@ package swarm import ( "errors" "fmt" + "io" "sort" "sync" @@ -239,25 +240,51 @@ func (c *Cluster) Pull(name string, callback func(what, status string)) { } // Load image -func (c *Cluster) Load(tarFile string, callback func(what, status string)) { +func (c *Cluster) Load(imageReader io.Reader, callback func(what, status string)) { size := len(c.engines) done := make(chan bool, size) + + pipeWriters := []*io.PipeWriter{} + pipeReaders := []*io.PipeReader{} for _, n := range c.engines { - go func(nn *cluster.Engine) { - if callback != nil { - callback(nn.Name, "") - } - err := nn.Load(tarFile) + pipeReader, pipeWriter := io.Pipe() + pipeReaders = append(pipeReaders, pipeReader) + pipeWriters = append(pipeWriters, pipeWriter) + + go func(reader *io.PipeReader, nn *cluster.Engine) { + // call engine load image + err := nn.Load(reader) if callback != nil { if err != nil { callback(nn.Name, err.Error()) - } else { - callback(nn.Name, "loaded") } } + // clean up + defer reader.Close() done <- true - }(n) + + }(pipeReader, n) } + + // create multi-writer + listWriter := []io.Writer{} + for _, pipeW := range pipeWriters { + listWriter = append(listWriter, pipeW) + } + mutiWriter := io.MultiWriter(listWriter...) + + // copy image-reader to muti-writer + _, err := io.Copy(mutiWriter, imageReader) + if err != nil { + log.Error(err) + } + + // close pipe writers + for _, pipeW := range pipeWriters { + pipeW.Close() + } + + // wait all host done for i := 0; i < size; i++ { <-done } From 7da46216e0712b9c18aa909081db7f26d837db5b Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Tue, 14 Apr 2015 23:52:35 +0800 Subject: [PATCH 05/13] integration test Signed-off-by: Xian Chaobo --- test/integration/docker-load.bats | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/integration/docker-load.bats diff --git a/test/integration/docker-load.bats b/test/integration/docker-load.bats new file mode 100644 index 0000000000..c4515766ac --- /dev/null +++ b/test/integration/docker-load.bats @@ -0,0 +1,27 @@ +#!/usr/bin/env bats +load helpers + +# temp file for saving image +IMAGE_FILE=$(mktemp) + +function teardown() { + stop_manager + stop_docker + rm -f $IMAGE_FILE +} + +@test "docker load should return success,every node should load the image" { + # create a tar file + docker pull busybox:latest + docker save -o $IMAGE_FILE busybox:latest + + start_docker 1 + start_manager + + run docker_swarm -i $IMAGE_FILE + [ "$status" -eq 0 ] + + run docker -H ${HOSTS[0]} images + [ "${#lines[@]}" -eq 2 ] +} + From f200e9a9547b34954ea44e85a7c1eff77d837775 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Thu, 16 Apr 2015 00:03:55 -0400 Subject: [PATCH 06/13] rebase and update test Signed-off-by: Xian Chaobo --- api/router.go | 2 +- test/integration/docker-load.bats | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/api/router.go b/api/router.go index a402aed895..4870343ccf 100644 --- a/api/router.go +++ b/api/router.go @@ -48,7 +48,7 @@ var routes = map[string]map[string]handler{ "/commit": postCommit, "/build": proxyRandomAndForceRefresh, "/images/create": postImagesCreate, - "/images/load": notImplementedHandler, + "/images/load": postImagesLoad, "/images/{name:.*}/push": proxyImage, "/images/{name:.*}/tag": proxyImage, "/containers/create": postContainersCreate, diff --git a/test/integration/docker-load.bats b/test/integration/docker-load.bats index c4515766ac..6594c8f261 100644 --- a/test/integration/docker-load.bats +++ b/test/integration/docker-load.bats @@ -15,7 +15,7 @@ function teardown() { docker pull busybox:latest docker save -o $IMAGE_FILE busybox:latest - start_docker 1 + start_docker 2 start_manager run docker_swarm -i $IMAGE_FILE @@ -23,5 +23,8 @@ function teardown() { run docker -H ${HOSTS[0]} images [ "${#lines[@]}" -eq 2 ] + + run docker -H ${HOSTS[1]} images + [ "${#lines[@]}" -eq 2 ] } From f7d9a967852b9d1b2d06e8a88e988562d936e65c Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Thu, 16 Apr 2015 00:57:59 -0400 Subject: [PATCH 07/13] rollback godeps.json Signed-off-by: Xian Chaobo --- Godeps/Godeps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 05a72b8d35..578f0bd51e 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -60,7 +60,7 @@ }, { "ImportPath": "github.com/samalba/dockerclient", - "Rev": "578f4b4d729fb23a8ffade2f7e3f335a964fea0c" + "Rev": "c37a52f55ab5a9edb9ffd4cf6e78692962b29b8d" }, { "ImportPath": "github.com/samuel/go-zookeeper/zk", From 820804b108f8858503ebdbe593b5561962f7bc69 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Thu, 16 Apr 2015 05:24:51 -0400 Subject: [PATCH 08/13] update load-image integration test Signed-off-by: Xian Chaobo --- test/integration/docker-load.bats | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/integration/docker-load.bats b/test/integration/docker-load.bats index 6594c8f261..7f2d18b13b 100644 --- a/test/integration/docker-load.bats +++ b/test/integration/docker-load.bats @@ -5,26 +5,26 @@ load helpers IMAGE_FILE=$(mktemp) function teardown() { - stop_manager - stop_docker - rm -f $IMAGE_FILE + stop_docker + swarm_manage_cleanup + rm -f $IMAGE_FILE } @test "docker load should return success,every node should load the image" { - # create a tar file - docker pull busybox:latest - docker save -o $IMAGE_FILE busybox:latest + # create a tar file + docker pull busybox:latest + docker save -o $IMAGE_FILE busybox:latest - start_docker 2 - start_manager + start_docker 2 + swarm_manage - run docker_swarm -i $IMAGE_FILE - [ "$status" -eq 0 ] + run docker_swarm load -i $IMAGE_FILE + [ "$status" -eq 0 ] - run docker -H ${HOSTS[0]} images - [ "${#lines[@]}" -eq 2 ] + run docker -H ${HOSTS[0]} images + [ "${#lines[@]}" -eq 2 ] - run docker -H ${HOSTS[1]} images - [ "${#lines[@]}" -eq 2 ] + run docker -H ${HOSTS[1]} images + [ "${#lines[@]}" -eq 2 ] } From 59c5b6b3171910988a8fe51084bef064913052d8 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Thu, 16 Apr 2015 22:10:39 -0400 Subject: [PATCH 09/13] use WaitGroup and move test in api.bats Signed-off-by: Xian Chaobo --- cluster/swarm/cluster.go | 20 ++++++++++---------- test/integration/api.bats | 23 ++++++++++++++++++++++- test/integration/docker-load.bats | 30 ------------------------------ 3 files changed, 32 insertions(+), 41 deletions(-) delete mode 100644 test/integration/docker-load.bats diff --git a/cluster/swarm/cluster.go b/cluster/swarm/cluster.go index 7c12f073de..a4e1edd03b 100644 --- a/cluster/swarm/cluster.go +++ b/cluster/swarm/cluster.go @@ -241,17 +241,22 @@ func (c *Cluster) Pull(name string, callback func(what, status string)) { // Load image func (c *Cluster) Load(imageReader io.Reader, callback func(what, status string)) { - size := len(c.engines) - done := make(chan bool, size) + var wg sync.WaitGroup + c.RLock() pipeWriters := []*io.PipeWriter{} pipeReaders := []*io.PipeReader{} for _, n := range c.engines { + wg.Add(1) + pipeReader, pipeWriter := io.Pipe() pipeReaders = append(pipeReaders, pipeReader) pipeWriters = append(pipeWriters, pipeWriter) go func(reader *io.PipeReader, nn *cluster.Engine) { + defer wg.Done() + defer reader.Close() + // call engine load image err := nn.Load(reader) if callback != nil { @@ -259,10 +264,6 @@ func (c *Cluster) Load(imageReader io.Reader, callback func(what, status string) callback(nn.Name, err.Error()) } } - // clean up - defer reader.Close() - done <- true - }(pipeReader, n) } @@ -284,10 +285,9 @@ func (c *Cluster) Load(imageReader io.Reader, callback func(what, status string) pipeW.Close() } - // wait all host done - for i := 0; i < size; i++ { - <-done - } + c.RUnlock() + + wg.Wait() } // Containers returns all the containers in the cluster. diff --git a/test/integration/api.bats b/test/integration/api.bats index 514e75134f..507d7c7de9 100644 --- a/test/integration/api.bats +++ b/test/integration/api.bats @@ -98,7 +98,28 @@ function teardown() { # FIXME @test "docker load" { - skip + # temp file for saving image + IMAGE_FILE=$(mktemp) + + # create a tar file + docker pull busybox:latest + docker save -o $IMAGE_FILE busybox:latest + + start_docker 2 + swarm_manage + + run docker_swarm load -i $IMAGE_FILE + [ "$status" -eq 0 ] + + run docker -H ${HOSTS[0]} images + [ "${#lines[@]}" -eq 2 ] + + run docker -H ${HOSTS[1]} images + [ "${#lines[@]}" -eq 2 ] + + rm -f $IMAGE_FILE +} + } # FIXME diff --git a/test/integration/docker-load.bats b/test/integration/docker-load.bats deleted file mode 100644 index 7f2d18b13b..0000000000 --- a/test/integration/docker-load.bats +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bats -load helpers - -# temp file for saving image -IMAGE_FILE=$(mktemp) - -function teardown() { - stop_docker - swarm_manage_cleanup - rm -f $IMAGE_FILE -} - -@test "docker load should return success,every node should load the image" { - # create a tar file - docker pull busybox:latest - docker save -o $IMAGE_FILE busybox:latest - - start_docker 2 - swarm_manage - - run docker_swarm load -i $IMAGE_FILE - [ "$status" -eq 0 ] - - run docker -H ${HOSTS[0]} images - [ "${#lines[@]}" -eq 2 ] - - run docker -H ${HOSTS[1]} images - [ "${#lines[@]}" -eq 2 ] -} - From 2ec8446344b831ccb33ba5a41c608fccd0a3d597 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Thu, 16 Apr 2015 23:11:18 -0400 Subject: [PATCH 10/13] remove FIXME Signed-off-by: Xian Chaobo --- test/integration/api.bats | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/api.bats b/test/integration/api.bats index 507d7c7de9..ec7b65551a 100644 --- a/test/integration/api.bats +++ b/test/integration/api.bats @@ -96,7 +96,6 @@ function teardown() { skip } -# FIXME @test "docker load" { # temp file for saving image IMAGE_FILE=$(mktemp) From 0b44d9615b2b4afb4ab1c16abe41a4855bff967a Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Sun, 19 Apr 2015 23:02:26 -0400 Subject: [PATCH 11/13] add force fresh images Signed-off-by: Xian Chaobo --- cluster/engine.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cluster/engine.go b/cluster/engine.go index 72d2699851..c9bc04471c 100644 --- a/cluster/engine.go +++ b/cluster/engine.go @@ -417,6 +417,10 @@ func (e *Engine) Load(reader io.Reader) error { if err := e.client.LoadImage(reader); err != nil { return err } + + // force fresh images + e.RefreshImages() + return nil } From c4d5b76db7304644a4d5e2f6430771b2aaa6d7e7 Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Sun, 19 Apr 2015 23:11:29 -0400 Subject: [PATCH 12/13] enhance load integration test Signed-off-by: Xian Chaobo --- test/integration/api.bats | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/integration/api.bats b/test/integration/api.bats index ec7b65551a..57201f577b 100644 --- a/test/integration/api.bats +++ b/test/integration/api.bats @@ -107,14 +107,22 @@ function teardown() { start_docker 2 swarm_manage + run docker_swarm images -q + [ "$status" -eq 0 ] + [ "${#lines[@]}" -eq 0 ] + run docker_swarm load -i $IMAGE_FILE [ "$status" -eq 0 ] - + + # check node0 run docker -H ${HOSTS[0]} images [ "${#lines[@]}" -eq 2 ] + [[ "${lines[1]}" == *"busybox"* ]] + # check node1 run docker -H ${HOSTS[1]} images [ "${#lines[@]}" -eq 2 ] + [[ "${lines[1]}" == *"busybox"* ]] rm -f $IMAGE_FILE } From 33eedfa1d9f14f5642d4d902446003a08078981a Mon Sep 17 00:00:00 2001 From: Xian Chaobo Date: Mon, 20 Apr 2015 03:02:50 -0400 Subject: [PATCH 13/13] update api README.md and using tab instead of whitespace Signed-off-by: Xian Chaobo --- api/README.md | 1 - test/integration/api.bats | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/api/README.md b/api/README.md index 6c83bb242d..d5a9d1499d 100644 --- a/api/README.md +++ b/api/README.md @@ -15,7 +15,6 @@ Some endpoints have not yet been implemented and will return a 404 error. ``` GET "/images/get" -POST "/images/load" POST "/images/create" : "docker import" flow not implement ``` diff --git a/test/integration/api.bats b/test/integration/api.bats index 57201f577b..9ddc1fd042 100644 --- a/test/integration/api.bats +++ b/test/integration/api.bats @@ -100,31 +100,31 @@ function teardown() { # temp file for saving image IMAGE_FILE=$(mktemp) - # create a tar file - docker pull busybox:latest - docker save -o $IMAGE_FILE busybox:latest + # create a tar file + docker pull busybox:latest + docker save -o $IMAGE_FILE busybox:latest - start_docker 2 + start_docker 2 swarm_manage run docker_swarm images -q [ "$status" -eq 0 ] - [ "${#lines[@]}" -eq 0 ] + [ "${#lines[@]}" -eq 0 ] - run docker_swarm load -i $IMAGE_FILE - [ "$status" -eq 0 ] + run docker_swarm load -i $IMAGE_FILE + [ "$status" -eq 0 ] # check node0 - run docker -H ${HOSTS[0]} images - [ "${#lines[@]}" -eq 2 ] + run docker -H ${HOSTS[0]} images + [ "${#lines[@]}" -eq 2 ] [[ "${lines[1]}" == *"busybox"* ]] # check node1 - run docker -H ${HOSTS[1]} images - [ "${#lines[@]}" -eq 2 ] + run docker -H ${HOSTS[1]} images + [ "${#lines[@]}" -eq 2 ] [[ "${lines[1]}" == *"busybox"* ]] - rm -f $IMAGE_FILE + rm -f $IMAGE_FILE } }