From 17a806c8a0b6add2aa773dfca272acefee9b638c Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 12 Dec 2013 22:39:35 +0000 Subject: [PATCH 1/4] Port 'docker images' to the engine API Docker-DCO-1.1-Signed-off-by: Solomon Hykes (github: shykes) --- api.go | 30 ++++------- engine/env.go | 74 +++++++++++++++++++++++++ engine/streams.go | 16 ++++++ engine/table_test.go | 28 ++++++++++ integration/api_test.go | 64 ++++++++++------------ integration/runtime_test.go | 17 +++--- integration/server_test.go | 105 +++++++++++++----------------------- integration/sorter_test.go | 16 ++---- integration/utils_test.go | 21 +++++++- server.go | 74 ++++++++++++++----------- 10 files changed, 270 insertions(+), 175 deletions(-) create mode 100644 engine/table_test.go diff --git a/api.go b/api.go index c768ef9344..10dab5fae2 100644 --- a/api.go +++ b/api.go @@ -181,27 +181,19 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http. if err := parseForm(r); err != nil { return err } - - all, err := getBoolParam(r.Form.Get("all")) - if err != nil { + fmt.Printf("getImagesJSON\n") + job := srv.Eng.Job("images") + job.Setenv("filter", r.Form.Get("filter")) + job.Setenv("all", r.Form.Get("all")) + // FIXME: 1.7 clients expect a single json list + job.Stdout.Add(w) + w.WriteHeader(http.StatusOK) + fmt.Printf("running images job\n") + if err := job.Run(); err != nil { return err } - filter := r.Form.Get("filter") - - outs, err := srv.Images(all, filter) - if err != nil { - return err - } - - if version < 1.7 { - outs2 := []APIImagesOld{} - for _, ctnr := range outs { - outs2 = append(outs2, ctnr.ToLegacy()...) - } - - return writeJSON(w, http.StatusOK, outs2) - } - return writeJSON(w, http.StatusOK, outs) + fmt.Printf("job has been run\n") + return nil } func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { diff --git a/engine/env.go b/engine/env.go index a65c8438d2..f4cc124240 100644 --- a/engine/env.go +++ b/engine/env.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "sort" "strconv" "strings" ) @@ -232,3 +233,76 @@ func (env *Env) Map() map[string]string { } return m } + +type Table struct { + Data []*Env + sortKey string +} + +func NewTable(sortKey string, sizeHint int) *Table { + return &Table{ + make([]*Env, 0, sizeHint), + sortKey, + } +} + +func (t *Table) Add(env *Env) { + t.Data = append(t.Data, env) +} + +func (t *Table) Len() int { + return len(t.Data) +} + +func (t *Table) Less(a, b int) bool { + return t.lessBy(a, b, t.sortKey) +} + +func (t *Table) lessBy(a, b int, by string) bool { + keyA := t.Data[a].Get(by) + keyB := t.Data[b].Get(by) + intA, errA := strconv.ParseInt(keyA, 10, 64) + intB, errB := strconv.ParseInt(keyB, 10, 64) + if errA == nil && errB == nil { + return intA < intB + } + return keyA < keyB +} + +func (t *Table) Swap(a, b int) { + tmp := t.Data[a] + t.Data[a] = t.Data[b] + t.Data[b] = tmp +} + +func (t *Table) Sort() { + sort.Sort(t) +} + +func (t *Table) WriteTo(dst io.Writer) (n int64, err error) { + for _, env := range t.Data { + bytes, err := env.WriteTo(dst) + if err != nil { + return -1, err + } + if _, err := dst.Write([]byte{'\n'}); err != nil { + return -1, err + } + n += bytes + 1 + } + return n, nil +} + +func (t *Table) ReadFrom(src io.Reader) (n int64, err error) { + decoder := NewDecoder(src) + for { + env, err := decoder.Decode() + if err == io.EOF { + return 0, nil + } else if err != nil { + return -1, err + } + t.Add(env) + } + return 0, nil +} diff --git a/engine/streams.go b/engine/streams.go index 7cd4a60cf7..824f0a4ab2 100644 --- a/engine/streams.go +++ b/engine/streams.go @@ -190,3 +190,19 @@ func (o *Output) AddEnv() (dst *Env, err error) { }() return dst, nil } + +func (o *Output) AddTable() (dst *Table, err error) { + src, err := o.AddPipe() + if err != nil { + return nil, err + } + dst = NewTable("", 0) + o.tasks.Add(1) + go func() { + defer o.tasks.Done() + if _, err := dst.ReadFrom(src); err != nil { + return + } + }() + return dst, nil +} diff --git a/engine/table_test.go b/engine/table_test.go new file mode 100644 index 0000000000..0a81d690eb --- /dev/null +++ b/engine/table_test.go @@ -0,0 +1,28 @@ +package engine + +import ( + "testing" + "bytes" + "encoding/json" +) + +func TestTableWriteTo(t *testing.T) { + table := NewTable("", 0) + e := &Env{} + e.Set("foo", "bar") + table.Add(e) + var buf bytes.Buffer + if _, err := table.WriteTo(&buf); err != nil { + t.Fatal(err) + } + output := make(map[string]string) + if err := json.Unmarshal(buf.Bytes(), &output); err != nil { + t.Fatal(err) + } + if len(output) != 1 { + t.Fatalf("Incorrect output: %v", output) + } + if val, exists := output["foo"]; !exists || val != "bar" { + t.Fatalf("Inccorect output: %v", output) + } +} diff --git a/integration/api_test.go b/integration/api_test.go index ff42afac5a..de54078dea 100644 --- a/integration/api_test.go +++ b/integration/api_test.go @@ -60,11 +60,14 @@ func TestGetInfo(t *testing.T) { defer mkRuntimeFromEngine(eng, t).Nuke() srv := mkServerFromEngine(eng, t) - initialImages, err := srv.Images(false, "") + job := eng.Job("images") + initialImages, err := job.Stdout.AddTable() if err != nil { t.Fatal(err) } - + if err := job.Run(); err != nil { + t.Fatal(err) + } req, err := http.NewRequest("GET", "/info", nil) if err != nil { t.Fatal(err) @@ -85,8 +88,8 @@ func TestGetInfo(t *testing.T) { t.Fatal(err) } out.Close() - if images := i.GetInt("Images"); images != len(initialImages) { - t.Errorf("Expected images: %d, %d found", len(initialImages), images) + if images := i.GetInt("Images"); images != initialImages.Len() { + t.Errorf("Expected images: %d, %d found", initialImages.Len(), images) } expected := "application/json" if result := r.HeaderMap.Get("Content-Type"); result != expected { @@ -145,12 +148,14 @@ func TestGetImagesJSON(t *testing.T) { defer mkRuntimeFromEngine(eng, t).Nuke() srv := mkServerFromEngine(eng, t) - // all=0 - - initialImages, err := srv.Images(false, "") + job := eng.Job("images") + initialImages, err := job.Stdout.AddTable() if err != nil { t.Fatal(err) } + if err := job.Run(); err != nil { + t.Fatal(err) + } req, err := http.NewRequest("GET", "/images/json?all=0", nil) if err != nil { @@ -164,18 +169,18 @@ func TestGetImagesJSON(t *testing.T) { } assertHttpNotError(r, t) - images := []docker.APIImages{} - if err := json.Unmarshal(r.Body.Bytes(), &images); err != nil { + images := engine.NewTable("Created", 0) + if _, err := images.ReadFrom(r.Body); err != nil { t.Fatal(err) } - if len(images) != len(initialImages) { - t.Errorf("Expected %d image, %d found", len(initialImages), len(images)) + if images.Len() != initialImages.Len() { + t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len()) } found := false - for _, img := range images { - if strings.Contains(img.RepoTags[0], unitTestImageName) { + for _, img := range images.Data { + if strings.Contains(img.GetList("RepoTags")[0], unitTestImageName) { found = true break } @@ -188,10 +193,7 @@ func TestGetImagesJSON(t *testing.T) { // all=1 - initialImages, err = srv.Images(true, "") - if err != nil { - t.Fatal(err) - } + initialImages = getAllImages(eng, t) req2, err := http.NewRequest("GET", "/images/json?all=true", nil) if err != nil { @@ -207,8 +209,8 @@ func TestGetImagesJSON(t *testing.T) { t.Fatal(err) } - if len(images2) != len(initialImages) { - t.Errorf("Expected %d image, %d found", len(initialImages), len(images2)) + if len(images2) != initialImages.Len() { + t.Errorf("Expected %d image, %d found", initialImages.Len(), len(images2)) } found = false @@ -1126,21 +1128,16 @@ func TestDeleteImages(t *testing.T) { defer mkRuntimeFromEngine(eng, t).Nuke() srv := mkServerFromEngine(eng, t) - initialImages, err := srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + initialImages := getImages(eng, t, true, "") if err := eng.Job("tag", unitTestImageName, "test", "test").Run(); err != nil { t.Fatal(err) } - images, err := srv.Images(false, "") - if err != nil { - t.Fatal(err) - } - if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+1 { - t.Errorf("Expected %d images, %d found", len(initialImages)+1, len(images)) + images := getImages(eng, t, true, "") + + if images.Len() != initialImages.Len()+1 { + t.Errorf("Expected %d images, %d found", initialImages.Len()+1, images.Len()) } req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil) @@ -1177,13 +1174,10 @@ func TestDeleteImages(t *testing.T) { if len(outs) != 1 { t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs)) } - images, err = srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + images = getImages(eng, t, false, "") - if len(images[0].RepoTags) != len(initialImages[0].RepoTags) { - t.Errorf("Expected %d image, %d found", len(initialImages), len(images)) + if images.Len() != initialImages.Len() { + t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len()) } } diff --git a/integration/runtime_test.go b/integration/runtime_test.go index cdd4818934..f3d8384082 100644 --- a/integration/runtime_test.go +++ b/integration/runtime_test.go @@ -51,14 +51,17 @@ func cleanup(eng *engine.Engine, t *testing.T) error { container.Kill() runtime.Destroy(container) } - srv := mkServerFromEngine(eng, t) - images, err := srv.Images(true, "") + job := eng.Job("images") + images, err := job.Stdout.AddTable() if err != nil { - return err + t.Fatal(err) } - for _, image := range images { - if image.ID != unitTestImageID { - srv.ImageDelete(image.ID, false) + if err := job.Run(); err != nil { + t.Fatal(err) + } + for _, image := range images.Data { + if image.Get("ID") != unitTestImageID { + mkServerFromEngine(eng, t).ImageDelete(image.Get("ID"), false) } } return nil @@ -158,7 +161,7 @@ func spawnGlobalDaemon() { Host: testDaemonAddr, } job := eng.Job("serveapi", listenURL.String()) - job.SetenvBool("Logging", os.Getenv("DEBUG") != "") + job.SetenvBool("Logging", true) if err := job.Run(); err != nil { log.Fatalf("Unable to spawn the test daemon: %s", err) } diff --git a/integration/server_test.go b/integration/server_test.go index a29c2acbf3..106bff9c2b 100644 --- a/integration/server_test.go +++ b/integration/server_test.go @@ -14,10 +14,7 @@ func TestImageTagImageDelete(t *testing.T) { srv := mkServerFromEngine(eng, t) - initialImages, err := srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + initialImages := getAllImages(eng, t) if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil { t.Fatal(err) } @@ -30,52 +27,43 @@ func TestImageTagImageDelete(t *testing.T) { t.Fatal(err) } - images, err := srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + images := getAllImages(eng, t) - if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+3 { - t.Errorf("Expected %d images, %d found", len(initialImages)+3, len(images)) + nExpected := len(initialImages.Data[0].GetList("RepoTags")) + 3 + nActual := len(images.Data[0].GetList("RepoTags")) + if nExpected != nActual { + t.Errorf("Expected %d images, %d found", nExpected, nActual) } if _, err := srv.ImageDelete("utest/docker:tag2", true); err != nil { t.Fatal(err) } - images, err = srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + images = getAllImages(eng, t) - if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+2 { - t.Errorf("Expected %d images, %d found", len(initialImages)+2, len(images)) + nExpected = len(initialImages.Data[0].GetList("RepoTags")) + 2 + nActual = len(images.Data[0].GetList("RepoTags")) + if nExpected != nActual { + t.Errorf("Expected %d images, %d found", nExpected, nActual) } if _, err := srv.ImageDelete("utest:5000/docker:tag3", true); err != nil { t.Fatal(err) } - images, err = srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + images = getAllImages(eng, t) - if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+1 { - t.Errorf("Expected %d images, %d found", len(initialImages)+1, len(images)) - } + nExpected = len(initialImages.Data[0].GetList("RepoTags")) + 1 + nActual = len(images.Data[0].GetList("RepoTags")) if _, err := srv.ImageDelete("utest:tag1", true); err != nil { t.Fatal(err) } - images, err = srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + images = getAllImages(eng, t) - if len(images) != len(initialImages) { - t.Errorf("Expected %d image, %d found", len(initialImages), len(images)) + if images.Len() != initialImages.Len() { + t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len()) } } @@ -250,10 +238,7 @@ func TestRmi(t *testing.T) { srv := mkServerFromEngine(eng, t) defer mkRuntimeFromEngine(eng, t).Nuke() - initialImages, err := srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + initialImages := getAllImages(eng, t) config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "echo", "test"}, nil) if err != nil { @@ -308,13 +293,10 @@ func TestRmi(t *testing.T) { t.Fatal(err) } - images, err := srv.Images(false, "") - if err != nil { - t.Fatal(err) - } + images := getAllImages(eng, t) - if len(images)-len(initialImages) != 2 { - t.Fatalf("Expected 2 new images, found %d.", len(images)-len(initialImages)) + if images.Len()-initialImages.Len() != 2 { + t.Fatalf("Expected 2 new images, found %d.", images.Len()-initialImages.Len()) } _, err = srv.ImageDelete(imageID, true) @@ -322,20 +304,17 @@ func TestRmi(t *testing.T) { t.Fatal(err) } - images, err = srv.Images(false, "") - if err != nil { - t.Fatal(err) + images = getAllImages(eng, t) + + if images.Len()-initialImages.Len() != 1 { + t.Fatalf("Expected 1 new image, found %d.", images.Len()-initialImages.Len()) } - if len(images)-len(initialImages) != 1 { - t.Fatalf("Expected 1 new image, found %d.", len(images)-len(initialImages)) - } - - for _, image := range images { - if strings.Contains(unitTestImageID, image.ID) { + for _, image := range images.Data { + if strings.Contains(unitTestImageID, image.Get("ID")) { continue } - if image.RepoTags[0] == ":" { + if image.GetList("RepoTags")[0] == ":" { t.Fatalf("Expected tagged image, got untagged one.") } } @@ -359,39 +338,27 @@ func TestImagesFilter(t *testing.T) { t.Fatal(err) } - images, err := srv.Images(false, "utest*/*") - if err != nil { - t.Fatal(err) - } + images := getImages(eng, t, false, "utest*/*") - if len(images[0].RepoTags) != 2 { + if len(images.Data[0].GetList("RepoTags")) != 2 { t.Fatal("incorrect number of matches returned") } - images, err = srv.Images(false, "utest") - if err != nil { - t.Fatal(err) - } + images = getImages(eng, t, false, "utest") - if len(images[0].RepoTags) != 1 { + if len(images.Data[0].GetList("RepoTags")) != 1 { t.Fatal("incorrect number of matches returned") } - images, err = srv.Images(false, "utest*") - if err != nil { - t.Fatal(err) - } + images = getImages(eng, t, false, "utest*") - if len(images[0].RepoTags) != 1 { + if len(images.Data[0].GetList("RepoTags")) != 1 { t.Fatal("incorrect number of matches returned") } - images, err = srv.Images(false, "*5000*/*") - if err != nil { - t.Fatal(err) - } + images = getImages(eng, t, false, "*5000*/*") - if len(images[0].RepoTags) != 1 { + if len(images.Data[0].GetList("RepoTags")) != 1 { t.Fatal("incorrect number of matches returned") } } diff --git a/integration/sorter_test.go b/integration/sorter_test.go index 77848c7ddf..1c089a2997 100644 --- a/integration/sorter_test.go +++ b/integration/sorter_test.go @@ -17,13 +17,10 @@ func TestServerListOrderedImagesByCreationDate(t *testing.T) { t.Fatal(err) } - images, err := srv.Images(true, "") - if err != nil { - t.Fatal(err) - } + images := getImages(eng, t, true, "") - if images[0].Created < images[1].Created { - t.Error("Expected []APIImges to be ordered by most recent creation date.") + if images.Data[0].GetInt("Created") < images.Data[1].GetInt("Created") { + t.Error("Expected images to be ordered by most recent creation date.") } } @@ -44,12 +41,9 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) { t.Fatal(err) } - images, err := srv.Images(true, "") - if err != nil { - t.Fatal(err) - } + images := getImages(eng, t, true, "") - if images[0].RepoTags[0] != "repo:zed" && images[0].RepoTags[0] != "repo:bar" { + if images.Data[0].GetList("RepoTags")[0] != "repo:zed" && images.Data[0].GetList("RepoTags")[0] != "repo:bar" { t.Errorf("Expected []APIImges to be ordered by most recent creation date. %s", images) } } diff --git a/integration/utils_test.go b/integration/utils_test.go index 85ba13d698..4ab1c96cca 100644 --- a/integration/utils_test.go +++ b/integration/utils_test.go @@ -186,8 +186,6 @@ func NewTestEngine(t utils.Fataler) *engine.Engine { if err != nil { t.Fatal(err) } - eng.Stdout = ioutil.Discard - eng.Stderr = ioutil.Discard // Load default plugins // (This is manually copied and modified from main() until we have a more generic plugin system) job := eng.Job("initapi") @@ -329,3 +327,22 @@ func fakeTar() (io.Reader, error) { tw.Close() return buf, nil } + +func getAllImages(eng *engine.Engine, t *testing.T) *engine.Table { + return getImages(eng, t, true, "") +} + +func getImages(eng *engine.Engine, t *testing.T, all bool, filter string) *engine.Table { + job := eng.Job("images") + job.SetenvBool("all", all) + job.Setenv("filter", filter) + images, err := job.Stdout.AddTable() + if err != nil { + t.Fatal(err) + } + if err := job.Run(); err != nil { + t.Fatal(err) + } + return images + +} diff --git a/server.go b/server.go index c1fda6aeb9..556b342c16 100644 --- a/server.go +++ b/server.go @@ -127,6 +127,10 @@ func jobInitApi(job *engine.Job) engine.Status { job.Error(err) return engine.StatusErr } + if err := job.Eng.Register("images", srv.Images); err != nil { + job.Error(err) + return engine.StatusErr + } return engine.StatusOK } @@ -568,23 +572,26 @@ func (srv *Server) ImagesViz(out io.Writer) error { return nil } -func (srv *Server) Images(all bool, filter string) ([]APIImages, error) { +func (srv *Server) Images(job *engine.Job) engine.Status { + fmt.Printf("Images()\n") + srv.Eng.Job("version").Run() var ( allImages map[string]*Image err error ) - if all { + if job.GetenvBool("all") { allImages, err = srv.runtime.graph.Map() } else { allImages, err = srv.runtime.graph.Heads() } if err != nil { - return nil, err + job.Errorf("%s", err) + return engine.StatusErr } - lookup := make(map[string]APIImages) + lookup := make(map[string]*engine.Env) for name, repository := range srv.runtime.repositories.Repositories { - if filter != "" { - if match, _ := path.Match(filter, name); !match { + if job.Getenv("filter") != "" { + if match, _ := path.Match(job.Getenv("filter"), name); !match { continue } } @@ -596,48 +603,51 @@ func (srv *Server) Images(all bool, filter string) ([]APIImages, error) { } if out, exists := lookup[id]; exists { - out.RepoTags = append(out.RepoTags, fmt.Sprintf("%s:%s", name, tag)) - - lookup[id] = out + repotag := fmt.Sprintf("%s:%s", name, tag) + out.SetList("RepoTags", append(out.GetList("RepoTags"), repotag)) } else { - var out APIImages - + out := &engine.Env{} delete(allImages, id) - - out.ParentId = image.Parent - out.RepoTags = []string{fmt.Sprintf("%s:%s", name, tag)} - out.ID = image.ID - out.Created = image.Created.Unix() - out.Size = image.Size - out.VirtualSize = image.getParentsSize(0) + image.Size - + out.Set("ParentId", image.Parent) + out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)}) + out.Set("ID", image.ID) + out.SetInt64("Created", image.Created.Unix()) + out.SetInt64("Size", image.Size) + out.SetInt64("VirtualSize", image.getParentsSize(0)+image.Size) lookup[id] = out } } } - outs := make([]APIImages, 0, len(lookup)) + outs := engine.NewTable("Created", len(lookup)) for _, value := range lookup { - outs = append(outs, value) + outs.Add(value) } // Display images which aren't part of a repository/tag - if filter == "" { + if job.Getenv("filter") == "" { for _, image := range allImages { - var out APIImages - out.ID = image.ID - out.ParentId = image.Parent - out.RepoTags = []string{":"} - out.Created = image.Created.Unix() - out.Size = image.Size - out.VirtualSize = image.getParentsSize(0) + image.Size - outs = append(outs, out) + out := &engine.Env{} + out.Set("ParentId", image.Parent) + out.SetList("RepoTags", []string{":"}) + out.Set("ID", image.ID) + out.SetInt64("Created", image.Created.Unix()) + out.SetInt64("Size", image.Size) + out.SetInt64("VirtualSize", image.getParentsSize(0)+image.Size) + outs.Add(out) } } - sortImagesByCreationAndTag(outs) - return outs, nil + outs.Sort() + job.Logf("Sending %d images to stdout", outs.Len()) + if n, err := outs.WriteTo(job.Stdout); err != nil { + job.Errorf("%s", err) + return engine.StatusErr + } else { + job.Logf("%d bytes sent", n) + } + return engine.StatusOK } func (srv *Server) DockerInfo(job *engine.Job) engine.Status { From 3a610f754f425ea6042c3f8b5452273656a06c90 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 13 Dec 2013 10:26:00 -0800 Subject: [PATCH 2/4] Add compat 1.8 Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- api.go | 7 +-- commands.go | 105 +++++++++++++++++++------------------ engine/env.go | 39 ++++++++++++-- integration/api_test.go | 40 +++++--------- integration/server_test.go | 2 - integration/sorter_test.go | 4 +- server.go | 14 ++--- 7 files changed, 112 insertions(+), 99 deletions(-) diff --git a/api.go b/api.go index 10dab5fae2..7e874c9f12 100644 --- a/api.go +++ b/api.go @@ -28,7 +28,7 @@ import ( ) const ( - APIVERSION = 1.8 + APIVERSION = 1.9 DEFAULTHTTPHOST = "127.0.0.1" DEFAULTHTTPPORT = 4243 DEFAULTUNIXSOCKET = "/var/run/docker.sock" @@ -181,18 +181,15 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http. if err := parseForm(r); err != nil { return err } - fmt.Printf("getImagesJSON\n") job := srv.Eng.Job("images") job.Setenv("filter", r.Form.Get("filter")) job.Setenv("all", r.Form.Get("all")) - // FIXME: 1.7 clients expect a single json list + job.SetenvBool("list", version <= 1.8) job.Stdout.Add(w) w.WriteHeader(http.StatusOK) - fmt.Printf("running images job\n") if err := job.Run(); err != nil { return err } - fmt.Printf("job has been run\n") return nil } diff --git a/commands.go b/commands.go index fd231abeea..40c450928c 100644 --- a/commands.go +++ b/commands.go @@ -1137,36 +1137,38 @@ func (cli *DockerCli) CmdImages(args ...string) error { return err } - var outs []APIImages - if err := json.Unmarshal(body, &outs); err != nil { + outs := engine.NewTable("Created", 0) + + if _, err := outs.ReadFrom(bytes.NewReader(body)); err != nil { return err } var ( - printNode func(cli *DockerCli, noTrunc bool, image APIImages, prefix string) - startImage APIImages + printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string) + startImage *engine.Env - roots []APIImages - byParent = make(map[string][]APIImages) + roots = engine.NewTable("Created", outs.Len()) + byParent = make(map[string]*engine.Table) ) - for _, image := range outs { - if image.ParentId == "" { - roots = append(roots, image) + for _, image := range outs.Data { + if image.Get("ParentId") == "" { + roots.Add(image) } else { - if children, exists := byParent[image.ParentId]; exists { - byParent[image.ParentId] = append(children, image) + if children, exists := byParent[image.Get("ParentId")]; exists { + children.Add(image) } else { - byParent[image.ParentId] = []APIImages{image} + byParent[image.Get("ParentId")] = engine.NewTable("Created", 1) + byParent[image.Get("ParentId")].Add(image) } } if filter != "" { - if filter == image.ID || filter == utils.TruncateID(image.ID) { + if filter == image.Get("ID") || filter == utils.TruncateID(image.Get("ID")) { startImage = image } - for _, repotag := range image.RepoTags { + for _, repotag := range image.GetList("RepoTags") { if repotag == filter { startImage = image } @@ -1181,10 +1183,12 @@ func (cli *DockerCli) CmdImages(args ...string) error { printNode = (*DockerCli).printTreeNode } - if startImage.ID != "" { - cli.WalkTree(*noTrunc, &[]APIImages{startImage}, byParent, "", printNode) + if startImage != nil { + root := engine.NewTable("Created", 1) + root.Add(startImage) + cli.WalkTree(*noTrunc, root, byParent, "", printNode) } else if filter == "" { - cli.WalkTree(*noTrunc, &roots, byParent, "", printNode) + cli.WalkTree(*noTrunc, roots, byParent, "", printNode) } if *flViz { fmt.Fprintf(cli.out, " base [style=invisible]\n}\n") @@ -1203,9 +1207,8 @@ func (cli *DockerCli) CmdImages(args ...string) error { return err } - var outs []APIImages - err = json.Unmarshal(body, &outs) - if err != nil { + outs := engine.NewTable("Created", 0) + if _, err := outs.ReadFrom(bytes.NewReader(body)); err != nil { return err } @@ -1214,19 +1217,19 @@ func (cli *DockerCli) CmdImages(args ...string) error { fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE") } - for _, out := range outs { - for _, repotag := range out.RepoTags { + for _, out := range outs.Data { + for _, repotag := range out.GetList("RepoTags") { repo, tag := utils.ParseRepositoryTag(repotag) - + outID := out.Get("ID") if !*noTrunc { - out.ID = utils.TruncateID(out.ID) + outID = utils.TruncateID(outID) } if !*quiet { - fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, out.ID, utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.Created, 0))), utils.HumanSize(out.VirtualSize)) + fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), utils.HumanSize(out.GetInt64("VirtualSize"))) } else { - fmt.Fprintln(w, out.ID) + fmt.Fprintln(w, outID) } } } @@ -1238,66 +1241,66 @@ func (cli *DockerCli) CmdImages(args ...string) error { return nil } -func (cli *DockerCli) WalkTree(noTrunc bool, images *[]APIImages, byParent map[string][]APIImages, prefix string, printNode func(cli *DockerCli, noTrunc bool, image APIImages, prefix string)) { - length := len(*images) +func (cli *DockerCli) WalkTree(noTrunc bool, images *engine.Table, byParent map[string]*engine.Table, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string)) { + length := images.Len() if length > 1 { - for index, image := range *images { + for index, image := range images.Data { if index+1 == length { printNode(cli, noTrunc, image, prefix+"└─") - if subimages, exists := byParent[image.ID]; exists { - cli.WalkTree(noTrunc, &subimages, byParent, prefix+" ", printNode) + if subimages, exists := byParent[image.Get("ID")]; exists { + cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode) } } else { - printNode(cli, noTrunc, image, prefix+"├─") - if subimages, exists := byParent[image.ID]; exists { - cli.WalkTree(noTrunc, &subimages, byParent, prefix+"│ ", printNode) + printNode(cli, noTrunc, image, prefix+"\u251C─") + if subimages, exists := byParent[image.Get("ID")]; exists { + cli.WalkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode) } } } } else { - for _, image := range *images { + for _, image := range images.Data { printNode(cli, noTrunc, image, prefix+"└─") - if subimages, exists := byParent[image.ID]; exists { - cli.WalkTree(noTrunc, &subimages, byParent, prefix+" ", printNode) + if subimages, exists := byParent[image.Get("ID")]; exists { + cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode) } } } } -func (cli *DockerCli) printVizNode(noTrunc bool, image APIImages, prefix string) { +func (cli *DockerCli) printVizNode(noTrunc bool, image *engine.Env, prefix string) { var ( imageID string parentID string ) if noTrunc { - imageID = image.ID - parentID = image.ParentId + imageID = image.Get("ID") + parentID = image.Get("ParentId") } else { - imageID = utils.TruncateID(image.ID) - parentID = utils.TruncateID(image.ParentId) + imageID = utils.TruncateID(image.Get("ID")) + parentID = utils.TruncateID(image.Get("ParentId")) } - if image.ParentId == "" { + if parentID == "" { fmt.Fprintf(cli.out, " base -> \"%s\" [style=invis]\n", imageID) } else { fmt.Fprintf(cli.out, " \"%s\" -> \"%s\"\n", parentID, imageID) } - if image.RepoTags[0] != ":" { + if image.GetList("RepoTags")[0] != ":" { fmt.Fprintf(cli.out, " \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n", - imageID, imageID, strings.Join(image.RepoTags, "\\n")) + imageID, imageID, strings.Join(image.GetList("RepoTags"), "\\n")) } } -func (cli *DockerCli) printTreeNode(noTrunc bool, image APIImages, prefix string) { +func (cli *DockerCli) printTreeNode(noTrunc bool, image *engine.Env, prefix string) { var imageID string if noTrunc { - imageID = image.ID + imageID = image.Get("ID") } else { - imageID = utils.TruncateID(image.ID) + imageID = utils.TruncateID(image.Get("ID")) } - fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, utils.HumanSize(image.VirtualSize)) - if image.RepoTags[0] != ":" { - fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.RepoTags, ", ")) + fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, utils.HumanSize(image.GetInt64("VirtualSize"))) + if image.GetList("RepoTags")[0] != ":" { + fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.GetList("RepoTags"), ", ")) } else { fmt.Fprint(cli.out, "\n") } diff --git a/engine/env.go b/engine/env.go index f4cc124240..0593bfa012 100644 --- a/engine/env.go +++ b/engine/env.go @@ -237,15 +237,21 @@ func (env *Env) Map() map[string]string { type Table struct { Data []*Env sortKey string + Chan chan *Env } func NewTable(sortKey string, sizeHint int) *Table { return &Table{ make([]*Env, 0, sizeHint), sortKey, + make(chan *Env), } } +func (t *Table) SetKey(sortKey string) { + t.sortKey = sortKey +} + func (t *Table) Add(env *Env) { t.Data = append(t.Data, env) } @@ -279,16 +285,41 @@ func (t *Table) Sort() { sort.Sort(t) } +func (t *Table) ReverseSort() { + sort.Sort(sort.Reverse(t)) +} + +func (t *Table) WriteListTo(dst io.Writer) (n int64, err error) { + if _, err := dst.Write([]byte{'['}); err != nil { + return -1, err + } + n = 1 + for i, env := range t.Data { + bytes, err := env.WriteTo(dst) + if err != nil { + return -1, err + } + n += bytes + if i != len(t.Data)-1 { + if _, err := dst.Write([]byte{','}); err != nil { + return -1, err + } + n += 1 + } + } + if _, err := dst.Write([]byte{']'}); err != nil { + return -1, err + } + return n + 1, nil +} + func (t *Table) WriteTo(dst io.Writer) (n int64, err error) { for _, env := range t.Data { bytes, err := env.WriteTo(dst) if err != nil { return -1, err } - if _, err := dst.Write([]byte{'\n'}); err != nil { - return -1, err - } - n += bytes + 1 + n += bytes } return n, nil } diff --git a/integration/api_test.go b/integration/api_test.go index de54078dea..47d63efb1d 100644 --- a/integration/api_test.go +++ b/integration/api_test.go @@ -204,18 +204,18 @@ func TestGetImagesJSON(t *testing.T) { } assertHttpNotError(r2, t) - images2 := []docker.APIImages{} - if err := json.Unmarshal(r2.Body.Bytes(), &images2); err != nil { + images2 := engine.NewTable("ID", 0) + if _, err := images2.ReadFrom(r2.Body); err != nil { t.Fatal(err) } - if len(images2) != initialImages.Len() { - t.Errorf("Expected %d image, %d found", initialImages.Len(), len(images2)) + if images2.Len() != initialImages.Len() { + t.Errorf("Expected %d image, %d found", initialImages.Len(), images2.Len()) } found = false - for _, img := range images2 { - if img.ID == unitTestImageID { + for _, img := range images2.Data { + if img.Get("ID") == unitTestImageID { found = true break } @@ -237,29 +237,13 @@ func TestGetImagesJSON(t *testing.T) { } assertHttpNotError(r3, t) - images3 := []docker.APIImages{} - if err := json.Unmarshal(r3.Body.Bytes(), &images3); err != nil { + images3 := engine.NewTable("ID", 0) + if _, err := images3.ReadFrom(r3.Body); err != nil { t.Fatal(err) } - if len(images3) != 0 { - t.Errorf("Expected 0 image, %d found", len(images3)) - } - - r4 := httptest.NewRecorder() - - // all=foobar - req4, err := http.NewRequest("GET", "/images/json?all=foobar", nil) - if err != nil { - t.Fatal(err) - } - - if err := docker.ServeRequest(srv, docker.APIVERSION, r4, req4); err != nil { - t.Fatal(err) - } - // Don't assert against HTTP error since we expect an error - if r4.Code != http.StatusBadRequest { - t.Fatalf("%d Bad Request expected, received %d\n", http.StatusBadRequest, r4.Code) + if images3.Len() != 0 { + t.Errorf("Expected 0 image, %d found", images3.Len()) } } @@ -1136,8 +1120,8 @@ func TestDeleteImages(t *testing.T) { images := getImages(eng, t, true, "") - if images.Len() != initialImages.Len()+1 { - t.Errorf("Expected %d images, %d found", initialImages.Len()+1, images.Len()) + if len(images.Data[0].GetList("RepoTags")) != len(initialImages.Data[0].GetList("RepoTags"))+1 { + t.Errorf("Expected %d images, %d found", len(initialImages.Data[0].GetList("RepoTags"))+1, len(images.Data[0].GetList("RepoTags"))) } req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil) diff --git a/integration/server_test.go b/integration/server_test.go index 106bff9c2b..e755d14728 100644 --- a/integration/server_test.go +++ b/integration/server_test.go @@ -324,8 +324,6 @@ func TestImagesFilter(t *testing.T) { eng := NewTestEngine(t) defer nuke(mkRuntimeFromEngine(eng, t)) - srv := mkServerFromEngine(eng, t) - if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil { t.Fatal(err) } diff --git a/integration/sorter_test.go b/integration/sorter_test.go index 1c089a2997..02d08d3409 100644 --- a/integration/sorter_test.go +++ b/integration/sorter_test.go @@ -43,8 +43,8 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) { images := getImages(eng, t, true, "") - if images.Data[0].GetList("RepoTags")[0] != "repo:zed" && images.Data[0].GetList("RepoTags")[0] != "repo:bar" { - t.Errorf("Expected []APIImges to be ordered by most recent creation date. %s", images) + if repoTags := images.Data[0].GetList("RepoTags"); repoTags[0] != "repo:zed" && repoTags[0] != "repo:bar" { + t.Errorf("Expected Images to be ordered by most recent creation date.") } } diff --git a/server.go b/server.go index 556b342c16..a0c545fbc4 100644 --- a/server.go +++ b/server.go @@ -573,8 +573,6 @@ func (srv *Server) ImagesViz(out io.Writer) error { } func (srv *Server) Images(job *engine.Job) engine.Status { - fmt.Printf("Images()\n") - srv.Eng.Job("version").Run() var ( allImages map[string]*Image err error @@ -639,13 +637,15 @@ func (srv *Server) Images(job *engine.Job) engine.Status { } } - outs.Sort() - job.Logf("Sending %d images to stdout", outs.Len()) - if n, err := outs.WriteTo(job.Stdout); err != nil { + outs.ReverseSort() + if job.GetenvBool("list") { + if _, err := outs.WriteListTo(job.Stdout); err != nil { + job.Errorf("%s", err) + return engine.StatusErr + } + } else if _, err := outs.WriteTo(job.Stdout); err != nil { job.Errorf("%s", err) return engine.StatusErr - } else { - job.Logf("%d bytes sent", n) } return engine.StatusOK } From aca1270104802347f5aa3104959282924b631daa Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 13 Jan 2014 11:20:33 -0800 Subject: [PATCH 3/4] add legacy compat Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- api.go | 1 + api_params.go | 36 ------------------------------------ server.go | 31 +++++++++++++++++++++++++------ sorter.go | 33 --------------------------------- 4 files changed, 26 insertions(+), 75 deletions(-) diff --git a/api.go b/api.go index 7e874c9f12..3bf19fd948 100644 --- a/api.go +++ b/api.go @@ -185,6 +185,7 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http. job.Setenv("filter", r.Form.Get("filter")) job.Setenv("all", r.Form.Get("all")) job.SetenvBool("list", version <= 1.8) + job.SetenvBool("legacy", version <= 1.7) job.Stdout.Add(w) w.WriteHeader(http.StatusOK) if err := job.Run(); err != nil { diff --git a/api_params.go b/api_params.go index fa9eab0c15..cfe80c8b0b 100644 --- a/api_params.go +++ b/api_params.go @@ -1,7 +1,5 @@ package docker -import "strings" - type ( APIHistory struct { ID string `json:"Id"` @@ -11,24 +9,6 @@ type ( Size int64 } - APIImages struct { - ID string `json:"Id"` - RepoTags []string `json:",omitempty"` - Created int64 - Size int64 - VirtualSize int64 - ParentId string `json:",omitempty"` - } - - APIImagesOld struct { - Repository string `json:",omitempty"` - Tag string `json:",omitempty"` - ID string `json:"Id"` - Created int64 - Size int64 - VirtualSize int64 - } - APITop struct { Titles []string Processes [][]string @@ -101,22 +81,6 @@ type ( } ) -func (api APIImages) ToLegacy() []APIImagesOld { - outs := []APIImagesOld{} - for _, repotag := range api.RepoTags { - components := strings.SplitN(repotag, ":", 2) - outs = append(outs, APIImagesOld{ - ID: api.ID, - Repository: components[0], - Tag: components[1], - Created: api.Created, - Size: api.Size, - VirtualSize: api.VirtualSize, - }) - } - return outs -} - func (api APIContainers) ToLegacy() *APIContainersOld { return &APIContainersOld{ ID: api.ID, diff --git a/server.go b/server.go index a0c545fbc4..18bda2abd2 100644 --- a/server.go +++ b/server.go @@ -601,13 +601,27 @@ func (srv *Server) Images(job *engine.Job) engine.Status { } if out, exists := lookup[id]; exists { - repotag := fmt.Sprintf("%s:%s", name, tag) - out.SetList("RepoTags", append(out.GetList("RepoTags"), repotag)) + if job.GetenvBool("legacy") { + out2 := &engine.Env{} + out2.Set("Repository", name) + out2.Set("Tag", tag) + out2.Set("ID", out.Get("ID")) + out2.SetInt64("Created", out.GetInt64("Created")) + out2.SetInt64("Size", out.GetInt64("Size")) + out2.SetInt64("VirtualSize", out.GetInt64("VirtualSize")) + } else { + out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag))) + } } else { out := &engine.Env{} delete(allImages, id) - out.Set("ParentId", image.Parent) - out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)}) + if job.GetenvBool("legacy") { + out.Set("Repository", name) + out.Set("Tag", tag) + } else { + out.Set("ParentId", image.Parent) + out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)}) + } out.Set("ID", image.ID) out.SetInt64("Created", image.Created.Unix()) out.SetInt64("Size", image.Size) @@ -627,8 +641,13 @@ func (srv *Server) Images(job *engine.Job) engine.Status { if job.Getenv("filter") == "" { for _, image := range allImages { out := &engine.Env{} - out.Set("ParentId", image.Parent) - out.SetList("RepoTags", []string{":"}) + if job.GetenvBool("legacy") { + out.Set("Repository", "") + out.Set("Tag", "") + } else { + out.Set("ParentId", image.Parent) + out.SetList("RepoTags", []string{":"}) + } out.Set("ID", image.ID) out.SetInt64("Created", image.Created.Unix()) out.SetInt64("Size", image.Size) diff --git a/sorter.go b/sorter.go index c9a86b45c0..9b3e1a9486 100644 --- a/sorter.go +++ b/sorter.go @@ -2,39 +2,6 @@ package docker import "sort" -type imageSorter struct { - images []APIImages - by func(i1, i2 *APIImages) bool // Closure used in the Less method. -} - -// Len is part of sort.Interface. -func (s *imageSorter) Len() int { - return len(s.images) -} - -// Swap is part of sort.Interface. -func (s *imageSorter) Swap(i, j int) { - s.images[i], s.images[j] = s.images[j], s.images[i] -} - -// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter. -func (s *imageSorter) Less(i, j int) bool { - return s.by(&s.images[i], &s.images[j]) -} - -// Sort []ApiImages by most recent creation date and tag name. -func sortImagesByCreationAndTag(images []APIImages) { - creationAndTag := func(i1, i2 *APIImages) bool { - return i1.Created > i2.Created - } - - sorter := &imageSorter{ - images: images, - by: creationAndTag} - - sort.Sort(sorter) -} - type portSorter struct { ports []Port by func(i, j Port) bool From 16ca6a1c12ffe9a02da4e823646bee6461ffbad5 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 13 Jan 2014 14:55:31 -0800 Subject: [PATCH 4/4] move legacy stuff outside the job Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- api.go | 49 +++++++++++++++++-- engine/table_test.go | 4 +- registry/registry.go | 2 +- server.go | 37 +++----------- .../src/github.com/gorilla/context/context.go | 2 +- vendor/src/github.com/gorilla/mux/old_test.go | 8 +-- 6 files changed, 58 insertions(+), 44 deletions(-) diff --git a/api.go b/api.go index 3bf19fd948..c8bd7368b4 100644 --- a/api.go +++ b/api.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/auth" + "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/pkg/systemd" "github.com/dotcloud/docker/utils" "github.com/gorilla/mux" @@ -181,16 +182,54 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http. if err := parseForm(r); err != nil { return err } - job := srv.Eng.Job("images") + + var ( + buffer *bytes.Buffer + job = srv.Eng.Job("images") + ) + job.Setenv("filter", r.Form.Get("filter")) job.Setenv("all", r.Form.Get("all")) - job.SetenvBool("list", version <= 1.8) - job.SetenvBool("legacy", version <= 1.7) - job.Stdout.Add(w) - w.WriteHeader(http.StatusOK) + + if version >= 1.9 { + job.Stdout.Add(w) + } else { + buffer = bytes.NewBuffer(nil) + job.Stdout.Add(buffer) + } + if err := job.Run(); err != nil { return err } + + if version < 1.9 { // Send as a valide JSON array + outs := engine.NewTable("Created", 0) + if _, err := outs.ReadFrom(buffer); err != nil { + return err + } + if version < 1.8 { // Convert to legacy format + outsLegacy := engine.NewTable("Created", 0) + for _, out := range outs.Data { + for _, repoTag := range out.GetList("RepoTags") { + parts := strings.Split(repoTag, ":") + outLegacy := &engine.Env{} + outLegacy.Set("Repository", parts[0]) + outLegacy.Set("Tag", parts[1]) + outLegacy.Set("ID", out.Get("ID")) + outLegacy.SetInt64("Created", out.GetInt64("Created")) + outLegacy.SetInt64("Size", out.GetInt64("Size")) + outLegacy.SetInt64("VirtualSize", out.GetInt64("VirtualSize")) + outsLegacy.Add(outLegacy) + } + } + if _, err := outsLegacy.WriteListTo(w); err != nil { + return err + } + } else if _, err := outs.WriteListTo(w); err != nil { + return err + } + } + return nil } diff --git a/engine/table_test.go b/engine/table_test.go index 0a81d690eb..3e8e4ff1b3 100644 --- a/engine/table_test.go +++ b/engine/table_test.go @@ -1,9 +1,9 @@ package engine import ( - "testing" "bytes" "encoding/json" + "testing" ) func TestTableWriteTo(t *testing.T) { @@ -19,7 +19,7 @@ func TestTableWriteTo(t *testing.T) { if err := json.Unmarshal(buf.Bytes(), &output); err != nil { t.Fatal(err) } - if len(output) != 1 { + if len(output) != 1 { t.Fatalf("Incorrect output: %v", output) } if val, exists := output["foo"]; !exists || val != "bar" { diff --git a/registry/registry.go b/registry/registry.go index a038fdfb66..a0da733ed9 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -59,7 +59,7 @@ func pingRegistryEndpoint(endpoint string) (bool, error) { // versions of the registry if standalone == "" { return true, nil - // Accepted values are "true" (case-insensitive) and "1". + // Accepted values are "true" (case-insensitive) and "1". } else if strings.EqualFold(standalone, "true") || standalone == "1" { return true, nil } diff --git a/server.go b/server.go index 18bda2abd2..0c7f1a2680 100644 --- a/server.go +++ b/server.go @@ -601,27 +601,12 @@ func (srv *Server) Images(job *engine.Job) engine.Status { } if out, exists := lookup[id]; exists { - if job.GetenvBool("legacy") { - out2 := &engine.Env{} - out2.Set("Repository", name) - out2.Set("Tag", tag) - out2.Set("ID", out.Get("ID")) - out2.SetInt64("Created", out.GetInt64("Created")) - out2.SetInt64("Size", out.GetInt64("Size")) - out2.SetInt64("VirtualSize", out.GetInt64("VirtualSize")) - } else { - out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag))) - } + out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag))) } else { out := &engine.Env{} delete(allImages, id) - if job.GetenvBool("legacy") { - out.Set("Repository", name) - out.Set("Tag", tag) - } else { - out.Set("ParentId", image.Parent) - out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)}) - } + out.Set("ParentId", image.Parent) + out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)}) out.Set("ID", image.ID) out.SetInt64("Created", image.Created.Unix()) out.SetInt64("Size", image.Size) @@ -641,13 +626,8 @@ func (srv *Server) Images(job *engine.Job) engine.Status { if job.Getenv("filter") == "" { for _, image := range allImages { out := &engine.Env{} - if job.GetenvBool("legacy") { - out.Set("Repository", "") - out.Set("Tag", "") - } else { - out.Set("ParentId", image.Parent) - out.SetList("RepoTags", []string{":"}) - } + out.Set("ParentId", image.Parent) + out.SetList("RepoTags", []string{":"}) out.Set("ID", image.ID) out.SetInt64("Created", image.Created.Unix()) out.SetInt64("Size", image.Size) @@ -657,12 +637,7 @@ func (srv *Server) Images(job *engine.Job) engine.Status { } outs.ReverseSort() - if job.GetenvBool("list") { - if _, err := outs.WriteListTo(job.Stdout); err != nil { - job.Errorf("%s", err) - return engine.StatusErr - } - } else if _, err := outs.WriteTo(job.Stdout); err != nil { + if _, err := outs.WriteTo(job.Stdout); err != nil { job.Errorf("%s", err) return engine.StatusErr } diff --git a/vendor/src/github.com/gorilla/context/context.go b/vendor/src/github.com/gorilla/context/context.go index 35d65561f3..12accb114a 100644 --- a/vendor/src/github.com/gorilla/context/context.go +++ b/vendor/src/github.com/gorilla/context/context.go @@ -92,7 +92,7 @@ func Purge(maxAge int) int { datat = make(map[*http.Request]int64) } else { min := time.Now().Unix() - int64(maxAge) - for r, _ := range data { + for r := range data { if datat[r] < min { clear(r) count++ diff --git a/vendor/src/github.com/gorilla/mux/old_test.go b/vendor/src/github.com/gorilla/mux/old_test.go index 7e266bb695..42530590e7 100644 --- a/vendor/src/github.com/gorilla/mux/old_test.go +++ b/vendor/src/github.com/gorilla/mux/old_test.go @@ -96,8 +96,8 @@ func TestRouteMatchers(t *testing.T) { method = "GET" headers = map[string]string{"X-Requested-With": "XMLHttpRequest"} resultVars = map[bool]map[string]string{ - true: map[string]string{"var1": "www", "var2": "product", "var3": "42"}, - false: map[string]string{}, + true: {"var1": "www", "var2": "product", "var3": "42"}, + false: {}, } } @@ -110,8 +110,8 @@ func TestRouteMatchers(t *testing.T) { method = "POST" headers = map[string]string{"Content-Type": "application/json"} resultVars = map[bool]map[string]string{ - true: map[string]string{"var4": "google", "var5": "product", "var6": "42"}, - false: map[string]string{}, + true: {"var4": "google", "var5": "product", "var6": "42"}, + false: {}, } }