mirror of
https://github.com/clearlinux/docker.git
synced 2026-09-05 13:11:30 +00:00
Merge pull request #12648 from estesp/userns-impl
Phase 1 implementation of user namespaces as a remapped container root
This commit is contained in:
@@ -45,6 +45,7 @@ func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
server, err := fakeStorage(map[string]string{
|
||||
"testD": `FROM busybox
|
||||
|
||||
@@ -1487,7 +1487,9 @@ func (s *DockerSuite) TestContainersApiCreateNoHostConfig118(c *check.C) {
|
||||
// extract an archive to a symlink in a writable volume which points to a
|
||||
// directory outside of the volume.
|
||||
func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs(c *check.C) {
|
||||
testRequires(c, SameHostDaemon) // Requires local volume mount bind.
|
||||
// Requires local volume mount bind.
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, SameHostDaemon, NotUserNamespace)
|
||||
|
||||
testVol := getTestDir(c, "test-put-container-archive-err-symlink-in-volume-to-read-only-rootfs-")
|
||||
defer os.RemoveAll(testVol)
|
||||
|
||||
@@ -2183,6 +2183,8 @@ func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) {
|
||||
// cat /test1/test2/foo gets permission denied for the user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildrelativecopy"
|
||||
dockerfile := `
|
||||
@@ -2248,7 +2250,7 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
|
||||
testRequires(c, SameHostDaemon)
|
||||
|
||||
name := "testbuildcontextcleanup"
|
||||
entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
|
||||
entries, err := ioutil.ReadDir(filepath.Join(dockerBasePath, "tmp"))
|
||||
if err != nil {
|
||||
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
||||
}
|
||||
@@ -2259,7 +2261,7 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
|
||||
entriesFinal, err := ioutil.ReadDir(filepath.Join(dockerBasePath, "tmp"))
|
||||
if err != nil {
|
||||
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
||||
}
|
||||
@@ -2274,7 +2276,7 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
|
||||
testRequires(c, SameHostDaemon)
|
||||
|
||||
name := "testbuildcontextcleanup"
|
||||
entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
|
||||
entries, err := ioutil.ReadDir(filepath.Join(dockerBasePath, "tmp"))
|
||||
if err != nil {
|
||||
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
||||
}
|
||||
@@ -2285,7 +2287,7 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
|
||||
if err == nil {
|
||||
c.Fatalf("expected build to fail, but it didn't")
|
||||
}
|
||||
entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
|
||||
entriesFinal, err := ioutil.ReadDir(filepath.Join(dockerBasePath, "tmp"))
|
||||
if err != nil {
|
||||
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
||||
}
|
||||
@@ -2683,6 +2685,8 @@ func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildAddLocalFileWithCache(c *check.C) {
|
||||
// local files are not owned by the correct user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildaddlocalfilewithcache"
|
||||
name2 := "testbuildaddlocalfilewithcache2"
|
||||
@@ -2741,6 +2745,8 @@ func (s *DockerSuite) TestBuildAddMultipleLocalFileWithCache(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildAddLocalFileWithoutCache(c *check.C) {
|
||||
// local files are not owned by the correct user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildaddlocalfilewithoutcache"
|
||||
name2 := "testbuildaddlocalfilewithoutcache2"
|
||||
@@ -3862,6 +3868,8 @@ RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/10
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
|
||||
// /docker/world/hello is not owned by the correct user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildenvusage"
|
||||
dockerfile := `FROM busybox
|
||||
@@ -3898,6 +3906,8 @@ RUN [ "$ghi" = "def" ]
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
|
||||
// /docker/world/hello is not owned by the correct user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildenvusage2"
|
||||
dockerfile := `FROM busybox
|
||||
@@ -4024,6 +4034,8 @@ RUN [ "$(cat /testfile)" = 'test!' ]`
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildAddTar(c *check.C) {
|
||||
// /test/foo is not owned by the correct user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildaddtar"
|
||||
|
||||
@@ -4080,7 +4092,8 @@ RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildAddTarXz(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// /test/foo is not owned by the correct user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildaddtarxz"
|
||||
|
||||
@@ -4839,6 +4852,8 @@ func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildXZHost(c *check.C) {
|
||||
// /usr/local/sbin/xz gets permission denied for the user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildxzhost"
|
||||
|
||||
@@ -4867,6 +4882,8 @@ RUN [ ! -e /injected ]`,
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) {
|
||||
// /foo/file gets permission denied for the user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
var (
|
||||
name = "testbuildvolumescontent"
|
||||
|
||||
@@ -559,7 +559,7 @@ func (s *DockerSuite) TestCpSpecialFiles(c *check.C) {
|
||||
// Copy actual /etc/resolv.conf
|
||||
dockerCmd(c, "cp", cleanedContainerID+":/etc/resolv.conf", outDir)
|
||||
|
||||
expected, err := ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/resolv.conf")
|
||||
expected, err := readContainerFile(cleanedContainerID, "resolv.conf")
|
||||
actual, err := ioutil.ReadFile(outDir + "/resolv.conf")
|
||||
|
||||
if !bytes.Equal(actual, expected) {
|
||||
@@ -569,7 +569,7 @@ func (s *DockerSuite) TestCpSpecialFiles(c *check.C) {
|
||||
// Copy actual /etc/hosts
|
||||
dockerCmd(c, "cp", cleanedContainerID+":/etc/hosts", outDir)
|
||||
|
||||
expected, err = ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/hosts")
|
||||
expected, err = readContainerFile(cleanedContainerID, "hosts")
|
||||
actual, err = ioutil.ReadFile(outDir + "/hosts")
|
||||
|
||||
if !bytes.Equal(actual, expected) {
|
||||
@@ -579,7 +579,7 @@ func (s *DockerSuite) TestCpSpecialFiles(c *check.C) {
|
||||
// Copy actual /etc/resolv.conf
|
||||
dockerCmd(c, "cp", cleanedContainerID+":/etc/hostname", outDir)
|
||||
|
||||
expected, err = ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/hostname")
|
||||
expected, err = readContainerFile(cleanedContainerID, "hostname")
|
||||
actual, err = ioutil.ReadFile(outDir + "/hostname")
|
||||
|
||||
if !bytes.Equal(actual, expected) {
|
||||
@@ -589,6 +589,8 @@ func (s *DockerSuite) TestCpSpecialFiles(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestCpVolumePath(c *check.C) {
|
||||
// stat /tmp/cp-test-volumepath851508420/test gets permission denied for the user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon)
|
||||
|
||||
|
||||
@@ -153,6 +153,8 @@ func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) {
|
||||
// Check that copying from a local path to a symlink in a container copies to
|
||||
// the symlink target and does not overwrite the container symlink itself.
|
||||
func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
|
||||
// stat /tmp/test-cp-to-symlink-destination-262430901/vol3 gets permission denied for the user
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon) // Requires local volume mount bind.
|
||||
|
||||
@@ -699,7 +701,8 @@ func (s *DockerSuite) TestCpToCaseJ(c *check.C) {
|
||||
// The `docker cp` command should also ensure that you cannot
|
||||
// write to a container rootfs that is marked as read-only.
|
||||
func (s *DockerSuite) TestCpToErrReadOnlyRootfs(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
tmpDir := getTestDir(c, "test-cp-to-err-read-only-rootfs")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
@@ -732,7 +735,8 @@ func (s *DockerSuite) TestCpToErrReadOnlyRootfs(c *check.C) {
|
||||
// The `docker cp` command should also ensure that you
|
||||
// cannot write to a volume that is mounted as read-only.
|
||||
func (s *DockerSuite) TestCpToErrReadOnlyVolume(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
tmpDir := getTestDir(c, "test-cp-to-err-read-only-volume")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ func (s *DockerSuite) TestCreateRM(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestCreateModeIpcContainer(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon)
|
||||
testRequires(c, SameHostDaemon, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "create", "busybox")
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
@@ -1075,7 +1075,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) {
|
||||
if out, err := s.d.Cmd("wait", id); err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log")
|
||||
logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log")
|
||||
|
||||
if _, err := os.Stat(logPath); err != nil {
|
||||
c.Fatal(err)
|
||||
@@ -1117,7 +1117,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) {
|
||||
if out, err := s.d.Cmd("wait", id); err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log")
|
||||
logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log")
|
||||
|
||||
if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) {
|
||||
c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err)
|
||||
@@ -1159,7 +1159,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) {
|
||||
if out, err := s.d.Cmd("wait", id); err != nil {
|
||||
c.Fatal(out, err)
|
||||
}
|
||||
logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log")
|
||||
logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log")
|
||||
|
||||
if _, err := os.Stat(logPath); err != nil {
|
||||
c.Fatal(err)
|
||||
@@ -1483,7 +1483,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) {
|
||||
testRequires(c, NativeExecDriver)
|
||||
testRequires(c, NativeExecDriver, NotUserNamespace)
|
||||
c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil)
|
||||
|
||||
out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l")
|
||||
|
||||
@@ -265,6 +265,7 @@ func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecCgroup(c *check.C) {
|
||||
testRequires(c, NotUserNamespace)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
dockerCmd(c, "run", "-d", "--name", "testing", "busybox", "top")
|
||||
|
||||
@@ -547,7 +548,7 @@ func (s *DockerSuite) TestExecWithUser(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecWithPrivileged(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
// Start main loop which attempts mknod repeatedly
|
||||
dockerCmd(c, "run", "-d", "--name", "parent", "--cap-drop=ALL", "busybox", "sh", "-c", `while (true); do if [ -e /exec_priv ]; then cat /exec_priv && mknod /tmp/sda b 8 0 && echo "Success"; else echo "Privileged exec has not run yet"; fi; usleep 10000; done`)
|
||||
|
||||
@@ -605,7 +606,8 @@ func (s *DockerSuite) TestExecWithImageUser(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecOnReadonlyContainer(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-d", "--read-only", "--name", "parent", "busybox", "top")
|
||||
if _, status := dockerCmd(c, "exec", "parent", "true"); status != 0 {
|
||||
c.Fatalf("exec into a read-only container failed with exit status %d", status)
|
||||
|
||||
@@ -3,8 +3,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
@@ -21,3 +28,57 @@ func (s *DockerSuite) TestExperimentalVersion(c *check.C) {
|
||||
c.Fatalf("docker version did not contain experimental: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
// user namespaces test: run daemon with remapped root setting
|
||||
// 1. validate uid/gid maps are set properly
|
||||
// 2. verify that files created are owned by remapped root
|
||||
func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *check.C) {
|
||||
testRequires(c, NativeExecDriver)
|
||||
testRequires(c, SameHostDaemon)
|
||||
|
||||
c.Assert(s.d.StartWithBusybox("--userns-remap", "default"), check.IsNil)
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "userns")
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// we need to find the uid and gid of the remapped root from the daemon's root dir info
|
||||
uidgid := strings.Split(filepath.Base(s.d.root), ".")
|
||||
c.Assert(len(uidgid), check.Equals, 2, check.Commentf("Should have gotten uid/gid strings from root dirname: %s", filepath.Base(s.d.root)))
|
||||
uid, err := strconv.Atoi(uidgid[0])
|
||||
c.Assert(err, check.IsNil, check.Commentf("Can't parse uid: %v", err))
|
||||
gid, err := strconv.Atoi(uidgid[1])
|
||||
c.Assert(err, check.IsNil, check.Commentf("Can't parse gid: %v", err))
|
||||
|
||||
//writeable by the remapped root UID/GID pair
|
||||
c.Assert(os.Chown(tmpDir, uid, gid), check.IsNil)
|
||||
|
||||
out, err := s.d.Cmd("run", "-d", "--name", "userns", "-v", tmpDir+":/goofy", "busybox", "sh", "-c", "touch /goofy/testfile; top")
|
||||
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
||||
|
||||
pid, err := s.d.Cmd("inspect", "--format='{{.State.Pid}}'", "userns")
|
||||
if err != nil {
|
||||
c.Fatalf("Could not inspect running container: out: %q; err: %v", pid, err)
|
||||
}
|
||||
// check the uid and gid maps for the PID to ensure root is remapped
|
||||
// (cmd = cat /proc/<pid>/uid_map | grep -E '0\s+9999\s+1')
|
||||
out, rc1, err := runCommandPipelineWithOutput(
|
||||
exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/uid_map"),
|
||||
exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", uid)))
|
||||
c.Assert(rc1, check.Equals, 0, check.Commentf("Didn't match uid_map: output: %s", out))
|
||||
|
||||
out, rc2, err := runCommandPipelineWithOutput(
|
||||
exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/gid_map"),
|
||||
exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", gid)))
|
||||
c.Assert(rc2, check.Equals, 0, check.Commentf("Didn't match gid_map: output: %s", out))
|
||||
|
||||
// check that the touched file is owned by remapped uid:gid
|
||||
stat, err := system.Stat(filepath.Join(tmpDir, "testfile"))
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
c.Assert(stat.UID(), check.Equals, uint32(uid), check.Commentf("Touched file not owned by remapped root UID"))
|
||||
c.Assert(stat.Gid(), check.Equals, uint32(gid), check.Commentf("Touched file not owned by remapped root GID"))
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json")
|
||||
switch t := data.(type) {
|
||||
case error:
|
||||
fmt.Fprintln(w, fmt.Sprintf(`{"Err": %s}`, t.Error()))
|
||||
fmt.Fprintln(w, fmt.Sprintf(`{"Err": %q}`, t.Error()))
|
||||
case string:
|
||||
fmt.Fprintln(w, t)
|
||||
default:
|
||||
@@ -91,13 +91,21 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
decReq := func(b io.ReadCloser, out interface{}, w http.ResponseWriter) error {
|
||||
defer b.Close()
|
||||
if err := json.NewDecoder(b).Decode(&out); err != nil {
|
||||
http.Error(w, fmt.Sprintf("error decoding json: %s", err.Error()), 500)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
base, err := ioutil.TempDir("", "external-graph-test")
|
||||
c.Assert(err, check.IsNil)
|
||||
vfsProto, err := vfs.Init(base, []string{})
|
||||
vfsProto, err := vfs.Init(base, []string{}, nil, nil)
|
||||
if err != nil {
|
||||
c.Fatalf("error initializing graph driver: %v", err)
|
||||
}
|
||||
driver := graphdriver.NewNaiveDiffDriver(vfsProto)
|
||||
driver := graphdriver.NewNaiveDiffDriver(vfsProto, nil, nil)
|
||||
|
||||
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
|
||||
s.ec.activations++
|
||||
@@ -113,8 +121,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.creations++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
if err := driver.Create(req.ID, req.Parent); err != nil {
|
||||
@@ -128,8 +135,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.removals++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -144,8 +150,8 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.gets++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dir, err := driver.Get(req.ID, req.MountLabel)
|
||||
@@ -160,8 +166,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.puts++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -176,8 +181,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.exists++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
respond(w, &graphDriverResponse{Exists: driver.Exists(req.ID)})
|
||||
@@ -185,7 +189,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
|
||||
mux.HandleFunc("/GraphDriver.Status", func(w http.ResponseWriter, r *http.Request) {
|
||||
s.ec.stats++
|
||||
respond(w, `{"Status":{}}`)
|
||||
respond(w, &graphDriverResponse{Status: driver.Status()})
|
||||
})
|
||||
|
||||
mux.HandleFunc("/GraphDriver.Cleanup", func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -202,8 +206,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.metadata++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -219,8 +222,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.diff++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -235,8 +237,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
mux.HandleFunc("/GraphDriver.Changes", func(w http.ResponseWriter, r *http.Request) {
|
||||
s.ec.changes++
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -250,10 +251,17 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
|
||||
mux.HandleFunc("/GraphDriver.ApplyDiff", func(w http.ResponseWriter, r *http.Request) {
|
||||
s.ec.applydiff++
|
||||
var diff archive.Reader = r.Body
|
||||
defer r.Body.Close()
|
||||
|
||||
id := r.URL.Query().Get("id")
|
||||
parent := r.URL.Query().Get("parent")
|
||||
|
||||
size, err := driver.ApplyDiff(id, parent, r.Body)
|
||||
if id == "" {
|
||||
http.Error(w, fmt.Sprintf("missing id"), 409)
|
||||
}
|
||||
|
||||
size, err := driver.ApplyDiff(id, parent, diff)
|
||||
if err != nil {
|
||||
respond(w, err)
|
||||
return
|
||||
@@ -265,8 +273,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||
s.ec.diffsize++
|
||||
|
||||
var req graphDriverRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
if err := decReq(r.Body, &req, w); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -296,7 +303,10 @@ func (s *DockerExternalGraphdriverSuite) TearDownSuite(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriver(c *check.C) {
|
||||
c.Assert(s.d.StartWithBusybox("-s", "test-external-graph-driver"), check.IsNil)
|
||||
if err := s.d.StartWithBusybox("-s", "test-external-graph-driver"); err != nil {
|
||||
b, _ := ioutil.ReadFile(s.d.LogfileName())
|
||||
c.Assert(err, check.IsNil, check.Commentf("\n%s", string(b)))
|
||||
}
|
||||
|
||||
out, err := s.d.Cmd("run", "-d", "--name=graphtest", "busybox", "sh", "-c", "echo hello > /hello")
|
||||
c.Assert(err, check.IsNil, check.Commentf(out))
|
||||
@@ -326,7 +336,7 @@ func (s *DockerExternalGraphdriverSuite) TestExternalGraphDriver(c *check.C) {
|
||||
c.Assert(s.ec.removals >= 1, check.Equals, true)
|
||||
c.Assert(s.ec.gets >= 1, check.Equals, true)
|
||||
c.Assert(s.ec.puts >= 1, check.Equals, true)
|
||||
c.Assert(s.ec.stats, check.Equals, 1)
|
||||
c.Assert(s.ec.stats, check.Equals, 3)
|
||||
c.Assert(s.ec.cleanups, check.Equals, 2)
|
||||
c.Assert(s.ec.exists >= 1, check.Equals, true)
|
||||
c.Assert(s.ec.applydiff >= 1, check.Equals, true)
|
||||
|
||||
@@ -2,10 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-check/check"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestLinksPingUnlinkedContainers(c *check.C) {
|
||||
@@ -233,7 +234,7 @@ func (s *DockerSuite) TestLinkShortDefinition(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top")
|
||||
out, _, err := dockerCmdWithError("run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true")
|
||||
if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior") {
|
||||
@@ -242,7 +243,7 @@ func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
|
||||
if !strings.HasPrefix(out, "-") {
|
||||
c.Errorf("/etc/hosts should be a regular file")
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (s *DockerSuite) TestLinksEtcHostsContentMatch(c *check.C) {
|
||||
// In a _unix file as using Unix specific files, and must be on the
|
||||
// same host as the daemon.
|
||||
testRequires(c, SameHostDaemon)
|
||||
testRequires(c, SameHostDaemon, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "--net=host", "busybox", "cat", "/etc/hosts")
|
||||
hosts, err := ioutil.ReadFile("/etc/hosts")
|
||||
|
||||
@@ -98,7 +98,7 @@ func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, NativeExecDriver)
|
||||
testRequires(c, SameHostDaemon, NativeExecDriver, NotUserNamespace)
|
||||
msg := "it works"
|
||||
startServerContainer(c, msg, 8080)
|
||||
endpoint := getExternalAddress(c)
|
||||
|
||||
@@ -23,7 +23,7 @@ func checkContains(expected string, out string, c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetHostname(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
var (
|
||||
out string
|
||||
@@ -81,7 +81,7 @@ func (s *DockerSuite) TestNetHostname(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestConflictContainerNetworkAndLinks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
var (
|
||||
out string
|
||||
err error
|
||||
@@ -102,7 +102,7 @@ func (s *DockerSuite) TestConflictContainerNetworkAndLinks(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestConflictNetworkModeAndOptions(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
var (
|
||||
out string
|
||||
err error
|
||||
|
||||
@@ -249,7 +249,7 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPortHostBinding(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox",
|
||||
"nc", "-l", "-p", "80")
|
||||
firstID := strings.TrimSpace(out)
|
||||
@@ -272,7 +272,7 @@ func (s *DockerSuite) TestPortHostBinding(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "-d", "-P", "--expose", "80", "busybox",
|
||||
"nc", "-l", "-p", "80")
|
||||
firstID := strings.TrimSpace(out)
|
||||
|
||||
@@ -707,7 +707,7 @@ func (s *DockerSuite) TestRunContainerNetwork(c *check.C) {
|
||||
func (s *DockerSuite) TestRunNetHostNotAllowedWithLinks(c *check.C) {
|
||||
// TODO Windows: This is Linux specific as --link is not supported and
|
||||
// this will be deprecated in favour of container networking model.
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "--name", "linked", "busybox", "true")
|
||||
|
||||
_, _, err := dockerCmdWithError("run", "--net=host", "--link", "linked:linked", "busybox", "true")
|
||||
@@ -733,7 +733,7 @@ func (s *DockerSuite) TestRunFullHostnameSet(c *check.C) {
|
||||
func (s *DockerSuite) TestRunPrivilegedCanMknod(c *check.C) {
|
||||
// Not applicable for Windows as Windows daemon does not support
|
||||
// the concept of --privileged, and mknod is a Unix concept.
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
|
||||
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||
c.Fatalf("expected output ok received %s", actual)
|
||||
@@ -743,7 +743,7 @@ func (s *DockerSuite) TestRunPrivilegedCanMknod(c *check.C) {
|
||||
func (s *DockerSuite) TestRunUnprivilegedCanMknod(c *check.C) {
|
||||
// Not applicable for Windows as Windows daemon does not support
|
||||
// the concept of --privileged, and mknod is a Unix concept.
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
|
||||
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||
c.Fatalf("expected output ok received %s", actual)
|
||||
@@ -799,7 +799,7 @@ func (s *DockerSuite) TestRunCapDropALLCannotMknod(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunCapDropALLAddMknodCanMknod(c *check.C) {
|
||||
// Not applicable for Windows as there is no concept of --cap-drop or mknod
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "--cap-add=SETGID", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
|
||||
|
||||
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||
@@ -861,7 +861,7 @@ func (s *DockerSuite) TestRunGroupAdd(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunPrivilegedCanMount(c *check.C) {
|
||||
// Not applicable for Windows as there is no concept of --privileged
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--privileged", "busybox", "sh", "-c", "mount -t tmpfs none /tmp && echo ok")
|
||||
|
||||
if actual := strings.Trim(out, "\r\n"); actual != "ok" {
|
||||
@@ -892,7 +892,7 @@ func (s *DockerSuite) TestRunSysNotWritableInNonPrivilegedContainers(c *check.C)
|
||||
|
||||
func (s *DockerSuite) TestRunSysWritableInPrivilegedContainers(c *check.C) {
|
||||
// Not applicable for Windows as there is no concept of unprivileged
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
if _, code, err := dockerCmdWithError("run", "--privileged", "busybox", "touch", "/sys/kernel/profiling"); err != nil || code != 0 {
|
||||
c.Fatalf("sys should be writable in privileged container")
|
||||
}
|
||||
@@ -908,7 +908,7 @@ func (s *DockerSuite) TestRunProcNotWritableInNonPrivilegedContainers(c *check.C
|
||||
|
||||
func (s *DockerSuite) TestRunProcWritableInPrivilegedContainers(c *check.C) {
|
||||
// Not applicable for Windows as there is no concept of --privileged
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
if _, code := dockerCmd(c, "run", "--privileged", "busybox", "touch", "/proc/sysrq-trigger"); code != 0 {
|
||||
c.Fatalf("proc should be writable in privileged container")
|
||||
}
|
||||
@@ -916,7 +916,8 @@ func (s *DockerSuite) TestRunProcWritableInPrivilegedContainers(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunDeviceNumbers(c *check.C) {
|
||||
// Not applicable on Windows as /dev/ is a Unix specific concept
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// TODO: NotUserNamespace could be removed here if "root" "root" is replaced w user
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "busybox", "sh", "-c", "ls -l /dev/null")
|
||||
deviceLineFields := strings.Fields(out)
|
||||
deviceLineFields[6] = ""
|
||||
@@ -946,7 +947,7 @@ func (s *DockerSuite) TestRunUnprivilegedWithChroot(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunAddingOptionalDevices(c *check.C) {
|
||||
// Not applicable on Windows as Windows does not support --device
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--device", "/dev/zero:/dev/nulo", "busybox", "sh", "-c", "ls /dev/nulo")
|
||||
if actual := strings.Trim(out, "\r\n"); actual != "/dev/nulo" {
|
||||
c.Fatalf("expected output /dev/nulo, received %s", actual)
|
||||
@@ -955,7 +956,7 @@ func (s *DockerSuite) TestRunAddingOptionalDevices(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunAddingOptionalDevicesNoSrc(c *check.C) {
|
||||
// Not applicable on Windows as Windows does not support --device
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--device", "/dev/zero:rw", "busybox", "sh", "-c", "ls /dev/zero")
|
||||
if actual := strings.Trim(out, "\r\n"); actual != "/dev/zero" {
|
||||
c.Fatalf("expected output /dev/zero, received %s", actual)
|
||||
@@ -964,7 +965,7 @@ func (s *DockerSuite) TestRunAddingOptionalDevicesNoSrc(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunAddingOptionalDevicesInvalidMode(c *check.C) {
|
||||
// Not applicable on Windows as Windows does not support --device
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
_, _, err := dockerCmdWithError("run", "--device", "/dev/zero:ro", "busybox", "sh", "-c", "ls /dev/zero")
|
||||
if err == nil {
|
||||
c.Fatalf("run container with device mode ro should fail")
|
||||
@@ -973,7 +974,7 @@ func (s *DockerSuite) TestRunAddingOptionalDevicesInvalidMode(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModeHostname(c *check.C) {
|
||||
// Not applicable on Windows as Windows does not support -h
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "-h=testhostname", "busybox", "cat", "/etc/hostname")
|
||||
|
||||
@@ -1711,6 +1712,8 @@ func (s *DockerSuite) TestRunEntrypoint(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunBindMounts(c *check.C) {
|
||||
// /tmp gets permission denied
|
||||
testRequires(c, NotUserNamespace)
|
||||
// Cannot run on Windows as Windows does not support volumes
|
||||
testRequires(c, DaemonIsLinux, SameHostDaemon)
|
||||
|
||||
@@ -1909,6 +1912,8 @@ func (s *DockerSuite) TestRunAllocatePortInReservedRange(c *check.C) {
|
||||
|
||||
// Regression test for #7792
|
||||
func (s *DockerSuite) TestRunMountOrdering(c *check.C) {
|
||||
// tmp gets permission denied
|
||||
testRequires(c, NotUserNamespace)
|
||||
// Not applicable on Windows as Windows does not support volumes
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
|
||||
@@ -1953,6 +1958,8 @@ func (s *DockerSuite) TestRunMountOrdering(c *check.C) {
|
||||
|
||||
// Regression test for https://github.com/docker/docker/issues/8259
|
||||
func (s *DockerSuite) TestRunReuseBindVolumeThatIsSymlink(c *check.C) {
|
||||
// /tmp gets permission denied
|
||||
testRequires(c, NotUserNamespace)
|
||||
// Not applicable on Windows as Windows does not support volumes
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
|
||||
@@ -2157,7 +2164,7 @@ func (s *DockerSuite) TestRunUnknownCommand(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModeIpcHost(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
hostIpc, err := os.Readlink("/proc/1/ns/ipc")
|
||||
if err != nil {
|
||||
@@ -2179,7 +2186,7 @@ func (s *DockerSuite) TestRunModeIpcHost(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && top")
|
||||
|
||||
@@ -2211,7 +2218,7 @@ func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _, err := dockerCmdWithError("run", "-d", "--ipc", "container:abcd1234", "busybox", "top")
|
||||
if !strings.Contains(out, "abcd1234") || err == nil {
|
||||
c.Fatalf("run IPC from a non exists container should with correct error out")
|
||||
@@ -2220,7 +2227,7 @@ func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModeIpcContainerNotRunning(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "create", "busybox")
|
||||
|
||||
@@ -2250,7 +2257,7 @@ func (s *DockerSuite) TestRunMountShmMqueueFromHost(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestContainerNetworkMode(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
|
||||
id := strings.TrimSpace(out)
|
||||
@@ -2272,7 +2279,7 @@ func (s *DockerSuite) TestContainerNetworkMode(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModePidHost(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, NativeExecDriver, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, NativeExecDriver, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
hostPid, err := os.Readlink("/proc/1/ns/pid")
|
||||
if err != nil {
|
||||
@@ -2413,7 +2420,7 @@ func (s *DockerSuite) TestRunNonLocalMacAddress(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunNetHost(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
hostNet, err := os.Readlink("/proc/1/ns/net")
|
||||
if err != nil {
|
||||
@@ -2436,7 +2443,7 @@ func (s *DockerSuite) TestRunNetHost(c *check.C) {
|
||||
func (s *DockerSuite) TestRunNetHostTwiceSameName(c *check.C) {
|
||||
// TODO Windows. As Windows networking evolves and converges towards
|
||||
// CNM, this test may be possible to enable on Windows.
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
dockerCmd(c, "run", "--rm", "--name=thost", "--net=host", "busybox", "true")
|
||||
dockerCmd(c, "run", "--rm", "--name=thost", "--net=host", "busybox", "true")
|
||||
@@ -2444,7 +2451,7 @@ func (s *DockerSuite) TestRunNetHostTwiceSameName(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunNetContainerWhichHost(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
hostNet, err := os.Readlink("/proc/1/ns/net")
|
||||
if err != nil {
|
||||
@@ -2534,7 +2541,8 @@ func (s *DockerSuite) TestRunContainerWithReadonlyRootfs(c *check.C) {
|
||||
func (s *DockerSuite) TestPermissionsPtsReadonlyRootfs(c *check.C) {
|
||||
// Not applicable on Windows due to use of Unix specific functionality, plus
|
||||
// the use of --read-only which is not supported.
|
||||
testRequires(c, DaemonIsLinux, NativeExecDriver)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, DaemonIsLinux, NativeExecDriver, NotUserNamespace)
|
||||
|
||||
// Ensure we have not broken writing /dev/pts
|
||||
out, status := dockerCmd(c, "run", "--read-only", "--rm", "busybox", "mount")
|
||||
@@ -2549,7 +2557,7 @@ func (s *DockerSuite) TestPermissionsPtsReadonlyRootfs(c *check.C) {
|
||||
|
||||
func testReadOnlyFile(filename string, c *check.C) {
|
||||
// Not applicable on Windows which does not support --read-only
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux)
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _, err := dockerCmdWithError("run", "--read-only", "--rm", "busybox", "touch", filename)
|
||||
if err == nil {
|
||||
@@ -2572,7 +2580,8 @@ func testReadOnlyFile(filename string, c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer(c *check.C) {
|
||||
// Not applicable on Windows which does not support --link
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
dockerCmd(c, "run", "-d", "--name", "test-etc-hosts-ro-linked", "busybox", "top")
|
||||
|
||||
@@ -2583,9 +2592,9 @@ func (s *DockerSuite) TestRunContainerWithReadonlyEtcHostsAndLinkedContainer(c *
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithDnsFlag(c *check.C) {
|
||||
// Not applicable on Windows which does not support either --read-only or
|
||||
// --dns.
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux)
|
||||
// Not applicable on Windows which does not support either --read-only or --dns.
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "--read-only", "--dns", "1.1.1.1", "busybox", "/bin/cat", "/etc/resolv.conf")
|
||||
if !strings.Contains(string(out), "1.1.1.1") {
|
||||
@@ -2595,7 +2604,8 @@ func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithDnsFlag(c *check.C)
|
||||
|
||||
func (s *DockerSuite) TestRunContainerWithReadonlyRootfsWithAddHostFlag(c *check.C) {
|
||||
// Not applicable on Windows which does not support --read-only
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, NativeExecDriver, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
out, _ := dockerCmd(c, "run", "--read-only", "--add-host", "testreadonly:127.0.0.1", "busybox", "/bin/cat", "/etc/hosts")
|
||||
if !strings.Contains(string(out), "testreadonly") {
|
||||
@@ -2654,7 +2664,7 @@ func (s *DockerSuite) TestRunContainerWithRmFlagCannotStartContainer(c *check.C)
|
||||
|
||||
func (s *DockerSuite) TestRunPidHostWithChildIsKillable(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix specific functionality
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
name := "ibuildthecloud"
|
||||
dockerCmd(c, "run", "-d", "--pid=host", "--name", name, "busybox", "sh", "-c", "sleep 30; echo hi")
|
||||
|
||||
@@ -2734,7 +2744,7 @@ func (s *DockerSuite) TestRunReadProcLatency(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunReadFilteredProc(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix specific functionality
|
||||
testRequires(c, Apparmor, DaemonIsLinux)
|
||||
testRequires(c, Apparmor, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
testReadPaths := []string{
|
||||
"/proc/latency_stats",
|
||||
@@ -2767,7 +2777,8 @@ func (s *DockerSuite) TestMountIntoProc(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestMountIntoSys(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix specific functionality
|
||||
testRequires(c, DaemonIsLinux, NativeExecDriver)
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, NativeExecDriver, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-v", "/sys/fs/cgroup", "busybox", "true")
|
||||
}
|
||||
|
||||
@@ -2854,7 +2865,7 @@ func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunWriteFilteredProc(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix specific functionality
|
||||
testRequires(c, Apparmor, NativeExecDriver, DaemonIsLinux)
|
||||
testRequires(c, Apparmor, NativeExecDriver, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
testWritePaths := []string{
|
||||
/* modprobe and core_pattern should both be denied by generic
|
||||
@@ -2917,7 +2928,8 @@ func (s *DockerSuite) TestRunNetworkFilesBindMountRO(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunNetworkFilesBindMountROFilesystem(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix specific functionality
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
filename := createTmpFile(c, "test123")
|
||||
defer os.Remove(filename)
|
||||
@@ -3260,7 +3272,8 @@ func (s *DockerSuite) TestRunContainerWithCgroupParentAbsPath(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunContainerWithCgroupMountRO(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix specific functionality
|
||||
testRequires(c, DaemonIsLinux, NativeExecDriver)
|
||||
// --read-only + userns has remount issues
|
||||
testRequires(c, DaemonIsLinux, NativeExecDriver, NotUserNamespace)
|
||||
|
||||
filename := "/sys/fs/cgroup/devices/test123"
|
||||
out, _, err := dockerCmdWithError("run", "busybox", "touch", filename)
|
||||
@@ -3275,7 +3288,7 @@ func (s *DockerSuite) TestRunContainerWithCgroupMountRO(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunContainerNetworkModeToSelf(c *check.C) {
|
||||
// Not applicable on Windows which does not support --net=container
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _, err := dockerCmdWithError("run", "--name=me", "--net=container:me", "busybox", "true")
|
||||
if err == nil || !strings.Contains(out, "cannot join own network") {
|
||||
c.Fatalf("using container net mode to self should result in an error\nerr: %q\nout: %s", err, out)
|
||||
@@ -3284,7 +3297,7 @@ func (s *DockerSuite) TestRunContainerNetworkModeToSelf(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunContainerNetModeWithDnsMacHosts(c *check.C) {
|
||||
// Not applicable on Windows which does not support --net=container
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _, err := dockerCmdWithError("run", "-d", "--name", "parent", "busybox", "top")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to run container: %v, output: %q", err, out)
|
||||
@@ -3308,7 +3321,7 @@ func (s *DockerSuite) TestRunContainerNetModeWithDnsMacHosts(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunContainerNetModeWithExposePort(c *check.C) {
|
||||
// Not applicable on Windows which does not support --net=container
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-d", "--name", "parent", "busybox", "top")
|
||||
|
||||
out, _, err := dockerCmdWithError("run", "-p", "5000:5000", "--net=container:parent", "busybox")
|
||||
@@ -3329,7 +3342,7 @@ func (s *DockerSuite) TestRunContainerNetModeWithExposePort(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunLinkToContainerNetMode(c *check.C) {
|
||||
// Not applicable on Windows which does not support --net=container or --link
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "--name", "test", "-d", "busybox", "top")
|
||||
dockerCmd(c, "run", "--name", "parent", "-d", "--net=container:test", "busybox", "top")
|
||||
dockerCmd(c, "run", "-d", "--link=parent:parent", "busybox", "top")
|
||||
@@ -3373,7 +3386,7 @@ func (s *DockerSuite) TestRunLoopbackWhenNetworkDisabled(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestRunModeNetContainerHostname(c *check.C) {
|
||||
// Windows does not support --net=container
|
||||
testRequires(c, DaemonIsLinux, ExecSupport)
|
||||
testRequires(c, DaemonIsLinux, ExecSupport, NotUserNamespace)
|
||||
|
||||
dockerCmd(c, "run", "-i", "-d", "--name", "parent", "busybox", "top")
|
||||
out, _ := dockerCmd(c, "exec", "parent", "cat", "/etc/hostname")
|
||||
@@ -3399,7 +3412,7 @@ func (s *DockerSuite) TestRunNetworkNotInitializedNoneMode(c *check.C) {
|
||||
|
||||
func (s *DockerSuite) TestTwoContainersInNetHost(c *check.C) {
|
||||
// Not applicable as Windows does not support --net=host
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top")
|
||||
dockerCmd(c, "run", "-d", "--net=host", "--name=second", "busybox", "top")
|
||||
dockerCmd(c, "stop", "first")
|
||||
@@ -3407,7 +3420,7 @@ func (s *DockerSuite) TestTwoContainersInNetHost(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork")
|
||||
dockerCmd(c, "run", "-d", "--net=testnetwork", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
@@ -3418,7 +3431,7 @@ func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
|
||||
@@ -3441,7 +3454,7 @@ func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
|
||||
@@ -3473,7 +3486,7 @@ func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
// Run and connect containers to testnetwork1
|
||||
@@ -3495,7 +3508,7 @@ func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
// Create 2 networks using bridge driver
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
|
||||
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
|
||||
@@ -3531,7 +3544,7 @@ func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
// Run a container with --net=host
|
||||
dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
@@ -3547,7 +3560,7 @@ func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-d", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
// Run second container in first container's network namespace
|
||||
@@ -3568,7 +3581,7 @@ func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
dockerCmd(c, "run", "-d", "--net=none", "--name=first", "busybox", "top")
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
|
||||
|
||||
// Test recursive bind mount works by default
|
||||
func (s *DockerSuite) TestRunWithVolumesIsRecursive(c *check.C) {
|
||||
// /tmp gets permission denied
|
||||
testRequires(c, NotUserNamespace)
|
||||
tmpDir, err := ioutil.TempDir("", "docker_recursive_mount_test")
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
@@ -90,7 +92,7 @@ func (s *DockerSuite) TestRunWithVolumesIsRecursive(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRunDeviceDirectory(c *check.C) {
|
||||
testRequires(c, NativeExecDriver)
|
||||
testRequires(c, NativeExecDriver, NotUserNamespace)
|
||||
if _, err := os.Stat("/dev/snd"); err != nil {
|
||||
c.Skip("Host does not have /dev/snd")
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func (s *DockerSuite) TestTopNonPrivileged(c *check.C) {
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestTopPrivileged(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
out, _ := dockerCmd(c, "run", "--privileged", "-i", "-d", "busybox", "top")
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -16,10 +19,6 @@ var (
|
||||
// the private registry to use for tests
|
||||
privateRegistryURL = "127.0.0.1:5000"
|
||||
|
||||
dockerBasePath = "/var/lib/docker"
|
||||
volumesConfigPath = dockerBasePath + "/volumes"
|
||||
containerStoragePath = dockerBasePath + "/containers"
|
||||
|
||||
runtimePath = "/var/run/docker"
|
||||
execDriverPath = runtimePath + "/execdriver/native"
|
||||
|
||||
@@ -38,6 +37,13 @@ var (
|
||||
// daemonDefaultImage is the name of the default image to use when running
|
||||
// tests. This is platform dependent.
|
||||
daemonDefaultImage string
|
||||
|
||||
// For a local daemon on Linux, these values will be used for testing
|
||||
// user namespace support as the standard graph path(s) will be
|
||||
// appended with the root remapped uid.gid prefix
|
||||
dockerBasePath string
|
||||
volumesConfigPath string
|
||||
containerStoragePath string
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -50,6 +56,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
reexec.Init()
|
||||
if dockerBin := os.Getenv("DOCKER_BINARY"); dockerBin != "" {
|
||||
dockerBinary = dockerBin
|
||||
}
|
||||
@@ -85,4 +92,21 @@ func init() {
|
||||
} else {
|
||||
isLocalDaemon = true
|
||||
}
|
||||
|
||||
// This is only used for a tests with local daemon true (Linux-only today)
|
||||
// default is "/var/lib/docker", but we'll try and ask the
|
||||
// /info endpoint for the specific root dir
|
||||
dockerBasePath = "/var/lib/docker"
|
||||
type Info struct {
|
||||
DockerRootDir string
|
||||
}
|
||||
var i Info
|
||||
status, b, err := sockRequest("GET", "/info", nil)
|
||||
if err == nil && status == 200 {
|
||||
if err = json.Unmarshal(b, &i); err == nil {
|
||||
dockerBasePath = i.DockerRootDir
|
||||
}
|
||||
}
|
||||
volumesConfigPath = dockerBasePath + "/volumes"
|
||||
containerStoragePath = dockerBasePath + "/containers"
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ type Daemon struct {
|
||||
c *check.C
|
||||
logFile *os.File
|
||||
folder string
|
||||
root string
|
||||
stdin io.WriteCloser
|
||||
stdout, stderr io.ReadCloser
|
||||
cmd *exec.Cmd
|
||||
@@ -65,9 +66,10 @@ func NewDaemon(c *check.C) *Daemon {
|
||||
if err != nil {
|
||||
c.Fatalf("Could not make %q an absolute path: %v", dir, err)
|
||||
}
|
||||
daemonRoot := filepath.Join(daemonFolder, "root")
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(daemonFolder, "graph"), 0600); err != nil {
|
||||
c.Fatalf("Could not create %s/graph directory", daemonFolder)
|
||||
if err := os.MkdirAll(daemonRoot, 0755); err != nil {
|
||||
c.Fatalf("Could not create daemon root %q: %v", dir, err)
|
||||
}
|
||||
|
||||
userlandProxy := true
|
||||
@@ -82,6 +84,7 @@ func NewDaemon(c *check.C) *Daemon {
|
||||
id: id,
|
||||
c: c,
|
||||
folder: daemonFolder,
|
||||
root: daemonRoot,
|
||||
storageDriver: os.Getenv("DOCKER_GRAPHDRIVER"),
|
||||
execDriver: os.Getenv("DOCKER_EXECDRIVER"),
|
||||
userlandProxy: userlandProxy,
|
||||
@@ -99,11 +102,15 @@ func (d *Daemon) Start(arg ...string) error {
|
||||
args := append(d.GlobalFlags,
|
||||
d.Command,
|
||||
"--host", d.sock(),
|
||||
"--graph", fmt.Sprintf("%s/graph", d.folder),
|
||||
"--graph", d.root,
|
||||
"--pidfile", fmt.Sprintf("%s/docker.pid", d.folder),
|
||||
fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
|
||||
)
|
||||
|
||||
if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
|
||||
args = append(args, []string{"--userns-remap", root}...)
|
||||
}
|
||||
|
||||
// If we don't explicitly set the log-level or debug flag(-D) then
|
||||
// turn on debug mode
|
||||
foundIt := false
|
||||
@@ -181,8 +188,11 @@ func (d *Daemon) Start(arg ...string) error {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
d.c.Logf("[%s] received status != 200 OK: %s", d.id, resp.Status)
|
||||
}
|
||||
|
||||
d.c.Logf("[%s] daemon started", d.id)
|
||||
d.root, err = d.queryRootDir()
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] error querying daemon for root directory: %v", d.id, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -278,6 +288,47 @@ func (d *Daemon) Restart(arg ...string) error {
|
||||
return d.Start(arg...)
|
||||
}
|
||||
|
||||
func (d *Daemon) queryRootDir() (string, error) {
|
||||
// update daemon root by asking /info endpoint (to support user
|
||||
// namespaced daemon with root remapped uid.gid directory)
|
||||
conn, err := net.Dial("unix", filepath.Join(d.folder, "docker.sock"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
client := httputil.NewClientConn(conn, nil)
|
||||
|
||||
req, err := http.NewRequest("GET", "/info", nil)
|
||||
if err != nil {
|
||||
client.Close()
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
client.Close()
|
||||
return "", err
|
||||
}
|
||||
body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
|
||||
defer client.Close()
|
||||
return resp.Body.Close()
|
||||
})
|
||||
|
||||
type Info struct {
|
||||
DockerRootDir string
|
||||
}
|
||||
var b []byte
|
||||
var i Info
|
||||
b, err = readBody(body)
|
||||
if err == nil && resp.StatusCode == 200 {
|
||||
// read the docker root dir
|
||||
if err = json.Unmarshal(b, &i); err == nil {
|
||||
return i.DockerRootDir, nil
|
||||
}
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (d *Daemon) sock() string {
|
||||
return fmt.Sprintf("unix://%s/docker.sock", d.folder)
|
||||
}
|
||||
@@ -1236,7 +1287,7 @@ func readFile(src string, c *check.C) (content string) {
|
||||
}
|
||||
|
||||
func containerStorageFile(containerID, basename string) string {
|
||||
return filepath.Join("/var/lib/docker/containers", containerID, basename)
|
||||
return filepath.Join(containerStoragePath, containerID, basename)
|
||||
}
|
||||
|
||||
// docker commands that use this function must be run with the '-d' switch.
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -147,6 +148,16 @@ var (
|
||||
},
|
||||
"Test requires native Golang compiler instead of GCCGO",
|
||||
}
|
||||
NotUserNamespace = testRequirement{
|
||||
func() bool {
|
||||
root := os.Getenv("DOCKER_REMAP_ROOT")
|
||||
if root != "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
"Test cannot be run when remapping root",
|
||||
}
|
||||
)
|
||||
|
||||
// testRequires checks if the environment satisfies the requirements
|
||||
|
||||
Reference in New Issue
Block a user