func TestRandomContainerName(t *testing.T) { eng := NewTestEngine(t) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := parseRun([]string{GetTestImage(daemon).ID, "echo test"}) if err != nil { t.Fatal(err) } container, err := daemon.Get(createTestContainer(eng, config, t)) if err != nil { t.Fatal(err) } containerID := container.ID if container.Name == "" { t.Fatalf("Expected not empty container name") } if c, err := daemon.Get(container.Name); err != nil { logrus.Fatalf("Could not lookup container %s by its name", container.Name) } else if c.ID != containerID { logrus.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 := parseRun([]string{unitTestImageID, "echo test"}) if err != nil { t.Fatal(err) } container, err := daemon.Get(createNamedTestContainer(eng, config, t, "some_name")) if err != nil { t.Fatal(err) } containerID := container.ID if container.Name != "/some_name" { t.Fatalf("Expect /some_name got %s", container.Name) } c, err := daemon.Get("/some_name") if err != nil { t.Fatalf("Couldn't retrieve test container as /some_name") } if c.ID != containerID { t.Fatalf("Container /some_name has ID %s instead of %s", c.ID, containerID) } }
func TestGet(t *testing.T) { daemon := mkDaemon(t) defer nuke(daemon) container1, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t) defer daemon.Rm(container1) container2, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t) defer daemon.Rm(container2) container3, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t) defer daemon.Rm(container3) if c, _ := daemon.Get(container1.ID); c != container1 { t.Errorf("Get(test1) returned %v while expecting %v", c, container1) } if c, _ := daemon.Get(container2.ID); c != container2 { t.Errorf("Get(test2) returned %v while expecting %v", c, container2) } if c, _ := daemon.Get(container3.ID); c != container3 { t.Errorf("Get(test3) returned %v while expecting %v", c, container3) } }
func TestGetAllChildren(t *testing.T) { eng := NewTestEngine(t) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}) if err != nil { t.Fatal(err) } container, err := daemon.Get(createNamedTestContainer(eng, config, t, "/webapp")) if err != nil { t.Fatal(err) } 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 = parseRun([]string{unitTestImageID, "echo test"}) if err != nil { t.Fatal(err) } childContainer, err := daemon.Get(createTestContainer(eng, config, t)) if err != nil { t.Fatal(err) } 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) } } }
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 := parseRun([]string{unitTestImageID, "echo test"}) 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, err := daemon.Get(engine.Tail(outputBuffer, 1)) if err != nil { t.Fatal(err) } if container.Name != "/"+test.Name { t.Fatalf("Expect /%s got %s", test.Name, container.Name) } if c, err := daemon.Get("/" + test.Name); err != 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 (srv *Server) ContainerStart(job *engine.Job) engine.Status { if len(job.Args) < 1 { return job.Errorf("Usage: %s container_id", job.Name) } var ( name = job.Args[0] daemon = srv.daemon container = daemon.Get(name) ) if container == nil { return job.Errorf("No such container: %s", name) } if container.State.IsRunning() { return job.Errorf("Container already started") } // If no environment was set, then no hostconfig was passed. if len(job.Environ()) > 0 { hostConfig := runconfig.ContainerHostConfigFromJob(job) if err := srv.setHostConfig(container, hostConfig); err != nil { return job.Error(err) } } if err := container.Start(); err != nil { return job.Errorf("Cannot start container %s: %s", name, err) } srv.LogEvent("start", container.ID, daemon.Repositories().ImageName(container.Image)) return engine.StatusOK }
func TestLinkChildContainer(t *testing.T) { eng := NewTestEngine(t) daemon := mkDaemonFromEngine(eng, t) defer nuke(daemon) config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}) if err != nil { t.Fatal(err) } container, err := daemon.Get(createNamedTestContainer(eng, config, t, "/webapp")) if err != nil { t.Fatal(err) } 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 = parseRun([]string{GetTestImage(daemon).ID, "echo test"}) if err != nil { t.Fatal(err) } childContainer, err := daemon.Get(createTestContainer(eng, config, t)) if err != nil { t.Fatal(err) } 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 getContainer(eng *engine.Engine, id string, t log.Fataler) *daemon.Container { daemon := mkDaemonFromEngine(eng, t) c := daemon.Get(id) if c == nil { t.Fatal(fmt.Errorf("No such container: %s", id)) } return c }
func getContainer(eng *engine.Engine, id string, t Fataler) *daemon.Container { daemon := mkDaemonFromEngine(eng, t) c, err := daemon.Get(id) if err != nil { t.Fatal(err) } return c }
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 := parseRun([]string{unitTestImageID, "echo test"}) if err != nil { if !test.Valid { continue } t.Fatal(err) } containerId, _, err := daemon.ContainerCreate(test.Name, config, &runconfig.HostConfig{}) if err != nil { if !test.Valid { continue } t.Fatal(err) } container, err := daemon.Get(containerId) if err != nil { t.Fatal(err) } if container.Name != "/"+test.Name { t.Fatalf("Expect /%s got %s", test.Name, container.Name) } if c, err := daemon.Get("/" + test.Name); err != 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 TestDestroy(t *testing.T) { daemon := mkDaemon(t) defer nuke(daemon) container, _, err := daemon.Create(&runconfig.Config{ Image: GetTestImage(daemon).ID, Cmd: []string{"ls", "-al"}, }, &runconfig.HostConfig{}, "") if err != nil { t.Fatal(err) } // Destroy if err := daemon.Destroy(container); err != nil { t.Error(err) } // Make sure daemon.Exists() behaves correctly if daemon.Exists("test_destroy") { t.Errorf("Exists() returned true") } // Make sure daemon.List() doesn't list the destroyed container if len(daemon.List()) != 0 { t.Errorf("Expected 0 container, %v found", len(daemon.List())) } // Make sure daemon.Get() refuses to return the unexisting container if daemon.Get(container.ID) != nil { t.Errorf("Unable to get newly created container") } // Test double destroy if err := daemon.Destroy(container); err == nil { // It should have failed t.Errorf("Double destroy did not fail") } }
func startEchoServerContainer(t *testing.T, proto string) (*daemon.Daemon, *daemon.Container, string) { var ( err error id string outputBuffer = bytes.NewBuffer(nil) strPort string eng = NewTestEngine(t) daemon = mkDaemonFromEngine(eng, t) port = 5554 p nat.Port ) defer func() { if err != nil { daemon.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[nat.Port]struct{}, 1) p = nat.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.Add(outputBuffer) if err := jobCreate.Run(); err != nil { t.Fatal(err) } id = engine.Tail(outputBuffer, 1) // FIXME: this relies on the undocumented behavior of daemon.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[nat.Port][]nat.PortBinding) portBindings[p] = []nat.PortBinding{ {}, } if err := jobStart.SetenvJson("PortsBindings", portBindings); err != nil { t.Fatal(err) } if err := jobStart.Run(); err != nil { t.Fatal(err) } container := daemon.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.IsRunning() { time.Sleep(10 * time.Millisecond) } }) // Even if the state is running, lets give some time to lxc to spawn the process container.WaitStop(500 * time.Millisecond) strPort = container.NetworkSettings.Ports[p][0].HostPort return daemon, container, strPort }
func TestDaemonCreate(t *testing.T) { daemon := mkDaemon(t) defer nuke(daemon) // Make sure we start we 0 containers if len(daemon.List()) != 0 { t.Errorf("Expected 0 containers, %v found", len(daemon.List())) } container, _, err := daemon.Create(&runconfig.Config{ Image: GetTestImage(daemon).ID, Cmd: []string{"ls", "-al"}, }, "", ) if err != nil { t.Fatal(err) } defer func() { if err := daemon.Destroy(container); err != nil { t.Error(err) } }() // Make sure we can find the newly created container with List() if len(daemon.List()) != 1 { t.Errorf("Expected 1 container, %v found", len(daemon.List())) } // Make sure the container List() returns is the right one if daemon.List()[0].ID != container.ID { t.Errorf("Unexpected container %v returned by List", daemon.List()[0]) } // Make sure we can get the container with Get() if daemon.Get(container.ID) == nil { t.Errorf("Unable to get newly created container") } // Make sure it is the right container if daemon.Get(container.ID) != container { t.Errorf("Get() returned the wrong container") } // Make sure Exists returns it as existing if !daemon.Exists(container.ID) { t.Errorf("Exists() returned false for a newly created container") } // Test that conflict error displays correct details testContainer, _, _ := daemon.Create( &runconfig.Config{ Image: GetTestImage(daemon).ID, Cmd: []string{"ls", "-al"}, }, "conflictname", ) if _, _, err := daemon.Create(&runconfig.Config{Image: GetTestImage(daemon).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 = daemon.Create(&runconfig.Config{Image: GetTestImage(daemon).ID}, ""); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is missing") } if _, _, err := daemon.Create( &runconfig.Config{ Image: GetTestImage(daemon).ID, Cmd: []string{}, }, "", ); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is empty") } config := &runconfig.Config{ Image: GetTestImage(daemon).ID, Cmd: []string{"/bin/ls"}, PortSpecs: []string{"80"}, } container, _, err = daemon.Create(config, "") _, err = daemon.Commit(container, "testrepo", "testtag", "", "", true, config) if err != nil { t.Error(err) } // test expose 80:8000 container, warnings, err := daemon.Create(&runconfig.Config{ Image: GetTestImage(daemon).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 containerAssertNotExists(eng *engine.Engine, id string, t log.Fataler) { daemon := mkDaemonFromEngine(eng, t) if c := daemon.Get(id); c != nil { t.Fatal(fmt.Errorf("Container %s should not exist", id)) } }
func startEchoServerContainer(t *testing.T, proto string) (*daemon.Daemon, *daemon.Container, string) { var ( err error id string strPort string eng = NewTestEngine(t) daemon = mkDaemonFromEngine(eng, t) port = 5554 p nat.Port ) defer func() { if err != nil { daemon.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[nat.Port]struct{}, 1) p = nat.Port(fmt.Sprintf("%s/%s", strPort, proto)) ep[p] = struct{}{} c := &runconfig.Config{ Image: unitTestImageID, Cmd: runconfig.NewCommand("sh", "-c", cmd), PortSpecs: []string{fmt.Sprintf("%s/%s", strPort, proto)}, ExposedPorts: ep, } id, _, err = daemon.ContainerCreate(unitTestImageID, c, &runconfig.HostConfig{}) // FIXME: this relies on the undocumented behavior of daemon.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) } if err := daemon.ContainerStart(id, &runconfig.HostConfig{}); err != nil { t.Fatal(err) } container, err := daemon.Get(id) if err != nil { t.Fatal(err) } setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() { for !container.IsRunning() { time.Sleep(10 * time.Millisecond) } }) // Even if the state is running, lets give some time to lxc to spawn the process container.WaitStop(500 * time.Millisecond) strPort = container.NetworkSettings.Ports[p][0].HostPort return daemon, container, strPort }