Add compat 1.8

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)
This commit is contained in:
Victor Vieux 2013-12-13 10:26:00 -08:00 committed by Victor Vieux
parent 17a806c8a0
commit 3a610f754f
7 changed files with 112 additions and 99 deletions

7
api.go
View file

@ -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
}

View file

@ -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] != "<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",
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] != "<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 {
fmt.Fprint(cli.out, "\n")
}

View file

@ -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
}

View file

@ -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)

View file

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

View file

@ -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.")
}
}

View file

@ -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
}