Browse Source

Add compat 1.8

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)
Victor Vieux 11 years ago
parent
commit
3a610f754f
7 changed files with 112 additions and 99 deletions
  1. 2 5
      api.go
  2. 54 51
      commands.go
  3. 35 4
      engine/env.go
  4. 12 28
      integration/api_test.go
  5. 0 2
      integration/server_test.go
  6. 2 2
      integration/sorter_test.go
  7. 7 7
      server.go

+ 2 - 5
api.go

@@ -28,7 +28,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"
@@ -181,18 +181,15 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.
 	if err := parseForm(r); err != nil {
 	if err := parseForm(r); err != nil {
 		return err
 		return err
 	}
 	}
-	fmt.Printf("getImagesJSON\n")
 	job := srv.Eng.Job("images")
 	job := srv.Eng.Job("images")
 	job.Setenv("filter", r.Form.Get("filter"))
 	job.Setenv("filter", r.Form.Get("filter"))
 	job.Setenv("all", r.Form.Get("all"))
 	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)
 	job.Stdout.Add(w)
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
-	fmt.Printf("running images job\n")
 	if err := job.Run(); err != nil {
 	if err := job.Run(); err != nil {
 		return err
 		return err
 	}
 	}
-	fmt.Printf("job has been run\n")
 	return nil
 	return nil
 }
 }
 
 

+ 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")
 	}
 	}

+ 35 - 4
engine/env.go

@@ -237,15 +237,21 @@ func (env *Env) Map() map[string]string {
 type Table struct {
 type Table struct {
 	Data    []*Env
 	Data    []*Env
 	sortKey string
 	sortKey string
+	Chan    chan *Env
 }
 }
 
 
 func NewTable(sortKey string, sizeHint int) *Table {
 func NewTable(sortKey string, sizeHint int) *Table {
 	return &Table{
 	return &Table{
 		make([]*Env, 0, sizeHint),
 		make([]*Env, 0, sizeHint),
 		sortKey,
 		sortKey,
+		make(chan *Env),
 	}
 	}
 }
 }
 
 
+func (t *Table) SetKey(sortKey string) {
+	t.sortKey = sortKey
+}
+
 func (t *Table) Add(env *Env) {
 func (t *Table) Add(env *Env) {
 	t.Data = append(t.Data, env)
 	t.Data = append(t.Data, env)
 }
 }
@@ -279,16 +285,41 @@ func (t *Table) Sort() {
 	sort.Sort(t)
 	sort.Sort(t)
 }
 }
 
 
-func (t *Table) WriteTo(dst io.Writer) (n int64, err error) {
-	for _, env := range t.Data {
+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)
 		bytes, err := env.WriteTo(dst)
 		if err != nil {
 		if err != nil {
 			return -1, err
 			return -1, err
 		}
 		}
-		if _, err := dst.Write([]byte{'\n'}); err != nil {
+		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
 			return -1, err
 		}
 		}
-		n += bytes + 1
+		n += bytes
 	}
 	}
 	return n, nil
 	return n, nil
 }
 }

+ 12 - 28
integration/api_test.go

@@ -204,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) != 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
 	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
 		}
 		}
@@ -237,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 {
+	images3 := engine.NewTable("ID", 0)
+	if _, err := images3.ReadFrom(r3.Body); err != nil {
 		t.Fatal(err)
 		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, "")
 	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)
 	req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)

+ 0 - 2
integration/server_test.go

@@ -324,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)
 	}
 	}

+ 2 - 2
integration/sorter_test.go

@@ -43,8 +43,8 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
 
 
 	images := getImages(eng, t, true, "")
 	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.")
 	}
 	}
 }
 }
 
 

+ 7 - 7
server.go

@@ -573,8 +573,6 @@ func (srv *Server) ImagesViz(out io.Writer) error {
 }
 }
 
 
 func (srv *Server) Images(job *engine.Job) engine.Status {
 func (srv *Server) Images(job *engine.Job) engine.Status {
-	fmt.Printf("Images()\n")
-	srv.Eng.Job("version").Run()
 	var (
 	var (
 		allImages map[string]*Image
 		allImages map[string]*Image
 		err       error
 		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)
 		job.Errorf("%s", err)
 		return engine.StatusErr
 		return engine.StatusErr
-	} else {
-		job.Logf("%d bytes sent", n)
 	}
 	}
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }