func TestGetAllChildren(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := runtime.Get(createNamedTestContainer(eng, config, t, "/webapp")) webapp, err := runtime.GetByName("/webapp") if err != nil { t.Fatal(err) } if webapp.ID != container.ID { t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) } config, _, _, err = docker.ParseRun([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } childContainer := runtime.Get(createTestContainer(eng, config, t)) if err := runtime.RegisterLink(webapp, childContainer, "db"); err != nil { t.Fatal(err) } children, err := runtime.Children("/webapp") if err != nil { t.Fatal(err) } if children == nil { t.Fatal("Children should not be nil") } if len(children) == 0 { t.Fatal("Children should not be empty") } for key, value := range children { if key != "/webapp/db" { t.Fatalf("Expected /webapp/db got %s", key) } if value.ID != childContainer.ID { t.Fatalf("Expected id %s got %s", childContainer.ID, value.ID) } } }
// Test that creating a container with a volume doesn't crash. Regression test for #995. func TestCreateVolume(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) config, hc, _, err := docker.ParseRun([]string{"-v", "/var/lib/data", unitTestImageID, "echo", "hello", "world"}, nil) if err != nil { t.Fatal(err) } jobCreate := eng.Job("create") if err := jobCreate.ImportEnv(config); err != nil { t.Fatal(err) } var id string jobCreate.Stdout.AddString(&id) if err := jobCreate.Run(); err != nil { t.Fatal(err) } jobStart := eng.Job("start", id) if err := jobStart.ImportEnv(hc); err != nil { t.Fatal(err) } if err := jobStart.Run(); err != nil { t.Fatal(err) } // FIXME: this hack can be removed once Wait is a job c := runtime.Get(id) if c == nil { t.Fatalf("Couldn't retrieve container %s from runtime", id) } c.WaitTimeout(500 * time.Millisecond) c.Wait() }
// Create a test container from the given runtime `r` and run arguments `args`. // If the image name is "_", (eg. []string{"-i", "-t", "_", "bash"}, it is // dynamically replaced by the current test image. // The caller is responsible for destroying the container. // Call t.Fatal() at the first error. func mkContainer(r *docker.Runtime, args []string, t *testing.T) (*docker.Container, *docker.HostConfig, error) { config, hc, _, err := docker.ParseRun(args, nil) defer func() { if err != nil && t != nil { t.Fatal(err) } }() if err != nil { return nil, nil, err } if config.Image == "_" { config.Image = GetTestImage(r).ID } c, _, err := r.Create(config, "") if err != nil { return nil, nil, err } // NOTE: hostConfig is ignored. // If `args` specify privileged mode, custom lxc conf, external mount binds, // port redirects etc. they will be ignored. // This is because the correct way to set these things is to pass environment // to the `start` job. // FIXME: this helper function should be deprecated in favor of calling // `create` and `start` jobs directly. return c, hc, nil }
func TestCreateRmVolumes(t *testing.T) { eng := NewTestEngine(t) defer mkRuntimeFromEngine(eng, t).Nuke() config, hostConfig, _, err := docker.ParseRun([]string{"-v", "/srv", unitTestImageID, "echo", "test"}, nil) if err != nil { t.Fatal(err) } id := createTestContainer(eng, config, t) job := 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.Errorf("Expected 1 container, %v found", len(outs.Data)) } job = eng.Job("start", id) if err := job.ImportEnv(hostConfig); err != nil { t.Fatal(err) } if err := job.Run(); err != nil { t.Fatal(err) } job = eng.Job("stop", id) job.SetenvInt("t", 1) if err := job.Run(); err != nil { t.Fatal(err) } job = eng.Job("container_delete", id) job.SetenvBool("removeVolume", true) if err := job.Run(); err != nil { t.Fatal(err) } job = 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) != 0 { t.Errorf("Expected 0 container, %v found", len(outs.Data)) } }
func TestCreateNumberUsername(t *testing.T) { eng := NewTestEngine(t) defer mkRuntimeFromEngine(eng, t).Nuke() config, _, _, err := docker.ParseRun([]string{"-u", "1002", unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } createTestContainer(eng, config, t) }
func TestEnv(t *testing.T) { os.Setenv("TRUE", "false") os.Setenv("TRICKY", "tri\ncky\n") runtime := mkRuntime(t) defer nuke(runtime) config, _, _, err := docker.ParseRun([]string{"-e=FALSE=true", "-e=TRUE", "-e=TRICKY", GetTestImage(runtime).ID, "env"}, nil) if err != nil { t.Fatal(err) } container, _, err := runtime.Create(config, "") if err != nil { t.Fatal(err) } defer runtime.Destroy(container) stdout, err := container.StdoutPipe() if err != nil { t.Fatal(err) } defer stdout.Close() if err := container.Start(); err != nil { t.Fatal(err) } container.Wait() output, err := ioutil.ReadAll(stdout) if err != nil { t.Fatal(err) } actualEnv := strings.Split(string(output), "\n") if actualEnv[len(actualEnv)-1] == "" { actualEnv = actualEnv[:len(actualEnv)-1] } sort.Strings(actualEnv) goodEnv := []string{ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HOME=/", "container=lxc", "HOSTNAME=" + utils.TruncateID(container.ID), "FALSE=true", "TRUE=false", "TRICKY=tri", "cky", "", } sort.Strings(goodEnv) if len(goodEnv) != len(actualEnv) { t.Fatalf("Wrong environment: should be %d variables, not: '%s'\n", len(goodEnv), strings.Join(actualEnv, ", ")) } for i := range goodEnv { if actualEnv[i] != goodEnv[i] { t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i]) } } }
func TestLinkChildContainer(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := runtime.Get(createNamedTestContainer(eng, config, t, "/webapp")) webapp, err := runtime.GetByName("/webapp") if err != nil { t.Fatal(err) } if webapp.ID != container.ID { t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) } config, _, _, err = docker.ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } childContainer := runtime.Get(createTestContainer(eng, config, t)) if err := runtime.RegisterLink(webapp, childContainer, "db"); err != nil { t.Fatal(err) } // Get the child by it's new name db, err := runtime.GetByName("/webapp/db") if err != nil { t.Fatal(err) } if db.ID != childContainer.ID { t.Fatalf("Expect db id to match container id: %s != %s", db.ID, childContainer.ID) } }
func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) config, hc, _, err := docker.ParseRun([]string{"-n=false", GetTestImage(runtime).ID, "ip", "addr", "show"}, nil) if err != nil { t.Fatal(err) } jobCreate := eng.Job("create") if err := jobCreate.ImportEnv(config); err != nil { t.Fatal(err) } var id string jobCreate.Stdout.AddString(&id) if err := jobCreate.Run(); err != nil { t.Fatal(err) } // FIXME: this hack can be removed once Wait is a job c := runtime.Get(id) if c == nil { t.Fatalf("Couldn't retrieve container %s from runtime", id) } stdout, err := c.StdoutPipe() if err != nil { t.Fatal(err) } jobStart := eng.Job("start", id) if err := jobStart.ImportEnv(hc); err != nil { t.Fatal(err) } if err := jobStart.Run(); err != nil { t.Fatal(err) } c.WaitTimeout(500 * time.Millisecond) c.Wait() output, err := ioutil.ReadAll(stdout) if err != nil { t.Fatal(err) } interfaces := regexp.MustCompile(`(?m)^[0-9]+: [a-zA-Z0-9]+`).FindAllString(string(output), -1) if len(interfaces) != 1 { t.Fatalf("Wrong interface count in test container: expected [*: lo], got %s", interfaces) } if !strings.HasSuffix(interfaces[0], ": lo") { t.Fatalf("Wrong interface in test container: expected [*: lo], got %s", interfaces) } }
// Regression test for being able to untag an image with an existing // container func TestDeleteTagWithExistingContainers(t *testing.T) { eng := NewTestEngine(t) defer nuke(mkRuntimeFromEngine(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 := docker.ParseRun([]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, err := srv.DeleteImage("utest:tag1", true) if 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 != unitTestImageID { t.Fatalf("Expected %s got %s", unitTestImageID, untag) } }
func TestContainerNameValidation(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) for _, test := range []struct { Name string Valid bool }{ {"abc-123_AAA.1", true}, {"\000asdf", false}, } { config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil) if err != nil { if !test.Valid { continue } t.Fatal(err) } var shortID string job := eng.Job("create", test.Name) if err := job.ImportEnv(config); err != nil { t.Fatal(err) } job.Stdout.AddString(&shortID) if err := job.Run(); err != nil { if !test.Valid { continue } t.Fatal(err) } container := runtime.Get(shortID) if container.Name != "/"+test.Name { t.Fatalf("Expect /%s got %s", test.Name, container.Name) } if c := runtime.Get("/" + test.Name); c == nil { t.Fatalf("Couldn't retrieve test container as /%s", test.Name) } else if c.ID != container.ID { t.Fatalf("Container /%s has ID %s instead of %s", test.Name, c.ID, container.ID) } } }
func TestCommit(t *testing.T) { eng := NewTestEngine(t) defer mkRuntimeFromEngine(eng, t).Nuke() config, _, _, err := docker.ParseRun([]string{unitTestImageID, "/bin/cat"}, nil) if err != nil { t.Fatal(err) } id := createTestContainer(eng, config, t) job := eng.Job("commit", id) job.Setenv("repo", "testrepo") job.Setenv("tag", "testtag") job.SetenvJson("config", config) if err := job.Run(); err != nil { t.Fatal(err) } }
func TestRandomContainerName(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) config, _, _, err := docker.ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := runtime.Get(createTestContainer(eng, config, t)) containerID := container.ID if container.Name == "" { t.Fatalf("Expected not empty container name") } if c := runtime.Get(container.Name); c == nil { log.Fatalf("Could not lookup container %s by its name", container.Name) } else if c.ID != containerID { log.Fatalf("Looking up container name %s returned id %s instead of %s", container.Name, c.ID, containerID) } }
func TestDefaultContainerName(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) defer nuke(runtime) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := runtime.Get(createNamedTestContainer(eng, config, t, "some_name")) containerID := container.ID if container.Name != "/some_name" { t.Fatalf("Expect /some_name got %s", container.Name) } if c := runtime.Get("/some_name"); c == nil { t.Fatalf("Couldn't retrieve test container as /some_name") } else if c.ID != containerID { t.Fatalf("Container /some_name has ID %s instead of %s", c.ID, containerID) } }
func TestRmi(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) defer mkRuntimeFromEngine(eng, t).Nuke() initialImages := getAllImages(eng, t) config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "echo", "test"}, nil) if err != nil { t.Fatal(err) } containerID := createTestContainer(eng, config, t) //To remove job := eng.Job("start", containerID) if err := job.ImportEnv(hostConfig); err != nil { t.Fatal(err) } if err := job.Run(); err != nil { t.Fatal(err) } if err := eng.Job("wait", containerID).Run(); err != nil { t.Fatal(err) } job = eng.Job("commit", containerID) job.Setenv("repo", "test") var imageID string job.Stdout.AddString(&imageID) if err := job.Run(); err != nil { t.Fatal(err) } if err := eng.Job("tag", imageID, "test", "0.1").Run(); err != nil { t.Fatal(err) } containerID = createTestContainer(eng, config, t) //To remove job = eng.Job("start", containerID) if err := job.ImportEnv(hostConfig); err != nil { t.Fatal(err) } if err := job.Run(); err != nil { t.Fatal(err) } if err := eng.Job("wait", containerID).Run(); err != nil { t.Fatal(err) } job = eng.Job("commit", containerID) job.Setenv("repo", "test") if err := job.Run(); err != nil { t.Fatal(err) } images := getAllImages(eng, t) if images.Len()-initialImages.Len() != 2 { t.Fatalf("Expected 2 new images, found %d.", images.Len()-initialImages.Len()) } _, err = srv.DeleteImage(imageID, true) if err != nil { t.Fatal(err) } images = getAllImages(eng, t) if images.Len()-initialImages.Len() != 1 { t.Fatalf("Expected 1 new image, found %d.", images.Len()-initialImages.Len()) } for _, image := range images.Data { if strings.Contains(unitTestImageID, image.Get("Id")) { continue } if image.GetList("RepoTags")[0] == "<none>:<none>" { t.Fatalf("Expected tagged image, got untagged one.") } } }
func TestCreateStartRestartStopStartKillRm(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) defer mkRuntimeFromEngine(eng, t).Nuke() config, hostConfig, _, err := docker.ParseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil) if err != nil { t.Fatal(err) } id := createTestContainer(eng, config, t) 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.Errorf("Expected 1 container, %v found", len(outs.Data)) } job = eng.Job("start", id) if err := job.ImportEnv(hostConfig); err != nil { t.Fatal(err) } if err := job.Run(); err != nil { t.Fatal(err) } job = eng.Job("restart", id) job.SetenvInt("t", 15) if err := job.Run(); err != nil { t.Fatal(err) } job = eng.Job("stop", id) job.SetenvInt("t", 15) if err := job.Run(); err != nil { t.Fatal(err) } job = eng.Job("start", id) if err := job.ImportEnv(hostConfig); err != nil { t.Fatal(err) } if err := job.Run(); err != nil { t.Fatal(err) } if err := eng.Job("kill", id).Run(); err != nil { t.Fatal(err) } // FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty") job = eng.Job("container_delete", id) job.SetenvBool("removeVolume", true) if err := job.Run(); err != nil { t.Fatal(err) } 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) != 0 { t.Errorf("Expected 0 container, %v found", len(outs.Data)) } }
func TestRestartKillWait(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) runtime := mkRuntimeFromEngine(eng, t) defer runtime.Nuke() config, hostConfig, _, err := docker.ParseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil) if err != nil { t.Fatal(err) } id := createTestContainer(eng, config, t) job := 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.Errorf("Expected 1 container, %v found", len(outs.Data)) } job = eng.Job("start", id) if err := job.ImportEnv(hostConfig); err != nil { t.Fatal(err) } if err := job.Run(); err != nil { t.Fatal(err) } job = eng.Job("kill", id) if err := job.Run(); err != nil { t.Fatal(err) } eng, err = engine.New(eng.Root()) if err != nil { t.Fatal(err) } job = eng.Job("initserver") job.Setenv("Root", eng.Root()) job.SetenvBool("AutoRestart", false) // TestGetEnabledCors and TestOptionsRoute require EnableCors=true job.SetenvBool("EnableCors", true) if err := job.Run(); err != nil { t.Fatal(err) } srv = mkServerFromEngine(eng, t) 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.Errorf("Expected 1 container, %v found", len(outs.Data)) } setTimeout(t, "Waiting on stopped container timedout", 5*time.Second, func() { job = srv.Eng.Job("wait", outs.Data[0].Get("Id")) var statusStr string job.Stdout.AddString(&statusStr) if err := job.Run(); err != nil { t.Fatal(err) } }) }