瀏覽代碼

add check to see if the image isn't parent of another and add -f to force

Victor Vieux 12 年之前
父節點
當前提交
67b20f2c8c
共有 7 個文件被更改,包括 37 次插入12 次删除
  1. 10 1
      api.go
  2. 6 1
      api_test.go
  3. 7 1
      commands.go
  4. 3 0
      docs/sources/api/docker_remote_api.rst
  5. 8 6
      server.go
  6. 2 2
      server_test.go
  7. 1 1
      tags.go

+ 10 - 1
api.go

@@ -36,6 +36,8 @@ func httpError(w http.ResponseWriter, err error) {
 		http.Error(w, err.Error(), http.StatusNotFound)
 	} else if strings.HasPrefix(err.Error(), "Bad parameter") {
 		http.Error(w, err.Error(), http.StatusBadRequest)
+	} else if strings.HasPrefix(err.Error(), "Conflict") {
+		http.Error(w, err.Error(), http.StatusConflict)
 	} else {
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
@@ -453,11 +455,18 @@ func deleteContainers(srv *Server, w http.ResponseWriter, r *http.Request, vars
 }
 
 func deleteImages(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+	if err := parseForm(r); err != nil {
+		return err
+	}
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
 	name := vars["name"]
-	if err := srv.ImageDelete(name); err != nil {
+	force, err := getBoolParam(r.Form.Get("force"))
+	if err != nil {
+		return err
+	}
+	if err := srv.ImageDelete(name, force); err != nil {
 		return err
 	}
 	w.WriteHeader(http.StatusNoContent)

+ 6 - 1
api_test.go

@@ -1312,8 +1312,13 @@ func TestDeleteImages(t *testing.T) {
 		t.Errorf("Excepted 2 images, %d found", len(images))
 	}
 
+	req, err := http.NewRequest("DELETE", "/images/test:test", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
 	r := httptest.NewRecorder()
-	if err := deleteImages(srv, r, nil, map[string]string{"name": "test:test"}); err != nil {
+	if err := deleteImages(srv, r, req, map[string]string{"name": "test:test"}); err != nil {
 		t.Fatal(err)
 	}
 	if r.Code != http.StatusNoContent {

+ 7 - 1
commands.go

@@ -459,6 +459,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
 // 'docker rmi IMAGE' removes all images with the name IMAGE
 func (cli *DockerCli) CmdRmi(args ...string) error {
 	cmd := Subcmd("rmi", "IMAGE [IMAGE...]", "Remove an image")
+	force := cmd.Bool("f", false, "Force")
 	if err := cmd.Parse(args); err != nil {
 		return nil
 	}
@@ -467,8 +468,13 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
 		return nil
 	}
 
+	v := url.Values{}
+	if *force {
+		v.Set("force", "1")
+	}
+
 	for _, name := range cmd.Args() {
-		_, _, err := cli.call("DELETE", "/images/"+name, nil)
+		_, _, err := cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil)
 		if err != nil {
 			fmt.Printf("%s", err)
 		} else {

+ 3 - 0
docs/sources/api/docker_remote_api.rst

@@ -728,6 +728,7 @@ Tag an image into a repository
 	:statuscode 200: no error
 	:statuscode 400: bad parameter
 	:statuscode 404: no such image
+	:statuscode 409: conflict
         :statuscode 500: server error
 
 
@@ -750,8 +751,10 @@ Remove an image
 
            HTTP/1.1 204 OK
 
+	:query force: 1/True/true or 0/False/false, default false
 	:statuscode 204: no error
         :statuscode 404: no such image
+	:statuscode 409: conflict
         :statuscode 500: server error
 
 

+ 8 - 6
server.go

@@ -710,7 +710,7 @@ func (srv *Server) ContainerDestroy(name string, removeVolume bool) error {
 	return nil
 }
 
-func (srv *Server) ImageDelete(name string) error {
+func (srv *Server) ImageDelete(name string, force bool) error {
 	img, err := srv.runtime.repositories.LookupImage(name)
 	if err != nil {
 		return fmt.Errorf("No such image: %s", name)
@@ -745,11 +745,13 @@ func (srv *Server) ImageDelete(name string) error {
 		}
 	}
 	// check is the image to delete isn't parent of another image
-	images, _ := srv.runtime.graph.All()
-	for _, image := range images {
-		if imgParent, err := image.GetParent(); err == nil && imgParent != nil {
-			if imgParent.Id == img.Id {
-				return fmt.Errorf("Can't delete %s, otherwise %s will be broken", name, image.ShortId())
+	if !force {
+		images, _ := srv.runtime.graph.All()
+		for _, image := range images {
+			if imgParent, err := image.GetParent(); err == nil && imgParent != nil {
+				if imgParent.Id == img.Id {
+					return fmt.Errorf("Conflict: Can't delete %s otherwise %s will be broken", name, image.ShortId())
+				}
 			}
 		}
 	}

+ 2 - 2
server_test.go

@@ -29,7 +29,7 @@ func TestContainerTagImageDelete(t *testing.T) {
 		t.Errorf("Excepted 3 images, %d found", len(images))
 	}
 
-	if err := srv.ImageDelete("utest/docker:tag2"); err != nil {
+	if err := srv.ImageDelete("utest/docker:tag2", true); err != nil {
 		t.Fatal(err)
 	}
 
@@ -42,7 +42,7 @@ func TestContainerTagImageDelete(t *testing.T) {
 		t.Errorf("Excepted 2 images, %d found", len(images))
 	}
 
-	if err := srv.ImageDelete("utest:tag1"); err != nil {
+	if err := srv.ImageDelete("utest:tag1", true); err != nil {
 		t.Fatal(err)
 	}
 

+ 1 - 1
tags.go

@@ -156,7 +156,7 @@ func (store *TagStore) Set(repoName, tag, imageName string, force bool) error {
 	} else {
 		repo = make(map[string]string)
 		if old, exists := store.Repositories[repoName]; exists && !force {
-			return fmt.Errorf("Tag %s:%s is already set to %s", repoName, tag, old)
+			return fmt.Errorf("Conflict: Tag %s:%s is already set to %s", repoName, tag, old)
 		}
 		store.Repositories[repoName] = repo
 	}