فهرست منبع

Merge pull request #3575 from shykes/engine-get-images

move `docker images` to a job
Victor Vieux 11 سال پیش
والد
کامیت
9792df2080

+ 43 - 14
api.go

@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"fmt"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/auth"
 	"github.com/dotcloud/docker/auth"
+	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/pkg/systemd"
 	"github.com/dotcloud/docker/pkg/systemd"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
@@ -28,7 +29,7 @@ import (
 )
 )
 
 
 const (
 const (
-	APIVERSION        = 1.8
+	APIVERSION        = 1.9
 	DEFAULTHTTPHOST   = "127.0.0.1"
 	DEFAULTHTTPHOST   = "127.0.0.1"
 	DEFAULTHTTPPORT   = 4243
 	DEFAULTHTTPPORT   = 4243
 	DEFAULTUNIXSOCKET = "/var/run/docker.sock"
 	DEFAULTUNIXSOCKET = "/var/run/docker.sock"
@@ -182,26 +183,54 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.
 		return err
 		return err
 	}
 	}
 
 
-	all, err := getBoolParam(r.Form.Get("all"))
-	if err != nil {
-		return err
+	var (
+		buffer *bytes.Buffer
+		job    = srv.Eng.Job("images")
+	)
+
+	job.Setenv("filter", r.Form.Get("filter"))
+	job.Setenv("all", r.Form.Get("all"))
+
+	if version >= 1.9 {
+		job.Stdout.Add(w)
+	} else {
+		buffer = bytes.NewBuffer(nil)
+		job.Stdout.Add(buffer)
 	}
 	}
