func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) { testRequires(c, NotUserNamespace) var testD string if daemonPlatform == "windows" { testD = `FROM busybox COPY * /tmp/ RUN find / -name ba* RUN find /tmp/` } else { // -xdev is required because sysfs can cause EPERM testD = `FROM busybox COPY * /tmp/ RUN find / -xdev -name ba* RUN find /tmp/` } server, err := fakeStorage(map[string]string{"testD": testD}) c.Assert(err, checker.IsNil) defer server.Close() res, body, err := request.SockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json", daemonHost()) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusOK) buf, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) // Make sure Dockerfile exists. // Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL out := string(buf) c.Assert(out, checker.Contains, "/tmp/Dockerfile") c.Assert(out, checker.Not(checker.Contains), "baz") }
// #20638 func (s *DockerSuite) TestExecAPIStartWithDetach(c *check.C) { name := "foo" runSleepingContainer(c, "-d", "-t", "--name", name) data := map[string]interface{}{ "cmd": []string{"true"}, "AttachStdin": true, } _, b, err := request.SockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), data, daemonHost()) c.Assert(err, checker.IsNil, check.Commentf(string(b))) createResp := struct { ID string `json:"Id"` }{} c.Assert(json.Unmarshal(b, &createResp), checker.IsNil, check.Commentf(string(b))) _, body, err := request.SockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", createResp.ID), strings.NewReader(`{"Detach": true}`), "application/json", daemonHost()) c.Assert(err, checker.IsNil) b, err = testutil.ReadBody(body) comment := check.Commentf("response body: %s", b) c.Assert(err, checker.IsNil, comment) resp, _, err := request.SockRequestRaw("GET", "/_ping", nil, "", daemonHost()) c.Assert(err, checker.IsNil) if resp.StatusCode != http.StatusOK { c.Fatal("daemon is down, it should alive") } }
func (s *DockerSuite) TestAPIErrorNotFoundPlainText(c *check.C) { httpResp, body, err := sockRequestRaw("GET", "/v1.23/notfound", nil, "application/json") c.Assert(err, checker.IsNil) c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound) c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain") b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) c.Assert(strings.TrimSpace(string(b)), checker.Equals, "page not found") }
func (s *DockerSuite) TestAPIErrorJSON(c *check.C) { httpResp, body, err := request.Post(daemonHost(), "/containers/create", request.JSONBody(struct{}{})) c.Assert(err, checker.IsNil) c.Assert(httpResp.StatusCode, checker.Equals, http.StatusInternalServerError) c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json") b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) c.Assert(getErrorMessage(c, b), checker.Equals, "Config cannot be empty in order to create a container") }
func (s *DockerSuite) TestAPIErrorNotFoundPlainText(c *check.C) { httpResp, body, err := request.Get(daemonHost(), "/v1.23/notfound", request.JSON) c.Assert(err, checker.IsNil) c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound) c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain") b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) c.Assert(strings.TrimSpace(string(b)), checker.Equals, "page not found") }
func (s *DockerSuite) TestAPIErrorJSON(c *check.C) { httpResp, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(`{}`), "application/json") c.Assert(err, checker.IsNil) c.Assert(httpResp.StatusCode, checker.Equals, http.StatusInternalServerError) c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json") b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) c.Assert(getErrorMessage(c, b), checker.Equals, "Config cannot be empty in order to create a container") }
func startExec(c *check.C, id string, code int) { resp, body, err := request.SockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "application/json", daemonHost()) c.Assert(err, checker.IsNil) b, err := testutil.ReadBody(body) comment := check.Commentf("response body: %s", b) c.Assert(err, checker.IsNil, comment) c.Assert(resp.StatusCode, checker.Equals, code, comment) }
func (s *DockerSuite) TestBuildAPIUnnormalizedTarPaths(c *check.C) { // Make sure that build context tars with entries of the form // x/./y don't cause caching false positives. buildFromTarContext := func(fileContents []byte) string { buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() dockerfile := []byte(`FROM busybox COPY dir /dir/`) err := tw.WriteHeader(&tar.Header{ Name: "Dockerfile", Size: int64(len(dockerfile)), }) //failed to write tar file header c.Assert(err, checker.IsNil) _, err = tw.Write(dockerfile) // failed to write Dockerfile in tar file content c.Assert(err, checker.IsNil) err = tw.WriteHeader(&tar.Header{ Name: "dir/./file", Size: int64(len(fileContents)), }) //failed to write tar file header c.Assert(err, checker.IsNil) _, err = tw.Write(fileContents) // failed to write file contents in tar file content c.Assert(err, checker.IsNil) // failed to close tar archive c.Assert(tw.Close(), checker.IsNil) res, body, err := request.SockRequestRaw("POST", "/build", buffer, "application/x-tar", daemonHost()) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusOK) out, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) lines := strings.Split(string(out), "\n") c.Assert(len(lines), checker.GreaterThan, 1) c.Assert(lines[len(lines)-2], checker.Matches, ".*Successfully built [0-9a-f]{12}.*") re := regexp.MustCompile("Successfully built ([0-9a-f]{12})") matches := re.FindStringSubmatch(lines[len(lines)-2]) return matches[1] } imageA := buildFromTarContext([]byte("abc")) imageB := buildFromTarContext([]byte("def")) c.Assert(imageA, checker.Not(checker.Equals), imageB) }
func (s *DockerSuite) TestAPIErrorNotFoundJSON(c *check.C) { // 404 is a different code path to normal errors, so test separately httpResp, body, err := request.Get(daemonHost(), "/notfound", request.JSON) c.Assert(err, checker.IsNil) c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound) c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json") b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) c.Assert(getErrorMessage(c, b), checker.Equals, "page not found") }
func (s *DockerSuite) TestBuildAPIRemoteTarballContextWithCustomDockerfile(c *check.C) { buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() dockerfile := []byte(`FROM busybox RUN echo 'wrong'`) err := tw.WriteHeader(&tar.Header{ Name: "Dockerfile", Size: int64(len(dockerfile)), }) // failed to write tar file header c.Assert(err, checker.IsNil) _, err = tw.Write(dockerfile) // failed to write tar file content c.Assert(err, checker.IsNil) custom := []byte(`FROM busybox RUN echo 'right' `) err = tw.WriteHeader(&tar.Header{ Name: "custom", Size: int64(len(custom)), }) // failed to write tar file header c.Assert(err, checker.IsNil) _, err = tw.Write(custom) // failed to write tar file content c.Assert(err, checker.IsNil) // failed to close tar archive c.Assert(tw.Close(), checker.IsNil) server, err := fakeBinaryStorage(map[string]*bytes.Buffer{ "testT.tar": buffer, }) c.Assert(err, checker.IsNil) defer server.Close() url := "/build?dockerfile=custom&remote=" + server.URL() + "/testT.tar" res, body, err := request.SockRequestRaw("POST", url, nil, "application/tar", daemonHost()) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusOK) defer body.Close() content, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) // Build used the wrong dockerfile. c.Assert(string(content), checker.Not(checker.Contains), "wrong") }
func (s *DockerSuite) TestAPIErrorPlainText(c *check.C) { // Windows requires API 1.25 or later. This test is validating a behaviour which was present // in v1.23, but changed in 1.24, hence not applicable on Windows. See apiVersionSupportsJSONErrors testRequires(c, DaemonIsLinux) httpResp, body, err := request.Post(daemonHost(), "/v1.23/containers/create", request.JSONBody(struct{}{})) c.Assert(err, checker.IsNil) c.Assert(httpResp.StatusCode, checker.Equals, http.StatusInternalServerError) c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain") b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) c.Assert(strings.TrimSpace(string(b)), checker.Equals, "Config cannot be empty in order to create a container") }
// regression gh14320 func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) { client, err := request.NewClient(daemonHost()) c.Assert(err, checker.IsNil) req, err := request.New(daemonHost(), "/containers/doesnotexist/attach", request.Method(http.MethodPost)) resp, err := client.Do(req) // connection will shutdown, err should be "persistent connection closed" c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) content, err := testutil.ReadBody(resp.Body) c.Assert(err, checker.IsNil) expected := "No such container: doesnotexist\r\n" c.Assert(string(content), checker.Equals, expected) }
// SockRequest create a request against the specified host (with method, endpoint and other request modifier) and // returns the status code, and the content as an byte slice // Deprecated: use request.Do instead func SockRequest(method, endpoint string, data interface{}, daemon string, modifiers ...func(*http.Request)) (int, []byte, error) { jsonData := bytes.NewBuffer(nil) if err := json.NewEncoder(jsonData).Encode(data); err != nil { return -1, nil, err } res, body, err := SockRequestRaw(method, endpoint, jsonData, "application/json", daemon, modifiers...) if err != nil { return -1, nil, err } b, err := testutil.ReadBody(body) return res.StatusCode, b, err }
// SockRequest executes a socket request on a daemon and returns statuscode and output. func (d *Daemon) SockRequest(method, endpoint string, data interface{}) (int, []byte, error) { jsonData := bytes.NewBuffer(nil) if err := json.NewEncoder(jsonData).Encode(data); err != nil { return -1, nil, err } res, body, err := d.SockRequestRaw(method, endpoint, jsonData, "application/json") if err != nil { return -1, nil, err } b, err := testutil.ReadBody(body) return res.StatusCode, b, err }
func (s *DockerSuite) TestExecAPIStartBackwardsCompatible(c *check.C) { testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later runSleepingContainer(c, "-d", "--name", "test") id := createExec(c, "test") resp, body, err := request.SockRequestRaw("POST", fmt.Sprintf("/v1.20/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "text/plain", daemonHost()) c.Assert(err, checker.IsNil) b, err := testutil.ReadBody(body) comment := check.Commentf("response body: %s", b) c.Assert(err, checker.IsNil, comment) c.Assert(resp.StatusCode, checker.Equals, http.StatusOK, comment) }
// regression gh14320 func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) { req, client, err := newRequestClient("POST", "/containers/doesnotexist/attach", nil, "", "") c.Assert(err, checker.IsNil) resp, err := client.Do(req) // connection will shutdown, err should be "persistent connection closed" c.Assert(err, checker.NotNil) // Server shutdown connection body, err := testutil.ReadBody(resp.Body) c.Assert(err, checker.IsNil) c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) expected := "No such container: doesnotexist\r\n" c.Assert(string(body), checker.Equals, expected) }
func (s *DockerSuite) TestBuildAPILowerDockerfile(c *check.C) { git, err := newFakeGit("repo", map[string]string{ "dockerfile": `FROM busybox RUN echo from dockerfile`, }, false) c.Assert(err, checker.IsNil) defer git.Close() res, body, err := request.SockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json", daemonHost()) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusOK) buf, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) out := string(buf) c.Assert(out, checker.Contains, "from dockerfile") }
func (s *DockerSuite) TestDeprecatedStartWithTooLowMemoryLimit(c *check.C) { // TODO Windows: Port once memory is supported testRequires(c, DaemonIsLinux) out, _ := dockerCmd(c, "create", "busybox") containerID := strings.TrimSpace(out) config := `{ "CpuShares": 100, "Memory": 524287 }` res, body, err := request.SockRequestRaw("POST", formatV123StartAPIURL("/containers/"+containerID+"/start"), strings.NewReader(config), "application/json", daemonHost()) c.Assert(err, checker.IsNil) b, err2 := testutil.ReadBody(body) c.Assert(err2, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) c.Assert(string(b), checker.Contains, "Minimum memory limit allowed is 4MB") }
func (s *DockerSuite) TestExecAPICreateNoValidContentType(c *check.C) { name := "exec_test" dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh") jsonData := bytes.NewBuffer(nil) if err := json.NewEncoder(jsonData).Encode(map[string]interface{}{"Cmd": nil}); err != nil { c.Fatalf("Can not encode data to json %s", err) } res, body, err := request.SockRequestRaw("POST", fmt.Sprintf("/containers/%s/exec", name), jsonData, "text/plain", daemonHost()) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) b, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) comment := check.Commentf("Expected message when creating exec command with invalid Content-Type specified") c.Assert(getErrorMessage(c, b), checker.Contains, "Content-Type specified", comment) }
func (d *Daemon) queryRootDir() (string, error) { // update daemon root by asking /info endpoint (to support user // namespaced daemon with root remapped uid.gid directory) clientConfig, err := d.getClientConfig() if err != nil { return "", err } client := &http.Client{ Transport: clientConfig.transport, } req, err := http.NewRequest("GET", "/info", nil) if err != nil { return "", err } req.Header.Set("Content-Type", "application/json") req.URL.Host = clientConfig.addr req.URL.Scheme = clientConfig.scheme resp, err := client.Do(req) if err != nil { return "", err } body := ioutils.NewReadCloserWrapper(resp.Body, func() error { return resp.Body.Close() }) type Info struct { DockerRootDir string } var b []byte var i Info b, err = testutil.ReadBody(body) if err == nil && resp.StatusCode == http.StatusOK { // read the docker root dir if err = json.Unmarshal(b, &i); err == nil { return i.DockerRootDir, nil } } return "", err }
func (s *DockerSuite) TestBuildAPIBuildGitWithF(c *check.C) { git, err := newFakeGit("repo", map[string]string{ "baz": `FROM busybox RUN echo from baz`, "Dockerfile": `FROM busybox RUN echo from Dockerfile`, }, false) c.Assert(err, checker.IsNil) defer git.Close() // Make sure it tries to 'dockerfile' query param value res, body, err := request.SockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json", daemonHost()) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusOK) buf, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) out := string(buf) c.Assert(out, checker.Contains, "from baz") }
func (s *DockerSuite) TestBuildAPIDoubleDockerfile(c *check.C) { testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows git, err := newFakeGit("repo", map[string]string{ "Dockerfile": `FROM busybox RUN echo from Dockerfile`, "dockerfile": `FROM busybox RUN echo from dockerfile`, }, false) c.Assert(err, checker.IsNil) 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(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusOK) buf, err := testutil.ReadBody(body) c.Assert(err, checker.IsNil) out := string(buf) c.Assert(out, checker.Contains, "from Dockerfile") }