summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--runsc/container/container.go5
-rw-r--r--runsc/container/multi_container_test.go165
2 files changed, 64 insertions, 106 deletions
diff --git a/runsc/container/container.go b/runsc/container/container.go
index 725b4d347..a3454eb8f 100644
--- a/runsc/container/container.go
+++ b/runsc/container/container.go
@@ -517,6 +517,7 @@ func (c *Container) Destroy() error {
log.Warningf("Failed to destroy sandbox %q: %v", c.Sandbox.ID, err)
}
}
+ c.Status = Stopped
c.Sandbox = nil
if c.GoferPid != 0 {
@@ -536,15 +537,11 @@ func (c *Container) Destroy() error {
return fmt.Errorf("error deleting container root directory %q: %v", c.Root, err)
}
- c.Status = Stopped
return nil
}
// IsRunning returns true if the sandbox or gofer process is running.
func (c *Container) IsRunning() bool {
- if c.Status == Stopped {
- return false
- }
if c.Sandbox != nil && c.Sandbox.IsRunning() {
return true
}
diff --git a/runsc/container/multi_container_test.go b/runsc/container/multi_container_test.go
index 34e27383e..cf5140b4e 100644
--- a/runsc/container/multi_container_test.go
+++ b/runsc/container/multi_container_test.go
@@ -20,34 +20,42 @@ import (
"sync"
"testing"
+ specs "github.com/opencontainers/runtime-spec/specs-go"
"gvisor.googlesource.com/gvisor/pkg/sentry/control"
"gvisor.googlesource.com/gvisor/runsc/specutils"
"gvisor.googlesource.com/gvisor/runsc/test/testutil"
)
+func createSpecs(cmds ...[]string) ([]*specs.Spec, []string) {
+ var specs []*specs.Spec
+ var ids []string
+ rootID := testutil.UniqueContainerID()
+
+ for i, cmd := range cmds {
+ spec := testutil.NewSpecWithArgs(cmd...)
+ if i == 0 {
+ spec.Annotations = map[string]string{
+ specutils.ContainerdContainerTypeAnnotation: specutils.ContainerdContainerTypeSandbox,
+ }
+ ids = append(ids, rootID)
+ } else {
+ spec.Annotations = map[string]string{
+ specutils.ContainerdContainerTypeAnnotation: specutils.ContainerdContainerTypeContainer,
+ specutils.ContainerdSandboxIDAnnotation: rootID,
+ }
+ ids = append(ids, testutil.UniqueContainerID())
+ }
+ specs = append(specs, spec)
+ }
+ return specs, ids
+}
+
// TestMultiContainerSanity checks that it is possible to run 2 dead-simple
// containers in the same sandbox.
func TestMultiContainerSanity(t *testing.T) {
for _, conf := range configs(all...) {
t.Logf("Running test with conf: %+v", conf)
- containerIDs := []string{
- testutil.UniqueContainerID(),
- testutil.UniqueContainerID(),
- }
- containerAnnotations := []map[string]string{
- // The first container creates a sandbox.
- map[string]string{
- specutils.ContainerdContainerTypeAnnotation: specutils.ContainerdContainerTypeSandbox,
- },
- // The second container creates a container within the first
- // container's sandbox.
- map[string]string{
- specutils.ContainerdContainerTypeAnnotation: specutils.ContainerdContainerTypeContainer,
- specutils.ContainerdSandboxIDAnnotation: containerIDs[0],
- },
- }
-
rootDir, err := testutil.SetupRootDir()
if err != nil {
t.Fatalf("error creating root dir: %v", err)
@@ -55,16 +63,16 @@ func TestMultiContainerSanity(t *testing.T) {
defer os.RemoveAll(rootDir)
// Setup the containers.
- containers := make([]*Container, 0, len(containerIDs))
- for i, annotations := range containerAnnotations {
- spec := testutil.NewSpecWithArgs("sleep", "100")
- spec.Annotations = annotations
+ sleep := []string{"sleep", "100"}
+ specs, ids := createSpecs(sleep, sleep)
+ var containers []*Container
+ for i, spec := range specs {
bundleDir, err := testutil.SetupContainerInRoot(rootDir, spec, conf)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(bundleDir)
- cont, err := Create(containerIDs[i], spec, conf, bundleDir, "", "")
+ cont, err := Create(ids[i], spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -75,24 +83,11 @@ func TestMultiContainerSanity(t *testing.T) {
containers = append(containers, cont)
}
+ // Check via ps that multiple processes are running.
expectedPL := []*control.Process{
- {
- UID: 0,
- PID: 1,
- PPID: 0,
- C: 0,
- Cmd: "sleep",
- },
- {
- UID: 0,
- PID: 2,
- PPID: 0,
- C: 0,
- Cmd: "sleep",
- },
+ {PID: 1, Cmd: "sleep"},
+ {PID: 2, Cmd: "sleep"},
}
-
- // Check via ps that multiple processes are running.
if err := waitForProcessList(containers[0], expectedPL); err != nil {
t.Errorf("failed to wait for sleep to start: %v", err)
}
@@ -100,50 +95,28 @@ func TestMultiContainerSanity(t *testing.T) {
}
func TestMultiContainerWait(t *testing.T) {
- t.Skip("Test is flakey.") // TODO: Remove.
- containerIDs := []string{
- testutil.UniqueContainerID(),
- testutil.UniqueContainerID(),
- }
- containerAnnotations := []map[string]string{
- // The first container creates a sandbox.
- map[string]string{
- specutils.ContainerdContainerTypeAnnotation: specutils.ContainerdContainerTypeSandbox,
- },
- // The second container creates a container within the first
- // container's sandbox.
- map[string]string{
- specutils.ContainerdContainerTypeAnnotation: specutils.ContainerdContainerTypeContainer,
- specutils.ContainerdSandboxIDAnnotation: containerIDs[0],
- },
- }
- args := [][]string{
- // The first container should run the entire duration of the
- // test.
- {"sleep", "100"},
- // We'll wait on the second container, which is much shorter
- // lived.
- {"sleep", "1"},
- }
-
rootDir, err := testutil.SetupRootDir()
if err != nil {
t.Fatalf("error creating root dir: %v", err)
}
defer os.RemoveAll(rootDir)
+ // The first container should run the entire duration of the test.
+ cmd1 := []string{"sleep", "100"}
+ // We'll wait on the second container, which is much shorter lived.
+ cmd2 := []string{"sleep", "1"}
+ specs, ids := createSpecs(cmd1, cmd2)
+
// Setup the containers.
- containers := make([]*Container, 0, len(containerIDs))
- for i, annotations := range containerAnnotations {
- spec := testutil.NewSpecWithArgs(args[i][0], args[i][1])
- spec.Annotations = annotations
+ var containers []*Container
+ for i, spec := range specs {
conf := testutil.TestConfig()
bundleDir, err := testutil.SetupContainerInRoot(rootDir, spec, conf)
if err != nil {
t.Fatalf("error setting up container: %v", err)
}
defer os.RemoveAll(bundleDir)
- cont, err := Create(containerIDs[i], spec, conf, bundleDir, "", "")
+ cont, err := Create(ids[i], spec, conf, bundleDir, "", "")
if err != nil {
t.Fatalf("error creating container: %v", err)
}
@@ -154,24 +127,11 @@ func TestMultiContainerWait(t *testing.T) {
containers = append(containers, cont)
}
+ // Check via ps that multiple processes are running.
expectedPL := []*control.Process{
- {
- UID: 0,
- PID: 1,
- PPID: 0,
- C: 0,
- Cmd: "sleep",
- },
- {
- UID: 0,
- PID: 2,
- PPID: 0,
- C: 0,
- Cmd: "sleep",
- },
+ {PID: 1, Cmd: "sleep"},
+ {PID: 2, Cmd: "sleep"},
}
-
- // Check via ps that multiple processes are running.
if err := waitForProcessList(containers[0], expectedPL); err != nil {
t.Errorf("failed to wait for sleep to start: %v", err)
}
@@ -180,41 +140,42 @@ func TestMultiContainerWait(t *testing.T) {
wg := sync.WaitGroup{}
for i := 0; i < 3; i++ {
wg.Add(1)
- go func() {
+ go func(c *Container) {
defer wg.Done()
- if ws, err := containers[1].Wait(); err != nil {
- t.Errorf("failed to wait for process %q: %v", strings.Join(containers[1].Spec.Process.Args, " "), err)
+ if ws, err := c.Wait(); err != nil {
+ t.Errorf("failed to wait for process %s: %v", c.Spec.Process.Args, err)
} else if es := ws.ExitStatus(); es != 0 {
- t.Errorf("process %q exited with non-zero status %d", strings.Join(containers[1].Spec.Process.Args, " "), es)
+ t.Errorf("process %s exited with non-zero status %d", c.Spec.Process.Args, es)
}
- if _, err := containers[1].Wait(); err == nil {
- t.Errorf("wait for stopped process %q should fail", strings.Join(containers[1].Spec.Process.Args, " "))
+ if _, err := c.Wait(); err == nil {
+ t.Errorf("wait for stopped process %s should fail", c.Spec.Process.Args)
}
-
- // After Wait returns, ensure that the root container is running and
- // the child has finished.
- if err := waitForProcessList(containers[0], expectedPL[:1]); err != nil {
- t.Errorf("failed to wait for %q to start: %v", strings.Join(containers[0].Spec.Process.Args, " "), err)
- }
- }()
+ }(containers[1])
}
// Also wait via PID.
for i := 0; i < 3; i++ {
wg.Add(1)
- go func() {
+ go func(c *Container) {
defer wg.Done()
const pid = 2
- if ws, err := containers[0].WaitPID(pid); err != nil {
+ if ws, err := c.WaitPID(pid); err != nil {
t.Errorf("failed to wait for PID %d: %v", pid, err)
} else if es := ws.ExitStatus(); es != 0 {
t.Errorf("PID %d exited with non-zero status %d", pid, es)
}
- if _, err := containers[0].WaitPID(pid); err == nil {
+ if _, err := c.WaitPID(pid); err == nil {
t.Errorf("wait for stopped PID %d should fail", pid)
}
- }()
+ // TODO: use 'container[1]' when PID namespace is supported.
+ }(containers[0])
}
wg.Wait()
+
+ // After Wait returns, ensure that the root container is running and
+ // the child has finished.
+ if err := waitForProcessList(containers[0], expectedPL[:1]); err != nil {
+ t.Errorf("failed to wait for %q to start: %v", strings.Join(containers[0].Spec.Process.Args, " "), err)
+ }
}