Signed-off-by: Jessica Frazelle <princess@docker.com>
| ... | ... |
@@ -63,7 +63,8 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi |
| 63 | 63 |
repos := daemon.Repositories().ByID()[img.ID] |
| 64 | 64 |
|
| 65 | 65 |
//If delete by id, see if the id belong only to one repository |
| 66 |
- if repoName == "" {
|
|
| 66 |
+ deleteByID := repoName == "" |
|
| 67 |
+ if deleteByID {
|
|
| 67 | 68 |
for _, repoAndTag := range repos {
|
| 68 | 69 |
parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag) |
| 69 | 70 |
if repoName == "" || repoName == parsedRepo {
|
| ... | ... |
@@ -91,7 +92,7 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi |
| 91 | 91 |
return nil |
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 |
- if len(repos) <= 1 {
|
|
| 94 |
+ if len(repos) <= 1 || (len(repoAndTags) <= 1 && deleteByID) {
|
|
| 95 | 95 |
if err := daemon.canDeleteImage(img.ID, force); err != nil {
|
| 96 | 96 |
return err |
| 97 | 97 |
} |
| ... | ... |
@@ -74,6 +74,55 @@ func (s *DockerSuite) TestRmiTag(c *check.C) {
|
| 74 | 74 |
} |
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 |
+func (s *DockerSuite) TestRmiImgIDMultipleTag(c *check.C) {
|
|
| 78 |
+ runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-one'") |
|
| 79 |
+ out, _, err := runCommandWithOutput(runCmd) |
|
| 80 |
+ if err != nil {
|
|
| 81 |
+ c.Fatalf("failed to create a container:%s, %v", out, err)
|
|
| 82 |
+ } |
|
| 83 |
+ containerID := strings.TrimSpace(out) |
|
| 84 |
+ runCmd = exec.Command(dockerBinary, "commit", containerID, "busybox-one") |
|
| 85 |
+ out, _, err = runCommandWithOutput(runCmd) |
|
| 86 |
+ if err != nil {
|
|
| 87 |
+ c.Fatalf("failed to commit a new busybox-one:%s, %v", out, err)
|
|
| 88 |
+ } |
|
| 89 |
+ |
|
| 90 |
+ imagesBefore, _ := dockerCmd(c, "images", "-a") |
|
| 91 |
+ dockerCmd(c, "tag", "busybox-one", "busybox-one:tag1") |
|
| 92 |
+ dockerCmd(c, "tag", "busybox-one", "busybox-one:tag2") |
|
| 93 |
+ |
|
| 94 |
+ imagesAfter, _ := dockerCmd(c, "images", "-a") |
|
| 95 |
+ if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
|
|
| 96 |
+ c.Fatalf("tag busybox to create 2 more images with same imageID; docker images shows: %q\n", imagesAfter)
|
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ imgID, err := inspectField("busybox-one:tag1", "Id")
|
|
| 100 |
+ c.Assert(err, check.IsNil) |
|
| 101 |
+ |
|
| 102 |
+ // run a container with the image |
|
| 103 |
+ out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox-one", "top")) |
|
| 104 |
+ if err != nil {
|
|
| 105 |
+ c.Fatalf("failed to create a container:%s, %v", out, err)
|
|
| 106 |
+ } |
|
| 107 |
+ containerID = strings.TrimSpace(out) |
|
| 108 |
+ |
|
| 109 |
+ // first checkout without force it fails |
|
| 110 |
+ out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "rmi", imgID)) |
|
| 111 |
+ expected := fmt.Sprintf("Conflict, cannot delete %s because the running container %s is using it, stop it and use -f to force", imgID[:12], containerID[:12])
|
|
| 112 |
+ if err == nil || !strings.Contains(out, expected) {
|
|
| 113 |
+ c.Fatalf("rmi tagged in multiple repos should have failed without force: %s, %v, expected: %s", out, err, expected)
|
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ dockerCmd(c, "stop", containerID) |
|
| 117 |
+ dockerCmd(c, "rmi", "-f", imgID) |
|
| 118 |
+ |
|
| 119 |
+ imagesAfter, _ = dockerCmd(c, "images", "-a") |
|
| 120 |
+ if strings.Contains(imagesAfter, imgID[:12]) {
|
|
| 121 |
+ c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
|
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+} |
|
| 125 |
+ |
|
| 77 | 126 |
func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
|
| 78 | 127 |
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'") |
| 79 | 128 |
out, _, err := runCommandWithOutput(runCmd) |
| ... | ... |
@@ -119,7 +168,6 @@ func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
|
| 119 | 119 |
} |
| 120 | 120 |
|
| 121 | 121 |
func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
|
| 122 |
- |
|
| 123 | 122 |
container := "test-delete-tag" |
| 124 | 123 |
newtag := "busybox:newtag" |
| 125 | 124 |
bb := "busybox:latest" |