// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume
func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "create", "-v", "/foo", "--name=one", "busybox")

	fooDir, err := inspectMountSourceField("one", "/foo")
	if err != nil {
		c.Fatal(err)
	}

	dockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox")

	bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}}
	status, _, err := sockRequest("POST", "/containers/two/start", bindSpec)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusNoContent)

	fooDir2, err := inspectMountSourceField("two", "/foo")
	if err != nil {
		c.Fatal(err)
	}

	if fooDir2 != fooDir {
		c.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2)
	}
}
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
	testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows
	git, err := fakeGIT("repo", map[string]string{
		"Dockerfile": `FROM busybox
RUN echo from Dockerfile`,
		"dockerfile": `FROM busybox
RUN echo from dockerfile`,
	}, false)
	if err != nil {
		c.Fatal(err)
	}
	defer git.Close()

	// Make sure it tries to 'dockerfile' query param value
	res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
	c.Assert(res.StatusCode, check.Equals, http.StatusOK)
	c.Assert(err, check.IsNil)

	buf, err := readBody(body)
	if err != nil {
		c.Fatal(err)
	}

	out := string(buf)
	if !strings.Contains(out, "from Dockerfile") {
		c.Fatalf("Incorrect output: %s", out)
	}
}
// TestRunSeccompProfileDenyChmod checks that 'docker run --security-opt seccomp=/tmp/profile.json busybox chmod 400 /etc/hostname' exits with operation not permitted.
func (s *DockerSuite) TestRunSeccompProfileDenyChmod(c *check.C) {
	testRequires(c, SameHostDaemon, seccompEnabled)
	jsonData := `{
	"defaultAction": "SCMP_ACT_ALLOW",
	"syscalls": [
		{
			"name": "chmod",
			"action": "SCMP_ACT_ERRNO"
		}
	]
}`
	tmpFile, err := ioutil.TempFile("", "profile.json")
	defer tmpFile.Close()
	if err != nil {
		c.Fatal(err)
	}

	if _, err := tmpFile.Write([]byte(jsonData)); err != nil {
		c.Fatal(err)
	}
	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp="+tmpFile.Name(), "busybox", "chmod", "400", "/etc/hostname")
	out, _, _ := runCommandWithOutput(runCmd)
	if !strings.Contains(out, "Operation not permitted") {
		c.Fatalf("expected chmod with seccomp profile denied to fail, got %s", out)
	}
}
// #6509
func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
	checkRedirect := func(command string) {
		_, tty, err := pty.Open()
		c.Assert(err, checker.IsNil, check.Commentf("Could not open pty"))
		cmd := exec.Command("sh", "-c", command)
		cmd.Stdin = tty
		cmd.Stdout = tty
		cmd.Stderr = tty
		c.Assert(cmd.Start(), checker.IsNil)
		ch := make(chan error)
		go func() {
			ch <- cmd.Wait()
			close(ch)
		}()

		select {
		case <-time.After(10 * time.Second):
			c.Fatal("command timeout")
		case err := <-ch:
			c.Assert(err, checker.IsNil, check.Commentf("wait err"))
		}
	}

	checkRedirect(dockerBinary + " run -i busybox cat /etc/passwd | grep -q root")
	checkRedirect(dockerBinary + " run busybox cat /etc/passwd | grep -q root")
}
func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
	testRequires(c, DaemonIsLinux)
	config := map[string]interface{}{
		"Image": "busybox",
	}

	create := func(ct string) (*http.Response, io.ReadCloser, error) {
		jsonData := bytes.NewBuffer(nil)
		if err := json.NewEncoder(jsonData).Encode(config); err != nil {
			c.Fatal(err)
		}
		return sockRequestRaw("POST", "/containers/create", jsonData, ct)
	}

	// Try with no content-type
	res, body, err := create("")
	c.Assert(err, check.IsNil)
	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
	body.Close()

	// Try with wrong content-type
	res, body, err = create("application/xml")
	c.Assert(err, check.IsNil)
	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
	body.Close()

	// now application/json
	res, body, err = create("application/json")
	c.Assert(err, check.IsNil)
	c.Assert(res.StatusCode, check.Equals, http.StatusCreated)
	body.Close()
}
func UtilCreateNetworkMode(c *check.C, networkMode string) {
	config := map[string]interface{}{
		"Image":      "busybox",
		"HostConfig": map[string]interface{}{"NetworkMode": networkMode},
	}

	status, body, err := sockRequest("POST", "/containers/create", config)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusCreated)

	var container types.ContainerCreateResponse
	if err := json.Unmarshal(body, &container); err != nil {
		c.Fatal(err)
	}

	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusOK)

	var containerJSON types.ContainerJSON
	if err := json.Unmarshal(body, &containerJSON); err != nil {
		c.Fatal(err)
	}

	if containerJSON.HostConfig.NetworkMode != runconfig.NetworkMode(networkMode) {
		c.Fatalf("Mismatched NetworkMode, Expected %s, Actual: %s ", networkMode, containerJSON.HostConfig.NetworkMode)
	}
}
func (s *DockerSuite) TestContainerApiCommit(c *check.C) {
	testRequires(c, DaemonIsLinux)
	cName := "testapicommit"
	dockerCmd(c, "run", "--name="+cName, "busybox", "/bin/sh", "-c", "touch /test")

	name := "TestContainerApiCommit"
	status, b, err := sockRequest("POST", "/commit?repo="+name+"&testtag=tag&container="+cName, nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusCreated)

	type resp struct {
		ID string
	}
	var img resp
	if err := json.Unmarshal(b, &img); err != nil {
		c.Fatal(err)
	}

	cmd, err := inspectField(img.ID, "Config.Cmd")
	if err != nil {
		c.Fatal(err)
	}
	if cmd != "{[/bin/sh -c touch /test]}" {
		c.Fatalf("got wrong Cmd from commit: %q", cmd)
	}
	// sanity check, make sure the image is what we think it is
	dockerCmd(c, "run", img.ID, "ls", "/test")
}
func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) {
	testRequires(c, DaemonIsLinux)
	name := "testing"
	config := map[string]interface{}{
		"Image":   "busybox",
		"Volumes": map[string]struct{}{"/tmp": {}},
	}

	status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusCreated)

	bindPath := randomTmpDirPath("test", daemonPlatform)
	config = map[string]interface{}{
		"Binds": []string{bindPath + ":/tmp"},
	}
	status, _, err = sockRequest("POST", "/containers/"+name+"/start", config)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusNoContent)

	pth, err := inspectMountSourceField(name, "/tmp")
	if err != nil {
		c.Fatal(err)
	}

	if pth != bindPath {
		c.Fatalf("expected volume host path to be %s, got %s", bindPath, pth)
	}
}
func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
	// TODO Windows CI: Requires some extra work. Consider copying the
	// runSleepingContainer helper to have an exec version.
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "-d", "--name", "testing", "busybox", "top")

	err := exec.Command(dockerBinary, "exec", "testing", "top").Start()
	c.Assert(err, checker.IsNil)

	type dstop struct {
		out []byte
		err error
	}

	ch := make(chan dstop)
	go func() {
		out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput()
		ch <- dstop{out, err}
		close(ch)
	}()
	select {
	case <-time.After(3 * time.Second):
		c.Fatal("Container stop timed out")
	case s := <-ch:
		c.Assert(s.err, check.IsNil)
	}
}
func (s *DockerSuite) TestExecTTYWithoutStdin(c *check.C) {
	out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
	id := strings.TrimSpace(out)
	c.Assert(waitRun(id), checker.IsNil)

	errChan := make(chan error)
	go func() {
		defer close(errChan)

		cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true")
		if _, err := cmd.StdinPipe(); err != nil {
			errChan <- err
			return
		}

		expected := "the input device is not a TTY"
		if runtime.GOOS == "windows" {
			expected += ".  If you are using mintty, try prefixing the command with 'winpty'"
		}
		if out, _, err := runCommandWithOutput(cmd); err == nil {
			errChan <- fmt.Errorf("exec should have failed")
			return
		} else if !strings.Contains(out, expected) {
			errChan <- fmt.Errorf("exec failed with error %q: expected %q", out, expected)
			return
		}
	}()

	select {
	case err := <-errChan:
		c.Assert(err, check.IsNil)
	case <-time.After(3 * time.Second):
		c.Fatal("exec is running but should have failed")
	}
}
func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
	var (
		expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
		result   []string
	)
	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
	links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
	if err != nil {
		c.Fatal(err)
	}

	err = unmarshalJSON([]byte(links), &result)
	if err != nil {
		c.Fatal(err)
	}

	output := convertSliceOfStringsToMap(result)

	equal := reflect.DeepEqual(output, expected)

	if !equal {
		c.Fatalf("Links %s, but expected %s", result, expected)
	}

}
func (s *DockerSuite) TestPluginBasicOps(c *check.C) {
	testRequires(c, DaemonIsLinux, ExperimentalDaemon)
	_, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", pNameWithTag)
	c.Assert(err, checker.IsNil)

	out, _, err := dockerCmdWithError("plugin", "ls")
	c.Assert(err, checker.IsNil)
	c.Assert(out, checker.Contains, pName)
	c.Assert(out, checker.Contains, pTag)
	c.Assert(out, checker.Contains, "true")

	id, _, err := dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", pNameWithTag)
	c.Assert(err, checker.IsNil)

	out, _, err = dockerCmdWithError("plugin", "remove", pNameWithTag)
	c.Assert(out, checker.Contains, "is enabled")

	_, _, err = dockerCmdWithError("plugin", "disable", pNameWithTag)
	c.Assert(err, checker.IsNil)

	out, _, err = dockerCmdWithError("plugin", "remove", pNameWithTag)
	c.Assert(err, checker.IsNil)
	c.Assert(out, checker.Contains, pNameWithTag)

	_, err = os.Stat(filepath.Join(dockerBasePath, "plugins", id))
	if !os.IsNotExist(err) {
		c.Fatal(err)
	}
}
func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
	config := map[string]interface{}{
		"Image": "busybox",
		"Cmd":   []string{"/bin/sh", "-c", "touch /test && ls /test"},
	}

	status, b, err := sockRequest("POST", "/containers/create", config)
	c.Assert(status, check.Equals, http.StatusCreated)
	c.Assert(err, check.IsNil)

	type createResp struct {
		Id string
	}
	var container createResp
	if err := json.Unmarshal(b, &container); err != nil {
		c.Fatal(err)
	}

	out, err := exec.Command(dockerBinary, "start", "-a", container.Id).CombinedOutput()
	if err != nil {
		c.Fatal(out, err)
	}
	if strings.TrimSpace(string(out)) != "/test" {
		c.Fatalf("expected output `/test`, got %q", out)
	}
}
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) {
	name := "exportcontainer"
	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test")
	out, _, err := runCommandWithOutput(runCmd)
	if err != nil {
		c.Fatalf("Error on container creation: %v, output: %q", err, out)
	}

	status, body, err := sockRequest("GET", "/containers/"+name+"/export", nil)
	c.Assert(status, check.Equals, http.StatusOK)
	c.Assert(err, check.IsNil)

	found := false
	for tarReader := tar.NewReader(bytes.NewReader(body)); ; {
		h, err := tarReader.Next()
		if err != nil {
			if err == io.EOF {
				break
			}
			c.Fatal(err)
		}
		if h.Name == "test" {
			found = true
			break
		}
	}

	if !found {
		c.Fatalf("The created test file has not been found in the exported image")
	}
}
func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
	// Test to make sure we stop people from trying to leave the
	// build context when specifying a symlink as the path to the dockerfile
	buffer := new(bytes.Buffer)
	tw := tar.NewWriter(buffer)
	defer tw.Close()

	if err := tw.WriteHeader(&tar.Header{
		Name:     "Dockerfile",
		Typeflag: tar.TypeSymlink,
		Linkname: "/etc/passwd",
	}); err != nil {
		c.Fatalf("failed to write tar file header: %v", err)
	}
	if err := tw.Close(); err != nil {
		c.Fatalf("failed to close tar archive: %v", err)
	}

	res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
	c.Assert(err, check.IsNil)

	out, err := readBody(body)
	if err != nil {
		c.Fatal(err)
	}

	// The reason the error is "Cannot locate specified Dockerfile" is because
	// in the builder, the symlink is resolved within the context, therefore
	// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
	// a nonexistent file.
	if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
		c.Fatalf("Didn't complain about leaving build context: %s", out)
	}
}
func (s *DockerSuite) TestContainerApiDeleteRemoveLinks(c *check.C) {
	testRequires(c, DaemonIsLinux)
	out, _ := dockerCmd(c, "run", "-d", "--name", "tlink1", "busybox", "top")

	id := strings.TrimSpace(out)
	c.Assert(waitRun(id), check.IsNil)

	out, _ = dockerCmd(c, "run", "--link", "tlink1:tlink1", "--name", "tlink2", "-d", "busybox", "top")

	id2 := strings.TrimSpace(out)
	c.Assert(waitRun(id2), check.IsNil)

	links, err := inspectFieldJSON(id2, "HostConfig.Links")
	c.Assert(err, check.IsNil)

	if links != "[\"/tlink1:/tlink2/tlink1\"]" {
		c.Fatal("expected to have links between containers")
	}

	status, _, err := sockRequest("DELETE", "/containers/tlink2/tlink1?link=1", nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusNoContent)

	linksPostRm, err := inspectFieldJSON(id2, "HostConfig.Links")
	c.Assert(err, check.IsNil)

	if linksPostRm != "null" {
		c.Fatal("call to api deleteContainer links should have removed the specified links")
	}
}
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) {
	testRequires(c, DaemonIsLinux)
	name := "exportcontainer"
	dockerCmd(c, "run", "--name", name, "busybox", "touch", "/test")

	status, body, err := sockRequest("GET", "/containers/"+name+"/export", nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusOK)

	found := false
	for tarReader := tar.NewReader(bytes.NewReader(body)); ; {
		h, err := tarReader.Next()
		if err != nil {
			if err == io.EOF {
				break
			}
			c.Fatal(err)
		}
		if h.Name == "test" {
			found = true
			break
		}
	}

	if !found {
		c.Fatalf("The created test file has not been found in the exported image")
	}
}
func (s *DockerSuite) TestExecInteractive(c *check.C) {
	testRequires(c, DaemonIsLinux)
	dockerCmd(c, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && top")

	execCmd := exec.Command(dockerBinary, "exec", "-i", "testing", "sh")
	stdin, err := execCmd.StdinPipe()
	c.Assert(err, checker.IsNil)
	stdout, err := execCmd.StdoutPipe()
	c.Assert(err, checker.IsNil)

	err = execCmd.Start()
	c.Assert(err, checker.IsNil)
	_, err = stdin.Write([]byte("cat /tmp/file\n"))
	c.Assert(err, checker.IsNil)

	r := bufio.NewReader(stdout)
	line, err := r.ReadString('\n')
	c.Assert(err, checker.IsNil)
	line = strings.TrimSpace(line)
	c.Assert(line, checker.Equals, "test")
	err = stdin.Close()
	c.Assert(err, checker.IsNil)
	errChan := make(chan error)
	go func() {
		errChan <- execCmd.Wait()
		close(errChan)
	}()
	select {
	case err := <-errChan:
		c.Assert(err, checker.IsNil)
	case <-time.After(1 * time.Second):
		c.Fatal("docker exec failed to exit on stdin close")
	}

}
func (s *DockerSuite) TestCreateByImageID(c *check.C) {
	imageName := "testcreatebyimageid"
	imageID, err := buildImage(imageName,
		`FROM busybox
		MAINTAINER dockerio`,
		true)
	if err != nil {
		c.Fatal(err)
	}
	truncatedImageID := stringid.TruncateID(imageID)

	dockerCmd(c, "create", imageID)
	dockerCmd(c, "create", truncatedImageID)
	dockerCmd(c, "create", fmt.Sprintf("%s:%s", imageName, truncatedImageID))

	// Ensure this fails
	out, exit, _ := dockerCmdWithError("create", fmt.Sprintf("%s:%s", imageName, imageID))
	if exit == 0 {
		c.Fatalf("expected non-zero exit code; received %d", exit)
	}

	if expected := "Error parsing reference"; !strings.Contains(out, expected) {
		c.Fatalf(`Expected %q in output; got: %s`, expected, out)
	}

	out, exit, _ = dockerCmdWithError("create", fmt.Sprintf("%s:%s", "wrongimage", truncatedImageID))
	if exit == 0 {
		c.Fatalf("expected non-zero exit code; received %d", exit)
	}

	if expected := "Unable to find image"; !strings.Contains(out, expected) {
		c.Fatalf(`Expected %q in output; got: %s`, expected, out)
	}
}
Beispiel #20
0
func (s *DockerSuite) TestExecTtyWithoutStdin(c *check.C) {
	out, _ := dockerCmd(c, "run", "-d", "-ti", "busybox")
	id := strings.TrimSpace(out)
	if err := waitRun(id); err != nil {
		c.Fatal(err)
	}

	errChan := make(chan error)
	go func() {
		defer close(errChan)

		cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true")
		if _, err := cmd.StdinPipe(); err != nil {
			errChan <- err
			return
		}

		expected := "cannot enable tty mode"
		if out, _, err := runCommandWithOutput(cmd); err == nil {
			errChan <- fmt.Errorf("exec should have failed")
			return
		} else if !strings.Contains(out, expected) {
			errChan <- fmt.Errorf("exec failed with error %q: expected %q", out, expected)
			return
		}
	}()

	select {
	case err := <-errChan:
		c.Assert(err, check.IsNil)
	case <-time.After(3 * time.Second):
		c.Fatal("exec is running but should have failed")
	}
}
func (s *DockerSuite) TestContainerApiCreateWithDomainName(c *check.C) {
	testRequires(c, DaemonIsLinux)
	domainName := "test-domain"
	config := map[string]interface{}{
		"Image":      "busybox",
		"Domainname": domainName,
	}

	status, body, err := sockRequest("POST", "/containers/create", config)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusCreated)

	var container types.ContainerCreateResponse
	if err := json.Unmarshal(body, &container); err != nil {
		c.Fatal(err)
	}

	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusOK)

	var containerJSON types.ContainerJSON
	if err := json.Unmarshal(body, &containerJSON); err != nil {
		c.Fatal(err)
	}

	if containerJSON.Config.Domainname != domainName {
		c.Fatalf("Mismatched Domainname, Expected %s, Actual: %s ", domainName, containerJSON.Config.Domainname)
	}
}
Beispiel #22
0
func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
	dockerCmd(c, "run", "-d", "--name", "testing", "busybox", "top")

	if err := exec.Command(dockerBinary, "exec", "testing", "top").Start(); err != nil {
		c.Fatal(err)
	}

	type dstop struct {
		out []byte
		err error
	}

	ch := make(chan dstop)
	go func() {
		out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput()
		ch <- dstop{out, err}
		close(ch)
	}()
	select {
	case <-time.After(3 * time.Second):
		c.Fatal("Container stop timed out")
	case s := <-ch:
		c.Assert(s.err, check.IsNil)
	}
}
func (s *DockerSuite) TestContainerApiCreateWithCpuSharesCpuset(c *check.C) {
	testRequires(c, DaemonIsLinux)
	config := map[string]interface{}{
		"Image":      "busybox",
		"CpuShares":  512,
		"CpusetCpus": "0,1",
	}

	status, body, err := sockRequest("POST", "/containers/create", config)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusCreated)

	var container types.ContainerCreateResponse
	if err := json.Unmarshal(body, &container); err != nil {
		c.Fatal(err)
	}

	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusOK)

	var containerJSON types.ContainerJSON

	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)

	out, err := inspectField(containerJSON.ID, "HostConfig.CpuShares")
	c.Assert(err, check.IsNil)
	c.Assert(out, check.Equals, "512")

	outCpuset, errCpuset := inspectField(containerJSON.ID, "HostConfig.CpusetCpus")
	c.Assert(errCpuset, check.IsNil, check.Commentf("Output: %s", outCpuset))
	c.Assert(outCpuset, check.Equals, "0,1")
}
func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) {
	testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, NotGCCGO)

	errChan := make(chan error)
	go func() {
		defer close(errChan)
		out, exitCode, _ := dockerCmdWithError("run", "--name", "oomFalse", "-m", "10MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done")
		if expected := 137; exitCode != expected {
			errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out)
		}
	}()
	select {
	case err := <-errChan:
		c.Assert(err, checker.IsNil)
	case <-time.After(30 * time.Second):
		c.Fatal("Timeout waiting for container to die on OOM")
	}

	out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=oomFalse", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
	events := strings.Split(strings.TrimSuffix(out, "\n"), "\n")
	nEvents := len(events)

	c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event
	c.Assert(parseEventAction(c, events[nEvents-5]), checker.Equals, "create")
	c.Assert(parseEventAction(c, events[nEvents-4]), checker.Equals, "attach")
	c.Assert(parseEventAction(c, events[nEvents-3]), checker.Equals, "start")
	c.Assert(parseEventAction(c, events[nEvents-2]), checker.Equals, "oom")
	c.Assert(parseEventAction(c, events[nEvents-1]), checker.Equals, "die")
}
// Issue 7941 - test to make sure a "null" in JSON is just ignored.
// W/o this fix a null in JSON would be parsed into a string var as "null"
func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
	testRequires(c, DaemonIsLinux)
	config := `{
		"Hostname":"",
		"Domainname":"",
		"Memory":0,
		"MemorySwap":0,
		"CpuShares":0,
		"Cpuset":null,
		"AttachStdin":true,
		"AttachStdout":true,
		"AttachStderr":true,
		"ExposedPorts":{},
		"Tty":true,
		"OpenStdin":true,
		"StdinOnce":true,
		"Env":[],
		"Cmd":"ls",
		"Image":"busybox",
		"Volumes":{},
		"WorkingDir":"",
		"Entrypoint":null,
		"NetworkDisabled":false,
		"OnBuild":null}`

	res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
	c.Assert(err, check.IsNil)
	c.Assert(res.StatusCode, check.Equals, http.StatusCreated)

	b, err := readBody(body)
	if err != nil {
		c.Fatal(err)
	}
	type createResp struct {
		ID string
	}
	var container createResp
	if err := json.Unmarshal(b, &container); err != nil {
		c.Fatal(err)
	}

	out, err := inspectField(container.ID, "HostConfig.CpusetCpus")
	if err != nil {
		c.Fatal(err, out)
	}
	if out != "" {
		c.Fatalf("expected empty string, got %q", out)
	}

	outMemory, errMemory := inspectField(container.ID, "HostConfig.Memory")
	c.Assert(outMemory, check.Equals, "0")
	if errMemory != nil {
		c.Fatal(errMemory, outMemory)
	}
	outMemorySwap, errMemorySwap := inspectField(container.ID, "HostConfig.MemorySwap")
	c.Assert(outMemorySwap, check.Equals, "0")
	if errMemorySwap != nil {
		c.Fatal(errMemorySwap, outMemorySwap)
	}
}
// TestV2Only ensures that a daemon in v2-only mode does not
// attempt to contact any v1 registry endpoints.
func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
	reg, err := newTestRegistry(c)
	c.Assert(err, check.IsNil)

	reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(404)
	})

	reg.registerHandler("/v1/.*", func(w http.ResponseWriter, r *http.Request) {
		c.Fatal("V1 registry contacted")
	})

	repoName := fmt.Sprintf("%s/busybox", reg.hostport)

	err = s.d.Start("--insecure-registry", reg.hostport, "--disable-legacy-registry=true")
	c.Assert(err, check.IsNil)

	dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
	c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
	defer cleanup()

	s.d.Cmd("build", "--file", dockerfileName, ".")

	s.d.Cmd("run", repoName)
	s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "*****@*****.**", reg.hostport)
	s.d.Cmd("tag", "busybox", repoName)
	s.d.Cmd("push", repoName)
	s.d.Cmd("pull", repoName)
}
// TestRunSeccompProfileDenyUnshare checks that 'docker run --security-opt seccomp=/tmp/profile.json debian:jessie unshare' exits with operation not permitted.
func (s *DockerSuite) TestRunSeccompProfileDenyUnshare(c *check.C) {
	testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor)
	jsonData := `{
	"defaultAction": "SCMP_ACT_ALLOW",
	"syscalls": [
		{
			"name": "unshare",
			"action": "SCMP_ACT_ERRNO"
		}
	]
}`
	tmpFile, err := ioutil.TempFile("", "profile.json")
	defer tmpFile.Close()
	if err != nil {
		c.Fatal(err)
	}

	if _, err := tmpFile.Write([]byte(jsonData)); err != nil {
		c.Fatal(err)
	}
	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc")
	out, _, _ := runCommandWithOutput(runCmd)
	if !strings.Contains(out, "Operation not permitted") {
		c.Fatalf("expected unshare with seccomp profile denied to fail, got %s", out)
	}
}
func (s *DockerSuite) TestContainerApiCopy(c *check.C) {
	testRequires(c, DaemonIsLinux)
	name := "test-container-api-copy"
	dockerCmd(c, "run", "--name", name, "busybox", "touch", "/test.txt")

	postData := types.CopyConfig{
		Resource: "/test.txt",
	}

	status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
	c.Assert(err, check.IsNil)
	c.Assert(status, check.Equals, http.StatusOK)

	found := false
	for tarReader := tar.NewReader(bytes.NewReader(body)); ; {
		h, err := tarReader.Next()
		if err != nil {
			if err == io.EOF {
				break
			}
			c.Fatal(err)
		}
		if h.Name == "test.txt" {
			found = true
			break
		}
	}
	c.Assert(found, check.Equals, true)
}
// TestRunSeccompProfileDenyUnshareUserns checks that 'docker run debian:jessie unshare --map-root-user --user sh -c whoami' with a specific profile to
// deny unhare of a userns exits with operation not permitted.
func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
	testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor)
	// from sched.h
	jsonData := fmt.Sprintf(`{
	"defaultAction": "SCMP_ACT_ALLOW",
	"syscalls": [
		{
			"name": "unshare",
			"action": "SCMP_ACT_ERRNO",
			"args": [
				{
					"index": 0,
					"value": %d,
					"op": "SCMP_CMP_EQ"
				}
			]
		}
	]
}`, uint64(0x10000000))
	tmpFile, err := ioutil.TempFile("", "profile.json")
	defer tmpFile.Close()
	if err != nil {
		c.Fatal(err)
	}

	if _, err := tmpFile.Write([]byte(jsonData)); err != nil {
		c.Fatal(err)
	}
	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), "debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami")
	out, _, _ := runCommandWithOutput(runCmd)
	if !strings.Contains(out, "Operation not permitted") {
		c.Fatalf("expected unshare userns with seccomp profile denied to fail, got %s", out)
	}
}
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
	server, err := fakeStorage(map[string]string{
		"testD": `FROM busybox
COPY * /tmp/
RUN find / -name ba*
RUN find /tmp/`,
	})
	if err != nil {
		c.Fatal(err)
	}
	defer server.Close()

	res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
	c.Assert(res.StatusCode, check.Equals, http.StatusOK)
	c.Assert(err, check.IsNil)

	buf, err := readBody(body)
	if err != nil {
		c.Fatal(err)
	}

	// Make sure Dockerfile exists.
	// Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL
	out := string(buf)
	if !strings.Contains(out, "/tmp/Dockerfile") ||
		strings.Contains(out, "baz") {
		c.Fatalf("Incorrect output: %s", out)
	}
}