func TestGetAllChildren(t *testing.T) { eng := NewTestEngine(t) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := daemon.Get(createNamedTestContainer(eng, config, t, "/webapp")) webapp, err := daemon.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 = runconfig.Parse([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } childContainer := daemon.Get(createTestContainer(eng, config, t)) if err := daemon.RegisterLink(webapp, childContainer, "db"); err != nil { t.Fatal(err) } children, err := daemon.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) } } }
// Create a test container from the given daemon `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 *daemon.Daemon, args []string, t *testing.T) (*daemon.Container, *runconfig.HostConfig, error) { config, hc, _, err := runconfig.Parse(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 TestMergeConfigOnCommit(t *testing.T) { eng := NewTestEngine(t) runtime := mkDaemonFromEngine(eng, t) defer runtime.Nuke() container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t) defer runtime.Destroy(container1) config, _, _, err := runconfig.Parse([]string{container1.ID, "cat /tmp/foo"}, nil) if err != nil { t.Error(err) } job := eng.Job("commit", container1.ID) job.Setenv("repo", "testrepo") job.Setenv("tag", "testtag") job.SetenvJson("config", config) var outputBuffer = bytes.NewBuffer(nil) job.Stdout.Add(outputBuffer) if err := job.Run(); err != nil { t.Error(err) } container2, _, _ := mkContainer(runtime, []string{engine.Tail(outputBuffer, 1)}, t) defer runtime.Destroy(container2) job = eng.Job("container_inspect", container1.Name) baseContainer, _ := job.Stdout.AddEnv() if err := job.Run(); err != nil { t.Error(err) } job = eng.Job("container_inspect", container2.Name) commitContainer, _ := job.Stdout.AddEnv() if err := job.Run(); err != nil { t.Error(err) } baseConfig := baseContainer.GetSubEnv("Config") commitConfig := commitContainer.GetSubEnv("Config") if commitConfig.Get("Env") != baseConfig.Get("Env") { t.Fatalf("Env config in committed container should be %v, was %v", baseConfig.Get("Env"), commitConfig.Get("Env")) } if baseConfig.Get("Cmd") != "[\"echo test \\u003e /tmp/foo\"]" { t.Fatalf("Cmd in base container should be [\"echo test \\u003e /tmp/foo\"], was %s", baseConfig.Get("Cmd")) } if commitConfig.Get("Cmd") != "[\"cat /tmp/foo\"]" { t.Fatalf("Cmd in committed container should be [\"cat /tmp/foo\"], was %s", commitConfig.Get("Cmd")) } }
func TestCreateNumberHostname(t *testing.T) { eng := NewTestEngine(t) defer mkDaemonFromEngine(eng, t).Nuke() config, _, _, err := runconfig.Parse([]string{"-h", "web.0", unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } createTestContainer(eng, config, t) }
func TestLinkChildContainer(t *testing.T) { eng := NewTestEngine(t) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := daemon.Get(createNamedTestContainer(eng, config, t, "/webapp")) webapp, err := daemon.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 = runconfig.Parse([]string{GetTestImage(daemon).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } childContainer := daemon.Get(createTestContainer(eng, config, t)) if err := daemon.RegisterLink(webapp, childContainer, "db"); err != nil { t.Fatal(err) } // Get the child by it's new name db, err := daemon.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 TestContainerNameValidation(t *testing.T) { eng := NewTestEngine(t) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) for _, test := range []struct { Name string Valid bool }{ {"abc-123_AAA.1", true}, {"\000asdf", false}, } { config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil) if err != nil { if !test.Valid { continue } t.Fatal(err) } var outputBuffer = bytes.NewBuffer(nil) job := eng.Job("create", test.Name) if err := job.ImportEnv(config); err != nil { t.Fatal(err) } job.Stdout.Add(outputBuffer) if err := job.Run(); err != nil { if !test.Valid { continue } t.Fatal(err) } container := daemon.Get(engine.Tail(outputBuffer, 1)) if container.Name != "/"+test.Name { t.Fatalf("Expect /%s got %s", test.Name, container.Name) } if c := daemon.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 (b *buildFile) CmdRun(args string) error { if b.image == "" { return fmt.Errorf("Please provide a source image with `from` prior to run") } config, _, _, err := runconfig.Parse(append([]string{b.image}, b.buildCmdFromJson(args)...), nil) if err != nil { return err } cmd := b.config.Cmd // set Cmd manually, this is special case only for Dockerfiles b.config.Cmd = config.Cmd runconfig.Merge(b.config, config) defer func(cmd []string) { b.config.Cmd = cmd }(cmd) log.Debugf("Command to be executed: %v", b.config.Cmd) hit, err := b.probeCache() if err != nil { return err } if hit { return nil } c, err := b.create() if err != nil { return err } // Ensure that we keep the container mounted until the commit // to avoid unmounting and then mounting directly again c.Mount() defer c.Unmount() err = b.run(c) if err != nil { return err } if err := b.commit(c.ID, cmd, "run"); err != nil { return err } return nil }
func TestCommit(t *testing.T) { eng := NewTestEngine(t) defer mkDaemonFromEngine(eng, t).Nuke() config, _, _, err := runconfig.Parse([]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) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := runconfig.Parse([]string{GetTestImage(daemon).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := daemon.Get(createTestContainer(eng, config, t)) containerID := container.ID if container.Name == "" { t.Fatalf("Expected not empty container name") } if c := daemon.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) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil) if err != nil { t.Fatal(err) } container := daemon.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 := daemon.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 TestCreateStartRestartStopStartKillRm(t *testing.T) { eng := NewTestEngine(t) defer mkDaemonFromEngine(eng, t).Nuke() config, hostConfig, _, err := runconfig.Parse([]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("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("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 TestRestartKillWait(t *testing.T) { eng := NewTestEngine(t) runtime := mkDaemonFromEngine(eng, t) defer runtime.Nuke() config, hostConfig, _, err := runconfig.Parse([]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 = newTestEngine(t, false, runtime.Config().Root) 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)) } setTimeout(t, "Waiting on stopped container timedout", 5*time.Second, func() { job = eng.Job("wait", outs.Data[0].Get("Id")) if err := job.Run(); err != nil { t.Fatal(err) } }) }