func TestGetAllChildren(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) runtime := srv.runtime defer nuke(runtime) config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "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 = 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) } 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) } } }
func TestLinkChildContainer(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{runtime: runtime} config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } shortId, _, err := srv.ContainerCreate(config, "/webapp") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) 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 = ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } shortId, _, err = srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } childContainer := runtime.Get(shortId) 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 (srv *Server) RegisterLinks(name string, hostConfig *HostConfig) error { runtime := srv.runtime container := runtime.Get(name) if container == nil { return fmt.Errorf("No such container: %s", name) } if hostConfig != nil && hostConfig.Links != nil { for _, l := range hostConfig.Links { parts, err := parseLink(l) if err != nil { return err } child, err := srv.runtime.GetByName(parts["name"]) if err != nil { return err } if child == nil { return fmt.Errorf("Could not get container for %s", parts["name"]) } if err := runtime.RegisterLink(container, child, parts["alias"]); err != nil { return err } } // After we load all the links into the runtime // set them to nil on the hostconfig hostConfig.Links = nil if err := container.writeHostConfig(); err != nil { return err } } return nil }
func TestRandomContainerName(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) runtime := srv.runtime defer nuke(runtime) config, _, _, err := 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") } paths := runtime.containerGraph.RefPaths(containerID) if paths == nil || len(paths) == 0 { t.Fatalf("Could not find edges for %s", containerID) } edge := paths[0] if edge.ParentID != "0" { t.Fatalf("Expected engine got %s", edge.ParentID) } if edge.EntityID != containerID { t.Fatalf("Expected %s got %s", containerID, edge.EntityID) } if edge.Name == "" { t.Fatalf("Expected not empty container name") } }
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 TestLinkChildContainer(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) runtime := srv.runtime defer nuke(runtime) config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "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 = 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 TestGet(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) container1, _, _ := mkContainer(runtime, []string{"_", "ls", "-al"}, t) defer runtime.Destroy(container1) container2, _, _ := mkContainer(runtime, []string{"_", "ls", "-al"}, t) defer runtime.Destroy(container2) container3, _, _ := mkContainer(runtime, []string{"_", "ls", "-al"}, t) defer runtime.Destroy(container3) if runtime.Get(container1.ID) != container1 { t.Errorf("Get(test1) returned %v while expecting %v", runtime.Get(container1.ID), container1) } if runtime.Get(container2.ID) != container2 { t.Errorf("Get(test2) returned %v while expecting %v", runtime.Get(container2.ID), container2) } if runtime.Get(container3.ID) != container3 { t.Errorf("Get(test3) returned %v while expecting %v", runtime.Get(container3.ID), container3) } }
func (srv *Server) ContainerStart(job *engine.Job) string { if len(job.Args) < 1 { return fmt.Sprintf("Usage: %s container_id", job.Name) } name := job.Args[0] runtime := srv.runtime container := runtime.Get(name) if container == nil { return fmt.Sprintf("No such container: %s", name) } // If no environment was set, then no hostconfig was passed. if len(job.Environ()) > 0 { var hostConfig HostConfig if err := job.ExportEnv(&hostConfig); err != nil { return err.Error() } // Validate the HostConfig binds. Make sure that: // 1) the source of a bind mount isn't / // The bind mount "/:/foo" isn't allowed. // 2) Check that the source exists // The source to be bind mounted must exist. for _, bind := range hostConfig.Binds { splitBind := strings.Split(bind, ":") source := splitBind[0] // refuse to bind mount "/" to the container if source == "/" { return fmt.Sprintf("Invalid bind mount '%s' : source can't be '/'", bind) } // ensure the source exists on the host _, err := os.Stat(source) if err != nil && os.IsNotExist(err) { return fmt.Sprintf("Invalid bind mount '%s' : source doesn't exist", bind) } } // Register any links from the host config before starting the container // FIXME: we could just pass the container here, no need to lookup by name again. if err := srv.RegisterLinks(name, &hostConfig); err != nil { return err.Error() } container.hostConfig = &hostConfig container.ToDisk() } if err := container.Start(); err != nil { return fmt.Sprintf("Cannot start container %s: %s", name, err) } srv.LogEvent("start", container.ID, runtime.repositories.ImageName(container.Image)) return "0" }
func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error { runtime := srv.runtime container := runtime.Get(name) if container == nil { return fmt.Errorf("No such container: %s", name) } if err := container.Start(hostConfig); err != nil { return fmt.Errorf("Cannot start container %s: %s", name, err) } srv.LogEvent("start", container.ShortID(), runtime.repositories.ImageName(container.Image)) return nil }
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 TestDestroy(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) container, _, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, "") if err != nil { t.Fatal(err) } // Destroy if err := runtime.Destroy(container); err != nil { t.Error(err) } // Make sure runtime.Exists() behaves correctly if runtime.Exists("test_destroy") { t.Errorf("Exists() returned true") } // Make sure runtime.List() doesn't list the destroyed container if len(runtime.List()) != 0 { t.Errorf("Expected 0 container, %v found", len(runtime.List())) } // Make sure runtime.Get() refuses to return the unexisting container if runtime.Get(container.ID) != nil { t.Errorf("Unable to get newly created container") } // Make sure the container root directory does not exist anymore _, err = os.Stat(container.root) if err == nil || !os.IsNotExist(err) { t.Errorf("Container root directory still exists after destroy") } // Test double destroy if err := runtime.Destroy(container); err == nil { // It should have failed t.Errorf("Double destroy did not fail") } }
func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error { runtime := srv.runtime container := runtime.Get(name) if hostConfig != nil { for _, bind := range hostConfig.Binds { splitBind := strings.Split(bind, ":") source := splitBind[0] // refuse to bind mount "/" to the container if source == "/" { return fmt.Errorf("Invalid bind mount '%s' : source can't be '/'", bind) } // ensure the source exists on the host _, err := os.Stat(source) if err != nil && os.IsNotExist(err) { return fmt.Errorf("Invalid bind mount '%s' : source doesn't exist", bind) } } } if container == nil { return fmt.Errorf("No such container: %s", name) } if hostConfig != nil { container.hostConfig = hostConfig container.ToDisk() } if err := container.Start(); err != nil { return fmt.Errorf("Cannot start container %s: %s", name, err) } srv.LogEvent("start", container.ShortID(), runtime.repositories.ImageName(container.Image)) return nil }
func TestRandomContainerName(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{runtime: runtime} config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } shortId, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) containerID := container.ID if container.Name == "" { t.Fatalf("Expected not empty container name") } paths := runtime.containerGraph.RefPaths(containerID) if paths == nil || len(paths) == 0 { t.Fatalf("Could not find edges for %s", containerID) } edge := paths[0] if edge.ParentID != "0" { t.Fatalf("Expected engine got %s", edge.ParentID) } if edge.EntityID != containerID { t.Fatalf("Expected %s got %s", containerID, edge.EntityID) } if edge.Name == "" { t.Fatalf("Expected not empty container name") } }
func startEchoServerContainer(t *testing.T, proto string) (*docker.Runtime, *docker.Container, string) { var ( err error id string strPort string eng = NewTestEngine(t) runtime = mkRuntimeFromEngine(eng, t) port = 5554 p docker.Port ) defer func() { if err != nil { runtime.Nuke() } }() for { port += 1 strPort = strconv.Itoa(port) var cmd string if proto == "tcp" { cmd = "socat TCP-LISTEN:" + strPort + ",reuseaddr,fork EXEC:/bin/cat" } else if proto == "udp" { cmd = "socat UDP-RECVFROM:" + strPort + ",fork EXEC:/bin/cat" } else { t.Fatal(fmt.Errorf("Unknown protocol %v", proto)) } ep := make(map[docker.Port]struct{}, 1) p = docker.Port(fmt.Sprintf("%s/%s", strPort, proto)) ep[p] = struct{}{} jobCreate := eng.Job("create") jobCreate.Setenv("Image", unitTestImageID) jobCreate.SetenvList("Cmd", []string{"sh", "-c", cmd}) jobCreate.SetenvList("PortSpecs", []string{fmt.Sprintf("%s/%s", strPort, proto)}) jobCreate.SetenvJson("ExposedPorts", ep) jobCreate.Stdout.AddString(&id) if err := jobCreate.Run(); err != nil { t.Fatal(err) } // FIXME: this relies on the undocumented behavior of runtime.Create // which will return a nil error AND container if the exposed ports // are invalid. That behavior should be fixed! if id != "" { break } t.Logf("Port %v already in use, trying another one", strPort) } jobStart := eng.Job("start", id) portBindings := make(map[docker.Port][]docker.PortBinding) portBindings[p] = []docker.PortBinding{ {}, } if err := jobStart.SetenvJson("PortsBindings", portBindings); err != nil { t.Fatal(err) } if err := jobStart.Run(); err != nil { t.Fatal(err) } container := runtime.Get(id) if container == nil { t.Fatalf("Couldn't fetch test container %s", id) } setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() { for !container.State.IsRunning() { time.Sleep(10 * time.Millisecond) } }) // Even if the state is running, lets give some time to lxc to spawn the process container.WaitTimeout(500 * time.Millisecond) strPort = container.NetworkSettings.Ports[p][0].HostPort return runtime, container, strPort }
func TestRuntimeCreate(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) // Make sure we start we 0 containers if len(runtime.List()) != 0 { t.Errorf("Expected 0 containers, %v found", len(runtime.List())) } container, _, err := runtime.Create(&docker.Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, "", ) if err != nil { t.Fatal(err) } defer func() { if err := runtime.Destroy(container); err != nil { t.Error(err) } }() // Make sure we can find the newly created container with List() if len(runtime.List()) != 1 { t.Errorf("Expected 1 container, %v found", len(runtime.List())) } // Make sure the container List() returns is the right one if runtime.List()[0].ID != container.ID { t.Errorf("Unexpected container %v returned by List", runtime.List()[0]) } // Make sure we can get the container with Get() if runtime.Get(container.ID) == nil { t.Errorf("Unable to get newly created container") } // Make sure it is the right container if runtime.Get(container.ID) != container { t.Errorf("Get() returned the wrong container") } // Make sure Exists returns it as existing if !runtime.Exists(container.ID) { t.Errorf("Exists() returned false for a newly created container") } // Test that conflict error displays correct details testContainer, _, _ := runtime.Create( &docker.Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, "conflictname", ) if _, _, err := runtime.Create(&docker.Config{Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}}, testContainer.Name); err == nil || !strings.Contains(err.Error(), utils.TruncateID(testContainer.ID)) { t.Fatalf("Name conflict error doesn't include the correct short id. Message was: %s", err.Error()) } // Make sure create with bad parameters returns an error if _, _, err = runtime.Create(&docker.Config{Image: GetTestImage(runtime).ID}, ""); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is missing") } if _, _, err := runtime.Create( &docker.Config{ Image: GetTestImage(runtime).ID, Cmd: []string{}, }, "", ); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is empty") } config := &docker.Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/ls"}, PortSpecs: []string{"80"}, } container, _, err = runtime.Create(config, "") _, err = runtime.Commit(container, "testrepo", "testtag", "", "", config) if err != nil { t.Error(err) } // test expose 80:8000 container, warnings, err := runtime.Create(&docker.Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, PortSpecs: []string{"80:8000"}, }, "", ) if err != nil { t.Fatal(err) } if warnings == nil || len(warnings) != 1 { t.Error("Expected a warning, got none") } }
func TestGetAllChildren(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{runtime: runtime} config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } shortId, _, err := srv.ContainerCreate(config, "/webapp") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) 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 = ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } shortId, _, err = srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } childContainer := runtime.Get(shortId) 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) } } }
func TestRuntimeCreate(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) // Make sure we start we 0 containers if len(runtime.List()) != 0 { t.Errorf("Expected 0 containers, %v found", len(runtime.List())) } builder := NewBuilder(runtime) container, err := builder.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) if err != nil { t.Fatal(err) } defer func() { if err := runtime.Destroy(container); err != nil { t.Error(err) } }() // Make sure we can find the newly created container with List() if len(runtime.List()) != 1 { t.Errorf("Expected 1 container, %v found", len(runtime.List())) } // Make sure the container List() returns is the right one if runtime.List()[0].ID != container.ID { t.Errorf("Unexpected container %v returned by List", runtime.List()[0]) } // Make sure we can get the container with Get() if runtime.Get(container.ID) == nil { t.Errorf("Unable to get newly created container") } // Make sure it is the right container if runtime.Get(container.ID) != container { t.Errorf("Get() returned the wrong container") } // Make sure Exists returns it as existing if !runtime.Exists(container.ID) { t.Errorf("Exists() returned false for a newly created container") } // Make sure crete with bad parameters returns an error _, err = builder.Create( &Config{ Image: GetTestImage(runtime).ID, }, ) if err == nil { t.Fatal("Builder.Create should throw an error when Cmd is missing") } _, err = builder.Create( &Config{ Image: GetTestImage(runtime).ID, Cmd: []string{}, }, ) if err == nil { t.Fatal("Builder.Create should throw an error when Cmd is empty") } }