diff --git a/integration-cli/docker_cli_rm_test.go b/integration-cli/docker_cli_rm_test.go index b61f1c9a93..08bc2a7224 100644 --- a/integration-cli/docker_cli_rm_test.go +++ b/integration-cli/docker_cli_rm_test.go @@ -3,6 +3,7 @@ package main import ( "os" "os/exec" + "strings" "testing" ) @@ -92,6 +93,69 @@ func TestRemoveContainerWithStopAndKill(t *testing.T) { logDone("rm - with --stop=true and --kill=true") } +func TestContainerOrphaning(t *testing.T) { + dockerfile1 := `FROM busybox:latest + ENTRYPOINT ["/bin/true"]` + img := "test-container-orphaning" + dockerfile2 := `FROM busybox:latest + ENTRYPOINT ["/bin/true"] + MAINTAINER Integration Tests` + + // build first dockerfile + img1, err := buildImage(img, dockerfile1, true) + if err != nil { + t.Fatalf("Could not build image %s: %v", img, err) + } + // run container on first image + if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", img)); err != nil { + t.Fatalf("Could not run image %s: %v: %s", img, err, out) + } + // rebuild dockerfile with a small addition at the end + if _, err := buildImage(img, dockerfile2, true); err != nil { + t.Fatalf("Could not rebuild image %s: %v", img, err) + } + // try to remove the image, should error out. + if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", img)); err == nil { + t.Fatalf("Expected to error out removing the image, but succeeded: %s", out) + } + // check if we deleted the first image + out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "images", "-q", "--no-trunc")) + if err != nil { + t.Fatalf("%v: %s", err, out) + } + if !strings.Contains(out, img1) { + t.Fatal("Orphaned container (could not find '%s' in docker images): %s", img1, out) + } + + deleteAllContainers() + + logDone("rm - container orphaning") +} + +func TestDeleteTagWithExistingContainers(t *testing.T) { + container := "test-delete-tag" + newtag := "busybox:newtag" + bb := "busybox:latest" + if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", bb, newtag)); err != nil { + t.Fatalf("Could not tag busybox: %v: %s", err, out) + } + if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", container, bb, "/bin/true")); err != nil { + t.Fatalf("Could not run busybox: %v: %s", err, out) + } + out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", newtag)) + if err != nil { + t.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out) + } + if d := strings.Count(out, "Untagged: "); d != 1 { + t.Fatalf("Expected 1 untagged entry got %d: %q", d, out) + } + + deleteAllContainers() + + logDone("rm - delete tag with existing containers") + +} + func createRunningContainer(t *testing.T, name string) { cmd := exec.Command(dockerBinary, "run", "-dt", "--name", name, "busybox", "top") if _, err := runCommand(cmd); err != nil { diff --git a/integration/commands_test.go b/integration/commands_test.go index 1e9f18eaf8..44e77e1c7e 100644 --- a/integration/commands_test.go +++ b/integration/commands_test.go @@ -13,7 +13,6 @@ import ( "github.com/docker/docker/api/client" "github.com/docker/docker/daemon" - "github.com/docker/docker/engine" "github.com/docker/docker/pkg/term" "github.com/docker/docker/utils" ) @@ -682,70 +681,3 @@ func TestRunCidFileCleanupIfEmpty(t *testing.T) { <-c }) } - -func TestContainerOrphaning(t *testing.T) { - - // setup a temporary directory - tmpDir, err := ioutil.TempDir("", "project") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) - - // setup a CLI and server - cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) - defer cleanup(globalEngine, t) - srv := mkServerFromEngine(globalEngine, t) - - // closure to build something - buildSomething := func(template string, image string) string { - dockerfile := path.Join(tmpDir, "Dockerfile") - replacer := strings.NewReplacer("{IMAGE}", unitTestImageID) - contents := replacer.Replace(template) - ioutil.WriteFile(dockerfile, []byte(contents), 0x777) - if err := cli.CmdBuild("-t", image, tmpDir); err != nil { - t.Fatal(err) - } - job := globalEngine.Job("image_get", image) - info, _ := job.Stdout.AddEnv() - if err := job.Run(); err != nil { - t.Fatal(err) - } - return info.Get("Id") - } - - // build an image - imageName := "orphan-test" - template1 := ` - from {IMAGE} - cmd ["/bin/echo", "holla"] - ` - img1 := buildSomething(template1, imageName) - - // create a container using the fist image - if err := cli.CmdRun(imageName); err != nil { - t.Fatal(err) - } - - // build a new image that splits lineage - template2 := ` - from {IMAGE} - cmd ["/bin/echo", "holla"] - expose 22 - ` - buildSomething(template2, imageName) - - // remove the second image by name - resp := engine.NewTable("", 0) - if err := srv.DeleteImage(imageName, resp, true, false, false); err == nil { - t.Fatal("Expected error, got none") - } - - // see if we deleted the first image (and orphaned the container) - for _, i := range resp.Data { - if img1 == i.Get("Deleted") { - t.Fatal("Orphaned image with container") - } - } - -} diff --git a/integration/server_test.go b/integration/server_test.go index 7b9f5ade01..241ca76bfe 100644 --- a/integration/server_test.go +++ b/integration/server_test.go @@ -297,56 +297,3 @@ func TestImagesFilter(t *testing.T) { t.Fatal("incorrect number of matches returned") } } - -// Regression test for being able to untag an image with an existing -// container -func TestDeleteTagWithExistingContainers(t *testing.T) { - eng := NewTestEngine(t) - defer nuke(mkDaemonFromEngine(eng, t)) - - srv := mkServerFromEngine(eng, t) - - // Tag the image - if err := eng.Job("tag", unitTestImageID, "utest", "tag1").Run(); err != nil { - t.Fatal(err) - } - - // Create a container from the image - config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil) - if err != nil { - t.Fatal(err) - } - - id := createNamedTestContainer(eng, config, t, "testingtags") - if id == "" { - t.Fatal("No id returned") - } - - job := srv.Eng.Job("containers") - job.SetenvBool("all", true) - outs, err := job.Stdout.AddListTable() - if err != nil { - t.Fatal(err) - } - if err := job.Run(); err != nil { - t.Fatal(err) - } - - if len(outs.Data) != 1 { - t.Fatalf("Expected 1 container got %d", len(outs.Data)) - } - - // Try to remove the tag - imgs := engine.NewTable("", 0) - if err := srv.DeleteImage("utest:tag1", imgs, true, false, false); err != nil { - t.Fatal(err) - } - - if len(imgs.Data) != 1 { - t.Fatalf("Should only have deleted one untag %d", len(imgs.Data)) - } - - if untag := imgs.Data[0].Get("Untagged"); untag != "utest:tag1" { - t.Fatalf("Expected %s got %s", unitTestImageID, untag) - } -}