summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/test/criutil/criutil.go11
-rw-r--r--pkg/test/testutil/testutil.go5
-rw-r--r--runsc/boot/loader.go15
-rw-r--r--runsc/container/multi_container_test.go80
-rw-r--r--test/root/crictl_test.go97
5 files changed, 166 insertions, 42 deletions
diff --git a/pkg/test/criutil/criutil.go b/pkg/test/criutil/criutil.go
index bebebb48e..8fed29ff5 100644
--- a/pkg/test/criutil/criutil.go
+++ b/pkg/test/criutil/criutil.go
@@ -113,6 +113,17 @@ func (cc *Crictl) Exec(contID string, args ...string) (string, error) {
return output, nil
}
+// Logs retrieves the container logs. It corresponds to `crictl logs`.
+func (cc *Crictl) Logs(contID string, args ...string) (string, error) {
+ a := []string{"logs", contID}
+ a = append(a, args...)
+ output, err := cc.run(a...)
+ if err != nil {
+ return "", fmt.Errorf("logs failed: %v", err)
+ }
+ return output, nil
+}
+
// Rm removes a container. It corresponds to `crictl rm`.
func (cc *Crictl) Rm(contID string) error {
_, err := cc.run("rm", contID)
diff --git a/pkg/test/testutil/testutil.go b/pkg/test/testutil/testutil.go
index ee8c78014..f21d6769a 100644
--- a/pkg/test/testutil/testutil.go
+++ b/pkg/test/testutil/testutil.go
@@ -251,7 +251,10 @@ func RandomID(prefix string) string {
if _, err := rand.Read(b); err != nil {
panic("rand.Read failed: " + err.Error())
}
- return fmt.Sprintf("%s-%s", prefix, base32.StdEncoding.EncodeToString(b))
+ if prefix != "" {
+ prefix = prefix + "-"
+ }
+ return fmt.Sprintf("%s%s", prefix, base32.StdEncoding.EncodeToString(b))
}
// RandomContainerID generates a random container id for each test.
diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go
index 002479612..b05a8bd45 100644
--- a/runsc/boot/loader.go
+++ b/runsc/boot/loader.go
@@ -754,6 +754,21 @@ func (l *Loader) startContainer(spec *specs.Spec, conf *Config, cid string, file
return err
}
+ // Add the HOME enviroment variable if it is not already set.
+ var envv []string
+ if kernel.VFS2Enabled {
+ envv, err = user.MaybeAddExecUserHomeVFS2(ctx, procArgs.MountNamespaceVFS2,
+ procArgs.Credentials.RealKUID, procArgs.Envv)
+
+ } else {
+ envv, err = user.MaybeAddExecUserHome(ctx, procArgs.MountNamespace,
+ procArgs.Credentials.RealKUID, procArgs.Envv)
+ }
+ if err != nil {
+ return err
+ }
+ procArgs.Envv = envv
+
// Create and start the new process.
tg, _, err := l.k.CreateProcess(procArgs)
if err != nil {
diff --git a/runsc/container/multi_container_test.go b/runsc/container/multi_container_test.go
index c2b54696c..a27a01942 100644
--- a/runsc/container/multi_container_test.go
+++ b/runsc/container/multi_container_test.go
@@ -1698,3 +1698,83 @@ func TestMultiContainerRunNonRoot(t *testing.T) {
t.Fatalf("child container failed, waitStatus: %v", ws)
}
}
+
+// TestMultiContainerHomeEnvDir tests that the HOME environment variable is set
+// for root containers, sub-containers, and execed processes.
+func TestMultiContainerHomeEnvDir(t *testing.T) {
+ // TODO(gvisor.dev/issue/1487): VFSv2 configs failing.
+ // NOTE: Don't use overlay since we need changes to persist to the temp dir
+ // outside the sandbox.
+ for testName, conf := range configs(t, noOverlay...) {
+ t.Run(testName, func(t *testing.T) {
+
+ rootDir, cleanup, err := testutil.SetupRootDir()
+ if err != nil {
+ t.Fatalf("error creating root dir: %v", err)
+ }
+ defer cleanup()
+ conf.RootDir = rootDir
+
+ // Create temp files we can write the value of $HOME to.
+ homeDirs := map[string]*os.File{}
+ for _, name := range []string{"root", "sub", "exec"} {
+ homeFile, err := ioutil.TempFile(testutil.TmpDir(), name)
+ if err != nil {
+ t.Fatalf("creating temp file: %v", err)
+ }
+ homeDirs[name] = homeFile
+ }
+
+ // We will sleep in the root container in order to ensure that
+ // the root container doesn't terminate before sub containers can be
+ // created.
+ rootCmd := []string{"/bin/sh", "-c", fmt.Sprintf("printf \"$HOME\" > %s; sleep 1000", homeDirs["root"].Name())}
+ subCmd := []string{"/bin/sh", "-c", fmt.Sprintf("printf \"$HOME\" > %s", homeDirs["sub"].Name())}
+ execCmd := []string{"/bin/sh", "-c", fmt.Sprintf("printf \"$HOME\" > %s", homeDirs["exec"].Name())}
+
+ // Setup the containers, a root container and sub container.
+ specConfig, ids := createSpecs(rootCmd, subCmd)
+ containers, cleanup, err := startContainers(conf, specConfig, ids)
+ if err != nil {
+ t.Fatalf("error starting containers: %v", err)
+ }
+ defer cleanup()
+
+ // Exec into the root container synchronously.
+ args := &control.ExecArgs{Argv: execCmd}
+ if _, err := containers[0].executeSync(args); err != nil {
+ t.Errorf("error executing %+v: %v", args, err)
+ }
+
+ // Wait for the subcontainer to finish.
+ _, err = containers[1].Wait()
+ if err != nil {
+ t.Errorf("wait on child container: %v", err)
+ }
+
+ // Wait for the root container to run.
+ expectedPL := []*control.Process{
+ newProcessBuilder().Cmd("sh").Process(),
+ newProcessBuilder().Cmd("sleep").Process(),
+ }
+ if err := waitForProcessList(containers[0], expectedPL); err != nil {
+ t.Errorf("failed to wait for sleep to start: %v", err)
+ }
+
+ // Check the written files.
+ for name, tmpFile := range homeDirs {
+ dirBytes, err := ioutil.ReadAll(tmpFile)
+ if err != nil {
+ t.Fatalf("reading %s temp file: %v", name, err)
+ }
+ got := string(dirBytes)
+
+ want := "/"
+ if got != want {
+ t.Errorf("%s $HOME incorrect: got: %q, want: %q", name, got, want)
+ }
+ }
+
+ })
+ }
+}
diff --git a/test/root/crictl_test.go b/test/root/crictl_test.go
index c138e02dc..732fae821 100644
--- a/test/root/crictl_test.go
+++ b/test/root/crictl_test.go
@@ -39,6 +39,29 @@ import (
// Tests for crictl have to be run as root (rather than in a user namespace)
// because crictl creates named network namespaces in /var/run/netns/.
+// Sandbox returns a JSON config for a simple sandbox. Sandbox names must be
+// unique so different names should be used when running tests on the same
+// containerd instance.
+func Sandbox(name string) string {
+ // Sandbox is a default JSON config for a sandbox.
+ s := map[string]interface{}{
+ "metadata": map[string]string{
+ "name": name,
+ "namespace": "default",
+ "uid": testutil.RandomID(""),
+ },
+ "linux": map[string]string{},
+ "log_directory": "/tmp",
+ }
+
+ v, err := json.Marshal(s)
+ if err != nil {
+ // This shouldn't happen.
+ panic(err)
+ }
+ return string(v)
+}
+
// SimpleSpec returns a JSON config for a simple container that runs the
// specified command in the specified image.
func SimpleSpec(name, image string, cmd []string, extra map[string]interface{}) string {
@@ -49,7 +72,9 @@ func SimpleSpec(name, image string, cmd []string, extra map[string]interface{})
"image": map[string]string{
"image": testutil.ImageByName(image),
},
- "log_path": fmt.Sprintf("%s.log", name),
+ // Log files are not deleted after root tests are run. Log to random
+ // paths to ensure logs are fresh.
+ "log_path": fmt.Sprintf("%s.log", testutil.RandomID(name)),
}
if len(cmd) > 0 { // Omit if empty.
s["command"] = cmd
@@ -65,20 +90,6 @@ func SimpleSpec(name, image string, cmd []string, extra map[string]interface{})
return string(v)
}
-// Sandbox is a default JSON config for a sandbox.
-var Sandbox = `{
- "metadata": {
- "name": "default-sandbox",
- "namespace": "default",
- "attempt": 1,
- "uid": "hdishd83djaidwnduwk28bcsb"
- },
- "linux": {
- },
- "log_directory": "/tmp"
-}
-`
-
// Httpd is a JSON config for an httpd container.
var Httpd = SimpleSpec("httpd", "basic/httpd", nil, nil)
@@ -90,7 +101,7 @@ func TestCrictlSanity(t *testing.T) {
t.Fatalf("failed to setup crictl: %v", err)
}
defer cleanup()
- podID, contID, err := crictl.StartPodAndContainer("basic/httpd", Sandbox, Httpd)
+ podID, contID, err := crictl.StartPodAndContainer("basic/httpd", Sandbox("default"), Httpd)
if err != nil {
t.Fatalf("start failed: %v", err)
}
@@ -142,7 +153,7 @@ func TestMountPaths(t *testing.T) {
t.Fatalf("failed to setup crictl: %v", err)
}
defer cleanup()
- podID, contID, err := crictl.StartPodAndContainer("basic/httpd", Sandbox, HttpdMountPaths)
+ podID, contID, err := crictl.StartPodAndContainer("basic/httpd", Sandbox("default"), HttpdMountPaths)
if err != nil {
t.Fatalf("start failed: %v", err)
}
@@ -168,7 +179,7 @@ func TestMountOverSymlinks(t *testing.T) {
defer cleanup()
spec := SimpleSpec("busybox", "basic/resolv", []string{"sleep", "1000"}, nil)
- podID, contID, err := crictl.StartPodAndContainer("basic/resolv", Sandbox, spec)
+ podID, contID, err := crictl.StartPodAndContainer("basic/resolv", Sandbox("default"), spec)
if err != nil {
t.Fatalf("start failed: %v", err)
}
@@ -200,7 +211,7 @@ func TestMountOverSymlinks(t *testing.T) {
}
// TestHomeDir tests that the HOME environment variable is set for
-// multi-containers.
+// Pod containers.
func TestHomeDir(t *testing.T) {
// Setup containerd and crictl.
crictl, cleanup, err := setup(t)
@@ -208,48 +219,52 @@ func TestHomeDir(t *testing.T) {
t.Fatalf("failed to setup crictl: %v", err)
}
defer cleanup()
- contSpec := SimpleSpec("root", "basic/busybox", []string{"sleep", "1000"}, nil)
- podID, contID, err := crictl.StartPodAndContainer("basic/busybox", Sandbox, contSpec)
- if err != nil {
- t.Fatalf("start failed: %v", err)
- }
- t.Run("root container", func(t *testing.T) {
- out, err := crictl.Exec(contID, "sh", "-c", "echo $HOME")
+ // Note that container ID returned here is a sub-container. All Pod
+ // containers are sub-containers. The root container of the sandbox is the
+ // pause container.
+ t.Run("sub-container", func(t *testing.T) {
+ contSpec := SimpleSpec("subcontainer", "basic/busybox", []string{"sh", "-c", "echo $HOME"}, nil)
+ podID, contID, err := crictl.StartPodAndContainer("basic/busybox", Sandbox("subcont-sandbox"), contSpec)
if err != nil {
- t.Fatalf("exec failed: %v, out: %s", err, out)
+ t.Fatalf("start failed: %v", err)
+ }
+
+ out, err := crictl.Logs(contID)
+ if err != nil {
+ t.Fatalf("failed retrieving container logs: %v, out: %s", err, out)
}
if got, want := strings.TrimSpace(string(out)), "/root"; got != want {
t.Fatalf("Home directory invalid. Got %q, Want : %q", got, want)
}
+
+ // Stop everything.
+ if err := crictl.StopPodAndContainer(podID, contID); err != nil {
+ t.Fatalf("stop failed: %v", err)
+ }
})
- t.Run("sub-container", func(t *testing.T) {
- // Create a sub container in the same pod.
- subContSpec := SimpleSpec("subcontainer", "basic/busybox", []string{"sleep", "1000"}, nil)
- subContID, err := crictl.StartContainer(podID, "basic/busybox", Sandbox, subContSpec)
+ // Tests that HOME is set for the exec process.
+ t.Run("exec", func(t *testing.T) {
+ contSpec := SimpleSpec("exec", "basic/busybox", []string{"sleep", "1000"}, nil)
+ podID, contID, err := crictl.StartPodAndContainer("basic/busybox", Sandbox("exec-sandbox"), contSpec)
if err != nil {
t.Fatalf("start failed: %v", err)
}
- out, err := crictl.Exec(subContID, "sh", "-c", "echo $HOME")
+ out, err := crictl.Exec(contID, "sh", "-c", "echo $HOME")
if err != nil {
- t.Fatalf("exec failed: %v, out: %s", err, out)
+ t.Fatalf("failed retrieving container logs: %v, out: %s", err, out)
}
if got, want := strings.TrimSpace(string(out)), "/root"; got != want {
- t.Fatalf("Home directory invalid. Got %q, Want: %q", got, want)
+ t.Fatalf("Home directory invalid. Got %q, Want : %q", got, want)
}
- if err := crictl.StopContainer(subContID); err != nil {
+ // Stop everything.
+ if err := crictl.StopPodAndContainer(podID, contID); err != nil {
t.Fatalf("stop failed: %v", err)
}
})
-
- // Stop everything.
- if err := crictl.StopPodAndContainer(podID, contID); err != nil {
- t.Fatalf("stop failed: %v", err)
- }
-
}
// containerdConfigTemplate is a .toml config for containerd. It contains a