-	filter := r.Form.Get("filter")
 
 
-	outs, err := srv.Images(all, filter)
-	if err != nil {
+	if err := job.Run(); err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	if version < 1.7 {
-		outs2 := []APIImagesOld{}
-		for _, ctnr := range outs {
-			outs2 = append(outs2, ctnr.ToLegacy()...)
+	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 writeJSON(w, http.StatusOK, outs2)
 	}
 	}
-	return writeJSON(w, http.StatusOK, outs)
+
+	return nil
 }
 }
 
 
 func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {

+ 0 - 36
api_params.go

@@ -1,7 +1,5 @@
 package docker
 package docker
 
 
-import "strings"
-
 type (
 type (
 	APIHistory struct {
 	APIHistory struct {
 		ID        string   `json:"Id"`
 		ID        string   `json:"Id"`
@@ -11,24 +9,6 @@ type (
 		Size      int64
 		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 {
 	APITop struct {
 		Titles    []string
 		Titles    []string
 		Processes [][]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 {
 func (api APIContainers) ToLegacy() *APIContainersOld {
 	return &APIContainersOld{
 	return &APIContainersOld{
 		ID:         api.ID,
 		ID:         api.ID,

+ 54 - 51
commands.go

@@ -1137,36 +1137,38 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 			return err
 			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
 			return err
 		}
 		}
 
 
 		var (
 		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 {
 			} 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 {
 				} else {
-					byParent[image.ParentId] = []APIImages{image}
+					byParent[image.Get("ParentId")] = engine.NewTable("Created", 1)
+					byParent[image.Get("ParentId")].Add(image)
 				}
 				}
 			}
 			}
 
 
 			if filter != "" {
 			if filter != "" {
-				if filter == image.ID || filter == utils.TruncateID(image.ID) {
+				if filter == image.Get("ID") || filter == utils.TruncateID(image.Get("ID")) {
 					startImage = image
 					startImage = image
 				}
 				}
 
 
-				for _, repotag := range image.RepoTags {
+				for _, repotag := range image.GetList("RepoTags") {
 					if repotag == filter {
 					if repotag == filter {
 						startImage = image
 						startImage = image
 					}
 					}
@@ -1181,10 +1183,12 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 			printNode = (*DockerCli).printTreeNode
 			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 == "" {
 		} else if filter == "" {
-			cli.WalkTree(*noTrunc, &roots, byParent, "", printNode)
+			cli.WalkTree(*noTrunc, roots, byParent, "", printNode)
 		}
 		}
 		if *flViz {
 		if *flViz {
 			fmt.Fprintf(cli.out, " base [style=invisible]\n}\n")
 			fmt.Fprintf(cli.out, " base [style=invisible]\n}\n")
@@ -1203,9 +1207,8 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 			return err
 			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
 			return err
 		}
 		}
 
 
@@ -1214,19 +1217,19 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 			fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE")
 			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)
 				repo, tag := utils.ParseRepositoryTag(repotag)
-
+				outID := out.Get("ID")
 				if !*noTrunc {
 				if !*noTrunc {
-					out.ID = utils.TruncateID(out.ID)
+					outID = utils.TruncateID(outID)
 				}
 				}
 
 
 				if !*quiet {
 				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 {
 				} else {
-					fmt.Fprintln(w, out.ID)
+					fmt.Fprintln(w, outID)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -1238,66 +1241,66 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 	return nil
 	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 {
 	if length > 1 {
-		for index, image := range *images {
+		for index, image := range images.Data {
 			if index+1 == length {
 			if index+1 == length {
 				printNode(cli, noTrunc, image, prefix+"└─")
 				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 {
 			} 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 {
 	} else {
-		for _, image := range *images {
+		for _, image := range images.Data {
 			printNode(cli, noTrunc, image, prefix+"└─")
 			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 (
 	var (
 		imageID  string
 		imageID  string
 		parentID string
 		parentID string
 	)
 	)
 	if noTrunc {
 	if noTrunc {
-		imageID = image.ID
-		parentID = image.ParentId
+		imageID = image.Get("ID")
+		parentID = image.Get("ParentId")
 	} else {
 	} 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)
 		fmt.Fprintf(cli.out, " base -> \"%s\" [style=invis]\n", imageID)
 	} else {
 	} else {
 		fmt.Fprintf(cli.out, " \"%s\" -> \"%s\"\n", parentID, imageID)
 		fmt.Fprintf(cli.out, " \"%s\" -> \"%s\"\n", parentID, imageID)
 	}
 	}
-	if image.RepoTags[0] != "<none>:<none>" {
+	if image.GetList("RepoTags")[0] != "<none>:<none>" {
 		fmt.Fprintf(cli.out, " \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n",
 		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
 	var imageID string
 	if noTrunc {
 	if noTrunc {
-		imageID = image.ID
+		imageID = image.Get("ID")
 	} else {
 	} 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] != "<none>:<none>" {
-		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] != "<none>:<none>" {
+		fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.GetList("RepoTags"), ", "))
 	} else {
 	} else {
 		fmt.Fprint(cli.out, "\n")
 		fmt.Fprint(cli.out, "\n")
 	}
 	}

+ 105 - 0
engine/env.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
+	"sort"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 )
 )
@@ -232,3 +233,107 @@ func (env *Env) Map() map[string]string {
 	}
 	}
 	return m
 	return m
 }
 }
+
+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)
+}
+
+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) 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
+		}
+		n += bytes
+	}
+	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
+}

+ 16 - 0
engine/streams.go

@@ -190,3 +190,19 @@ func (o *Output) AddEnv() (dst *Env, err error) {
 	}()
 	}()
 	return dst, nil
 	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
+}

+ 28 - 0
engine/table_test.go

@@ -0,0 +1,28 @@
+package engine
+
+import (
+	"bytes"
+	"encoding/json"
+	"testing"
+)
+
+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)
+	}
+}

+ 37 - 59
integration/api_test.go

@@ -60,11 +60,14 @@ func TestGetInfo(t *testing.T) {
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	srv := mkServerFromEngine(eng, t)
 	srv := mkServerFromEngine(eng, t)
 
 
-	initialImages, err := srv.Images(false, "")
+	job := eng.Job("images")
+	initialImages, err := job.Stdout.AddTable()
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-
+	if err := job.Run(); err != nil {
+		t.Fatal(err)
+	}
 	req, err := http.NewRequest("GET", "/info", nil)
 	req, err := http.NewRequest("GET", "/info", nil)
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
@@ -85,8 +88,8 @@ func TestGetInfo(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 	out.Close()
 	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"
 	expected := "application/json"
 	if result := r.HeaderMap.Get("Content-Type"); result != expected {
 	if result := r.HeaderMap.Get("Content-Type"); result != expected {
@@ -145,12 +148,14 @@ func TestGetImagesJSON(t *testing.T) {
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	srv := mkServerFromEngine(eng, t)
 	srv := mkServerFromEngine(eng, t)
 
 
-	// all=0
-
-	initialImages, err := srv.Images(false, "")
+	job := eng.Job("images")
+	initialImages, err := job.Stdout.AddTable()
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
+	if err := job.Run(); err != nil {
+		t.Fatal(err)
+	}
 
 
 	req, err := http.NewRequest("GET", "/images/json?all=0", nil)
 	req, err := http.NewRequest("GET", "/images/json?all=0", nil)
 	if err != nil {
 	if err != nil {
@@ -164,18 +169,18 @@ func TestGetImagesJSON(t *testing.T) {
 	}
 	}
 	assertHttpNotError(r, 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)
 		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
 	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
 			found = true
 			break
 			break
 		}
 		}
@@ -188,10 +193,7 @@ func TestGetImagesJSON(t *testing.T) {
 
 
 	// all=1
 	// 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)
 	req2, err := http.NewRequest("GET", "/images/json?all=true", nil)
 	if err != nil {
 	if err != nil {
@@ -202,18 +204,18 @@ func TestGetImagesJSON(t *testing.T) {
 	}
 	}
 	assertHttpNotError(r2, 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)
 		t.Fatal(err)
 	}
 	}
 
 
-	if len(images2) != len(initialImages) {
-		t.Errorf("Expected %d image, %d found", len(initialImages), len(images2))
+	if images2.Len() != initialImages.Len() {
+		t.Errorf("Expected %d image, %d found", initialImages.Len(), images2.Len())
 	}
 	}
 
 
 	found = false
 	found = false
-	for _, img := range images2 {
-		if img.ID == unitTestImageID {
+	for _, img := range images2.Data {
+		if img.Get("ID") == unitTestImageID {
 			found = true
 			found = true
 			break
 			break
 		}
 		}
@@ -235,29 +237,13 @@ func TestGetImagesJSON(t *testing.T) {
 	}
 	}
 	assertHttpNotError(r3, t)
 	assertHttpNotError(r3, t)
 
 
-	images3 := []docker.APIImages{}
-	if err := json.Unmarshal(r3.Body.Bytes(), &images3); 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 {
+	images3 := engine.NewTable("ID", 0)
+	if _, err := images3.ReadFrom(r3.Body); err != nil {
 		t.Fatal(err)
 		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())
 	}
 	}
 }
 }
 
 
@@ -1126,21 +1112,16 @@ func TestDeleteImages(t *testing.T) {
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	srv := mkServerFromEngine(eng, t)
 	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 {
 	if err := eng.Job("tag", unitTestImageName, "test", "test").Run(); err != nil {
 		t.Fatal(err)
 		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 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)
 	req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)
@@ -1177,13 +1158,10 @@ func TestDeleteImages(t *testing.T) {
 	if len(outs) != 1 {
 	if len(outs) != 1 {
 		t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs))
 		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())
 	}
 	}
 }
 }
 
 

+ 10 - 7
integration/runtime_test.go

@@ -51,14 +51,17 @@ func cleanup(eng *engine.Engine, t *testing.T) error {
 		container.Kill()
 		container.Kill()
 		runtime.Destroy(container)
 		runtime.Destroy(container)
 	}
 	}
-	srv := mkServerFromEngine(eng, t)
-	images, err := srv.Images(true, "")
+	job := eng.Job("images")
+	images, err := job.Stdout.AddTable()
 	if err != nil {
 	if err != nil {
-		return err
+		t.Fatal(err)
+	}
+	if err := job.Run(); err != nil {
+		t.Fatal(err)
 	}
 	}
-	for _, image := range images {
-		if image.ID != unitTestImageID {
-			srv.ImageDelete(image.ID, false)
+	for _, image := range images.Data {
+		if image.Get("ID") != unitTestImageID {
+			mkServerFromEngine(eng, t).ImageDelete(image.Get("ID"), false)
 		}
 		}
 	}
 	}
 	return nil
 	return nil
@@ -158,7 +161,7 @@ func spawnGlobalDaemon() {
 			Host:   testDaemonAddr,
 			Host:   testDaemonAddr,
 		}
 		}
 		job := eng.Job("serveapi", listenURL.String())
 		job := eng.Job("serveapi", listenURL.String())
