summaryrefslogtreecommitdiffhomepage
path: root/runsc/test/testutil
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/test/testutil')
-rw-r--r--runsc/test/testutil/BUILD1
-rw-r--r--runsc/test/testutil/docker.go6
-rw-r--r--runsc/test/testutil/testutil.go57
3 files changed, 61 insertions, 3 deletions
diff --git a/runsc/test/testutil/BUILD b/runsc/test/testutil/BUILD
index 03ab3c4ac..ca91e07ff 100644
--- a/runsc/test/testutil/BUILD
+++ b/runsc/test/testutil/BUILD
@@ -18,5 +18,6 @@ go_library(
"//runsc/specutils",
"@com_github_cenkalti_backoff//:go_default_library",
"@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_syndtr_gocapability//capability:go_default_library",
],
)
diff --git a/runsc/test/testutil/docker.go b/runsc/test/testutil/docker.go
index b7d60e712..fc67c174a 100644
--- a/runsc/test/testutil/docker.go
+++ b/runsc/test/testutil/docker.go
@@ -32,7 +32,7 @@ func init() {
rand.Seed(time.Now().UnixNano())
}
-func runtime() string {
+func getRuntime() string {
r := os.Getenv("RUNSC_RUNTIME")
if r == "" {
return "runsc-test"
@@ -43,7 +43,7 @@ func runtime() string {
// IsPauseResumeSupported returns true if Pause/Resume is supported by runtime.
func IsPauseResumeSupported() bool {
// Native host network stack can't be saved.
- return !strings.Contains(runtime(), "hostnet")
+ return !strings.Contains(getRuntime(), "hostnet")
}
// EnsureSupportedDockerVersion checks if correct docker is installed.
@@ -128,7 +128,7 @@ type Docker struct {
// Names of containers will be unique.
func MakeDocker(namePrefix string) Docker {
suffix := fmt.Sprintf("-%06d", rand.Int())[:7]
- return Docker{Name: namePrefix + suffix, Runtime: runtime()}
+ return Docker{Name: namePrefix + suffix, Runtime: getRuntime()}
}
// Create calls 'docker create' with the arguments provided.
diff --git a/runsc/test/testutil/testutil.go b/runsc/test/testutil/testutil.go
index fc3d61e52..e90ab5ad5 100644
--- a/runsc/test/testutil/testutil.go
+++ b/runsc/test/testutil/testutil.go
@@ -23,11 +23,16 @@ import (
"io/ioutil"
"net/http"
"os"
+ "os/exec"
"path/filepath"
+ "runtime"
+ "syscall"
+ "testing"
"time"
"github.com/cenkalti/backoff"
specs "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/syndtr/gocapability/capability"
"gvisor.googlesource.com/gvisor/runsc/boot"
"gvisor.googlesource.com/gvisor/runsc/specutils"
)
@@ -227,3 +232,55 @@ func WaitForHTTP(port int, timeout time.Duration) error {
}
return Poll(cb, timeout)
}
+
+// RunAsRoot ensures the test runs with CAP_SYS_ADMIN. If need it will create
+// a new user namespace and reexecute the test as root inside of the namespace.
+func RunAsRoot(m *testing.M) {
+ caps, err := capability.NewPid2(os.Getpid())
+ if err != nil {
+ panic(err.Error())
+ }
+ if err := caps.Load(); err != nil {
+ panic(err.Error())
+ }
+ if caps.Get(capability.EFFECTIVE, capability.CAP_SYS_ADMIN) {
+ // Capability: check! Good to run.
+ os.Exit(m.Run())
+ }
+
+ // Current process doesn't have CAP_SYS_ADMIN, create user namespace and run
+ // as root inside that namespace to get it.
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ cmd := exec.Command("/proc/self/exe", os.Args...)
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Cloneflags: syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS,
+ // Set current user/group as root inside the namespace.
+ UidMappings: []syscall.SysProcIDMap{
+ {ContainerID: 0, HostID: os.Getuid(), Size: 1},
+ },
+ GidMappings: []syscall.SysProcIDMap{
+ {ContainerID: 0, HostID: os.Getgid(), Size: 1},
+ },
+ GidMappingsEnableSetgroups: false,
+ Credential: &syscall.Credential{
+ Uid: 0,
+ Gid: 0,
+ },
+ }
+ cmd.Env = os.Environ()
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ if exit, ok := err.(*exec.ExitError); ok {
+ if ws, ok := exit.Sys().(syscall.WaitStatus); ok {
+ os.Exit(ws.ExitStatus())
+ }
+ os.Exit(-1)
+ }
+ panic(fmt.Sprint("error running child process:", err.Error()))
+ }
+ os.Exit(0)
+}