diff --git a/components/engine/server.go b/components/engine/server.go index cd2a36b0b3..8b15ecf1b0 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -551,7 +551,10 @@ func (srv *Server) poolAdd(kind, key string) error { defer srv.Unlock() if _, exists := srv.pullingPool[key]; exists { - return fmt.Errorf("%s %s is already in progress", key, kind) + return fmt.Errorf("pull %s is already in progress", key) + } + if _, exists := srv.pushingPool[key]; exists { + return fmt.Errorf("push %s is already in progress", key) } switch kind { diff --git a/components/engine/server_test.go b/components/engine/server_test.go index 104e94bb79..b66c44427e 100644 --- a/components/engine/server_test.go +++ b/components/engine/server_test.go @@ -205,6 +205,110 @@ func TestRunWithTooLowMemoryLimit(t *testing.T) { } +func TestContainerTop(t *testing.T) { + runtime := mkRuntime(t) + srv := &Server{runtime: runtime} + defer nuke(runtime) + + c, hostConfig, _ := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t) + c, hostConfig, err := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t) + if err != nil { + t.Fatal(err) + } + + defer runtime.Destroy(c) + if err := c.Start(hostConfig); err != nil { + t.Fatal(err) + } + + // Give some time to the process to start + c.WaitTimeout(500 * time.Millisecond) + + if !c.State.Running { + t.Errorf("Container should be running") + } + procs, err := srv.ContainerTop(c.ID, "") + if err != nil { + t.Fatal(err) + } + + if len(procs.Processes) != 2 { + t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes)) + } + + pos := -1 + for i := 0; i < len(procs.Titles); i++ { + if procs.Titles[i] == "CMD" { + pos = i + break + } + } + + if pos == -1 { + t.Fatalf("Expected CMD, not found.") + } + + if procs.Processes[0][pos] != "sh" && procs.Processes[0][pos] != "busybox" { + t.Fatalf("Expected `busybox` or `sh`, found %s.", procs.Processes[0][pos]) + } + + if procs.Processes[1][pos] != "sh" && procs.Processes[1][pos] != "busybox" { + t.Fatalf("Expected `busybox` or `sh`, found %s.", procs.Processes[1][pos]) + } +} + +func TestPools(t *testing.T) { + runtime := mkRuntime(t) + srv := &Server{ + runtime: runtime, + pullingPool: make(map[string]struct{}), + pushingPool: make(map[string]struct{}), + } + defer nuke(runtime) + + err := srv.poolAdd("pull", "test1") + if err != nil { + t.Fatal(err) + } + err = srv.poolAdd("pull", "test2") + if err != nil { + t.Fatal(err) + } + err = srv.poolAdd("push", "test1") + if err == nil || err.Error() != "pull test1 is already in progress" { + t.Fatalf("Expected `pull test1 is already in progress`") + } + err = srv.poolAdd("pull", "test1") + if err == nil || err.Error() != "pull test1 is already in progress" { + t.Fatalf("Expected `pull test1 is already in progress`") + } + err = srv.poolAdd("wait", "test3") + if err == nil || err.Error() != "Unkown pool type" { + t.Fatalf("Expected `Unkown pool type`") + } + + err = srv.poolRemove("pull", "test2") + if err != nil { + t.Fatal(err) + } + err = srv.poolRemove("pull", "test2") + if err != nil { + t.Fatal(err) + } + err = srv.poolRemove("pull", "test1") + if err != nil { + t.Fatal(err) + } + err = srv.poolRemove("push", "test1") + if err != nil { + t.Fatal(err) + } + err = srv.poolRemove("wait", "test3") + if err == nil || err.Error() != "Unkown pool type" { + t.Fatalf("Expected `Unkown pool type`") + } +} + func TestLogEvent(t *testing.T) { runtime := mkRuntime(t) srv := &Server{ @@ -240,7 +344,6 @@ func TestLogEvent(t *testing.T) { } } }) - } func TestRmi(t *testing.T) { diff --git a/components/engine/utils.go b/components/engine/utils.go index 16efccd387..2264caefc9 100644 --- a/components/engine/utils.go +++ b/components/engine/utils.go @@ -18,14 +18,16 @@ func CompareConfig(a, b *Config) bool { a.MemorySwap != b.MemorySwap || a.CpuShares != b.CpuShares || a.OpenStdin != b.OpenStdin || - a.Tty != b.Tty { + a.Tty != b.Tty || + a.VolumesFrom != b.VolumesFrom { return false } if len(a.Cmd) != len(b.Cmd) || len(a.Dns) != len(b.Dns) || len(a.Env) != len(b.Env) || len(a.PortSpecs) != len(b.PortSpecs) || - len(a.Entrypoint) != len(b.Entrypoint) { + len(a.Entrypoint) != len(b.Entrypoint) || + len(a.Volumes) != len(b.Volumes) { return false } @@ -54,6 +56,11 @@ func CompareConfig(a, b *Config) bool { return false } } + for key := range a.Volumes { + if _, exists := b.Volumes[key]; !exists { + return false + } + } return true } @@ -125,6 +132,9 @@ func MergeConfig(userConf, imageConf *Config) { if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 { userConf.Entrypoint = imageConf.Entrypoint } + if userConf.VolumesFrom == "" { + userConf.VolumesFrom = imageConf.VolumesFrom + } if userConf.Volumes == nil || len(userConf.Volumes) == 0 { userConf.Volumes = imageConf.Volumes } else { diff --git a/components/engine/utils_test.go b/components/engine/utils_test.go index 91df6183fc..5c37e9e8ec 100644 --- a/components/engine/utils_test.go +++ b/components/engine/utils_test.go @@ -140,15 +140,73 @@ func runContainer(r *Runtime, args []string, t *testing.T) (output string, err e return } +func TestCompareConfig(t *testing.T) { + volumes1 := make(map[string]struct{}) + volumes1["/test1"] = struct{}{} + config1 := Config{ + Dns: []string{"1.1.1.1", "2.2.2.2"}, + PortSpecs: []string{"1111:1111", "2222:2222"}, + Env: []string{"VAR1=1", "VAR2=2"}, + VolumesFrom: "11111111", + Volumes: volumes1, + } + config2 := Config{ + Dns: []string{"0.0.0.0", "2.2.2.2"}, + PortSpecs: []string{"1111:1111", "2222:2222"}, + Env: []string{"VAR1=1", "VAR2=2"}, + VolumesFrom: "11111111", + Volumes: volumes1, + } + config3 := Config{ + Dns: []string{"1.1.1.1", "2.2.2.2"}, + PortSpecs: []string{"0000:0000", "2222:2222"}, + Env: []string{"VAR1=1", "VAR2=2"}, + VolumesFrom: "11111111", + Volumes: volumes1, + } + config4 := Config{ + Dns: []string{"1.1.1.1", "2.2.2.2"}, + PortSpecs: []string{"0000:0000", "2222:2222"}, + Env: []string{"VAR1=1", "VAR2=2"}, + VolumesFrom: "22222222", + Volumes: volumes1, + } + volumes2 := make(map[string]struct{}) + volumes2["/test2"] = struct{}{} + config5 := Config{ + Dns: []string{"1.1.1.1", "2.2.2.2"}, + PortSpecs: []string{"0000:0000", "2222:2222"}, + Env: []string{"VAR1=1", "VAR2=2"}, + VolumesFrom: "11111111", + Volumes: volumes2, + } + if CompareConfig(&config1, &config2) { + t.Fatalf("CompareConfig should return false, Dns are different") + } + if CompareConfig(&config1, &config3) { + t.Fatalf("CompareConfig should return false, PortSpecs are different") + } + if CompareConfig(&config1, &config4) { + t.Fatalf("CompareConfig should return false, VolumesFrom are different") + } + if CompareConfig(&config1, &config5) { + t.Fatalf("CompareConfig should return false, Volumes are different") + } + if !CompareConfig(&config1, &config1) { + t.Fatalf("CompareConfig should return true") + } +} + func TestMergeConfig(t *testing.T) { volumesImage := make(map[string]struct{}) volumesImage["/test1"] = struct{}{} volumesImage["/test2"] = struct{}{} configImage := &Config{ - Dns: []string{"1.1.1.1", "2.2.2.2"}, - PortSpecs: []string{"1111:1111", "2222:2222"}, - Env: []string{"VAR1=1", "VAR2=2"}, - Volumes: volumesImage, + Dns: []string{"1.1.1.1", "2.2.2.2"}, + PortSpecs: []string{"1111:1111", "2222:2222"}, + Env: []string{"VAR1=1", "VAR2=2"}, + VolumesFrom: "1111", + Volumes: volumesImage, } volumesUser := make(map[string]struct{}) @@ -196,6 +254,10 @@ func TestMergeConfig(t *testing.T) { t.Fatalf("Expected /test1 or /test2 or /test3, found %s", v) } } + + if configUser.VolumesFrom != "1111" { + t.Fatalf("Expected VolumesFrom to be 1111, found %s", configUser.VolumesFrom) + } } func TestMergeConfigPublicPortNotHonored(t *testing.T) {