-		job.SetenvBool("Logging", os.Getenv("DEBUG") != "")
+		job.SetenvBool("Logging", true)
 		if err := job.Run(); err != nil {
 		if err := job.Run(); err != nil {
 			log.Fatalf("Unable to spawn the test daemon: %s", err)
 			log.Fatalf("Unable to spawn the test daemon: %s", err)
 		}
 		}

+ 35 - 70
integration/server_test.go

@@ -14,10 +14,7 @@ func TestImageTagImageDelete(t *testing.T) {
 
 
 	srv := mkServerFromEngine(eng, 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 {
 	if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -30,52 +27,43 @@ func TestImageTagImageDelete(t *testing.T) {
 		t.Fatal(err)
 		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 {
 	if _, err := srv.ImageDelete("utest/docker:tag2", true); err != nil {
 		t.Fatal(err)
 		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 {
 	if _, err := srv.ImageDelete("utest:5000/docker:tag3", true); err != nil {
 		t.Fatal(err)
 		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 {
 	if _, err := srv.ImageDelete("utest:tag1", true); err != nil {
 		t.Fatal(err)
 		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)
 	srv := mkServerFromEngine(eng, t)
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	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)
 	config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "echo", "test"}, nil)
 	if err != nil {
 	if err != nil {
@@ -308,13 +293,10 @@ func TestRmi(t *testing.T) {
 		t.Fatal(err)
 		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)
 	_, err = srv.ImageDelete(imageID, true)
@@ -322,20 +304,17 @@ func TestRmi(t *testing.T) {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
-	images, err = srv.Images(false, "")
-	if err != nil {
-		t.Fatal(err)
-	}
+	images = getAllImages(eng, t)
 
 
-	if len(images)-len(initialImages) != 1 {
-		t.Fatalf("Expected 1 new image, found %d.", len(images)-len(initialImages))
+	if images.Len()-initialImages.Len() != 1 {
+		t.Fatalf("Expected 1 new image, found %d.", images.Len()-initialImages.Len())
 	}
 	}
 
 
-	for _, image := range images {
-		if strings.Contains(unitTestImageID, image.ID) {
+	for _, image := range images.Data {
+		if strings.Contains(unitTestImageID, image.Get("ID")) {
 			continue
 			continue
 		}
 		}
-		if image.RepoTags[0] == "<none>:<none>" {
+		if image.GetList("RepoTags")[0] == "<none>:<none>" {
 			t.Fatalf("Expected tagged image, got untagged one.")
 			t.Fatalf("Expected tagged image, got untagged one.")
 		}
 		}
 	}
 	}
@@ -345,8 +324,6 @@ func TestImagesFilter(t *testing.T) {
 	eng := NewTestEngine(t)
 	eng := NewTestEngine(t)
 	defer nuke(mkRuntimeFromEngine(eng, t))
 	defer nuke(mkRuntimeFromEngine(eng, t))
 
 
-	srv := mkServerFromEngine(eng, t)
-
 	if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil {
 	if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -359,39 +336,27 @@ func TestImagesFilter(t *testing.T) {
 		t.Fatal(err)
 		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")
 		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")
 		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")
 		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")
 		t.Fatal("incorrect number of matches returned")
 	}
 	}
 }
 }

+ 6 - 12
integration/sorter_test.go

@@ -17,13 +17,10 @@ func TestServerListOrderedImagesByCreationDate(t *testing.T) {
 		t.Fatal(err)
 		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,13 +41,10 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
 		t.Fatal(err)
 		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" {
-		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.")
 	}
 	}
 }
 }
 
 

+ 19 - 2
integration/utils_test.go

@@ -186,8 +186,6 @@ func NewTestEngine(t utils.Fataler) *engine.Engine {
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	eng.Stdout = ioutil.Discard
-	eng.Stderr = ioutil.Discard
 	// Load default plugins
 	// Load default plugins
 	// (This is manually copied and modified from main() until we have a more generic plugin system)
 	// (This is manually copied and modified from main() until we have a more generic plugin system)
 	job := eng.Job("initapi")
 	job := eng.Job("initapi")
@@ -329,3 +327,22 @@ func fakeTar() (io.Reader, error) {
 	tw.Close()
 	tw.Close()
 	return buf, nil
 	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
+
+}

+ 1 - 1
registry/registry.go

@@ -59,7 +59,7 @@ func pingRegistryEndpoint(endpoint string) (bool, error) {
 	// versions of the registry
 	// versions of the registry
 	if standalone == "" {
 	if standalone == "" {
 		return true, nil
 		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" {
 	} else if strings.EqualFold(standalone, "true") || standalone == "1" {
 		return true, nil
 		return true, nil
 	}
 	}

+ 36 - 32
server.go

@@ -127,6 +127,10 @@ func jobInitApi(job *engine.Job) engine.Status {
 		job.Error(err)
 		job.Error(err)
 		return engine.StatusErr
 		return engine.StatusErr
 	}
 	}
+	if err := job.Eng.Register("images", srv.Images); err != nil {
+		job.Error(err)
+		return engine.StatusErr
+	}
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
 
 
@@ -568,23 +572,24 @@ func (srv *Server) ImagesViz(out io.Writer) error {
 	return nil
 	return nil
 }
 }
 
 
-func (srv *Server) Images(all bool, filter string) ([]APIImages, error) {
+func (srv *Server) Images(job *engine.Job) engine.Status {
 	var (
 	var (
 		allImages map[string]*Image
 		allImages map[string]*Image
 		err       error
 		err       error
 	)
 	)
-	if all {
+	if job.GetenvBool("all") {
 		allImages, err = srv.runtime.graph.Map()
 		allImages, err = srv.runtime.graph.Map()
 	} else {
 	} else {
 		allImages, err = srv.runtime.graph.Heads()
 		allImages, err = srv.runtime.graph.Heads()
 	}
 	}
 	if err != nil {
 	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 {
 	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
 				continue
 			}
 			}
 		}
 		}
@@ -596,48 +601,47 @@ func (srv *Server) Images(all bool, filter string) ([]APIImages, error) {
 			}
 			}
 
 
 			if out, exists := lookup[id]; exists {
 			if out, exists := lookup[id]; exists {
-				out.RepoTags = append(out.RepoTags, fmt.Sprintf("%s:%s", name, tag))
-
-				lookup[id] = out
+				out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag)))
 			} else {
 			} else {
-				var out APIImages
-
+				out := &engine.Env{}
 				delete(allImages, id)
 				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
 				lookup[id] = out
 			}
 			}
 
 
 		}
 		}
 	}
 	}
 
 
-	outs := make([]APIImages, 0, len(lookup))
+	outs := engine.NewTable("Created", len(lookup))
 	for _, value := range lookup {
 	for _, value := range lookup {
-		outs = append(outs, value)
+		outs.Add(value)
 	}
 	}
 
 
 	// Display images which aren't part of a repository/tag
 	// Display images which aren't part of a repository/tag
-	if filter == "" {
+	if job.Getenv("filter") == "" {
 		for _, image := range allImages {
 		for _, image := range allImages {
-			var out APIImages
-			out.ID = image.ID
-			out.ParentId = image.Parent
-			out.RepoTags = []string{"<none>:<none>"}
-			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{"<none>:<none>"})
+			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.ReverseSort()
+	if _, err := outs.WriteTo(job.Stdout); err != nil {
+		job.Errorf("%s", err)
+		return engine.StatusErr
+	}
+	return engine.StatusOK
 }
 }
 
 
 func (srv *Server) DockerInfo(job *engine.Job) engine.Status {
 func (srv *Server) DockerInfo(job *engine.Job) engine.Status {

+ 0 - 33
sorter.go

@@ -2,39 +2,6 @@ package docker
 
 
 import "sort"
 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 {
 type portSorter struct {
 	ports []Port
 	ports []Port
 	by    func(i, j Port) bool
 	by    func(i, j Port) bool

+ 1 - 1
vendor/src/github.com/gorilla/context/context.go

@@ -92,7 +92,7 @@ func Purge(maxAge int) int {
 		datat = make(map[*http.Request]int64)
 		datat = make(map[*http.Request]int64)
 	} else {
 	} else {
 		min := time.Now().Unix() - int64(maxAge)
 		min := time.Now().Unix() - int64(maxAge)
-		for r, _ := range data {
+		for r := range data {
 			if datat[r] < min {
 			if datat[r] < min {
 				clear(r)
 				clear(r)
 				count++
 				count++

+ 4 - 4
vendor/src/github.com/gorilla/mux/old_test.go

@@ -96,8 +96,8 @@ func TestRouteMatchers(t *testing.T) {
 		method = "GET"
 		method = "GET"
 		headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
 		headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
 		resultVars = map[bool]map[string]string{
 		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"
 		method = "POST"
 		headers = map[string]string{"Content-Type": "application/json"}
 		headers = map[string]string{"Content-Type": "application/json"}
 		resultVars = map[bool]map[string]string{
 		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: {},
 		}
 		}
 	}
 	}