Return remote API errors as JSON
Signed-off-by: Ben Firshman <ben@firshman.co.uk> Upstream-commit: 322e2a7d059a81617b593cf6ece2cfd9f6d4ea03 Component: engine
This commit is contained in:
@@ -85,8 +85,8 @@ func (s *DockerSuite) TestGetContainersWsAttachContainerNotFound(c *check.C) {
|
||||
status, body, err := sockRequest("GET", "/containers/doesnotexist/attach/ws", nil)
|
||||
c.Assert(status, checker.Equals, http.StatusNotFound)
|
||||
c.Assert(err, checker.IsNil)
|
||||
expected := "No such container: doesnotexist\n"
|
||||
c.Assert(string(body), checker.Contains, expected)
|
||||
expected := "No such container: doesnotexist"
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
|
||||
|
||||
@@ -16,9 +16,10 @@ func (s *DockerSuite) TestAuthApi(c *check.C) {
|
||||
Password: "no-password",
|
||||
}
|
||||
|
||||
expected := "Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password\n"
|
||||
expected := "Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password"
|
||||
status, body, err := sockRequest("POST", "/auth", config)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusUnauthorized)
|
||||
c.Assert(string(body), checker.Contains, expected, check.Commentf("Expected: %v, got: %v", expected, string(body)))
|
||||
msg := getErrorMessage(c, body)
|
||||
c.Assert(msg, checker.Contains, expected, check.Commentf("Expected: %v, got: %v", expected, msg))
|
||||
}
|
||||
|
||||
@@ -480,10 +480,10 @@ func (s *DockerSuite) TestContainerApiBadPort(c *check.C) {
|
||||
jsonData := bytes.NewBuffer(nil)
|
||||
json.NewEncoder(jsonData).Encode(config)
|
||||
|
||||
status, b, err := sockRequest("POST", "/containers/create", config)
|
||||
status, body, err := sockRequest("POST", "/containers/create", config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusInternalServerError)
|
||||
c.Assert(strings.TrimSpace(string(b)), checker.Equals, `Invalid port specification: "aa80"`, check.Commentf("Incorrect error msg: %s", string(b)))
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, `Invalid port specification: "aa80"`, check.Commentf("Incorrect error msg: %s", body))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
|
||||
@@ -509,12 +509,12 @@ func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
|
||||
func (s *DockerSuite) TestContainerApiCreateEmptyConfig(c *check.C) {
|
||||
config := map[string]interface{}{}
|
||||
|
||||
status, b, err := sockRequest("POST", "/containers/create", config)
|
||||
status, body, err := sockRequest("POST", "/containers/create", config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusInternalServerError)
|
||||
|
||||
expected := "Config cannot be empty in order to create a container\n"
|
||||
c.Assert(string(b), checker.Equals, expected)
|
||||
expected := "Config cannot be empty in order to create a container"
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiCreateMultipleNetworksConfig(c *check.C) {
|
||||
@@ -530,14 +530,15 @@ func (s *DockerSuite) TestContainerApiCreateMultipleNetworksConfig(c *check.C) {
|
||||
},
|
||||
}
|
||||
|
||||
status, b, err := sockRequest("POST", "/containers/create", config)
|
||||
status, body, err := sockRequest("POST", "/containers/create", config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusBadRequest)
|
||||
msg := getErrorMessage(c, body)
|
||||
// network name order in error message is not deterministic
|
||||
c.Assert(string(b), checker.Contains, "Container cannot be connected to network endpoints")
|
||||
c.Assert(string(b), checker.Contains, "net1")
|
||||
c.Assert(string(b), checker.Contains, "net2")
|
||||
c.Assert(string(b), checker.Contains, "net3")
|
||||
c.Assert(msg, checker.Contains, "Container cannot be connected to network endpoints")
|
||||
c.Assert(msg, checker.Contains, "net1")
|
||||
c.Assert(msg, checker.Contains, "net2")
|
||||
c.Assert(msg, checker.Contains, "net3")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
|
||||
@@ -997,7 +998,7 @@ func (s *DockerSuite) TestContainerApiDeleteNotExist(c *check.C) {
|
||||
status, body, err := sockRequest("DELETE", "/containers/doesnotexist", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusNotFound)
|
||||
c.Assert(string(body), checker.Matches, "No such container: doesnotexist\n")
|
||||
c.Assert(getErrorMessage(c, body), checker.Matches, "No such container: doesnotexist")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestContainerApiDeleteForce(c *check.C) {
|
||||
@@ -1247,8 +1248,8 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C)
|
||||
status, body, err := sockRequest("POST", "/containers/create?name="+name, c1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusInternalServerError)
|
||||
expected := "Invalid value 1-42,, for cpuset cpus\n"
|
||||
c.Assert(string(body), checker.Equals, expected)
|
||||
expected := "Invalid value 1-42,, for cpuset cpus"
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, expected)
|
||||
|
||||
c2 := struct {
|
||||
Image string
|
||||
@@ -1258,8 +1259,8 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C)
|
||||
status, body, err = sockRequest("POST", "/containers/create?name="+name, c2)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusInternalServerError)
|
||||
expected = "Invalid value 42-3,1-- for cpuset mems\n"
|
||||
c.Assert(string(body), checker.Equals, expected)
|
||||
expected = "Invalid value 42-3,1-- for cpuset mems"
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) {
|
||||
@@ -1273,7 +1274,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) {
|
||||
status, body, err := sockRequest("POST", "/containers/create", config)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusInternalServerError)
|
||||
c.Assert(string(body), checker.Contains, "SHM size must be greater than 0")
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, "SHM size must be greater than 0")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.C) {
|
||||
@@ -1409,9 +1410,11 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che
|
||||
status, b, err := sockRequest("POST", "/containers/create?name="+name, config)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusInternalServerError)
|
||||
|
||||
expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]"
|
||||
if !strings.Contains(string(b), expected) {
|
||||
c.Fatalf("Expected output to contain %q, got %q", expected, string(b))
|
||||
msg := getErrorMessage(c, b)
|
||||
if !strings.Contains(msg, expected) {
|
||||
c.Fatalf("Expected output to contain %q, got %q", expected, msg)
|
||||
}
|
||||
|
||||
config = struct {
|
||||
@@ -1423,8 +1426,9 @@ func (s *DockerSuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c *che
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusInternalServerError)
|
||||
expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]"
|
||||
if !strings.Contains(string(b), expected) {
|
||||
c.Fatalf("Expected output to contain %q, got %q", expected, string(b))
|
||||
msg = getErrorMessage(c, b)
|
||||
if !strings.Contains(msg, expected) {
|
||||
c.Fatalf("Expected output to contain %q, got %q", expected, msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/integration/checker"
|
||||
"github.com/go-check/check"
|
||||
@@ -15,31 +14,31 @@ func (s *DockerSuite) TestApiCreateWithNotExistImage(c *check.C) {
|
||||
"Volumes": map[string]struct{}{"/tmp": {}},
|
||||
}
|
||||
|
||||
status, resp, err := sockRequest("POST", "/containers/create?name="+name, config)
|
||||
status, body, err := sockRequest("POST", "/containers/create?name="+name, config)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusNotFound)
|
||||
expected := "No such image: test456:v1"
|
||||
c.Assert(strings.TrimSpace(string(resp)), checker.Contains, expected)
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, expected)
|
||||
|
||||
config2 := map[string]interface{}{
|
||||
"Image": "test456",
|
||||
"Volumes": map[string]struct{}{"/tmp": {}},
|
||||
}
|
||||
|
||||
status, resp, err = sockRequest("POST", "/containers/create?name="+name, config2)
|
||||
status, body, err = sockRequest("POST", "/containers/create?name="+name, config2)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusNotFound)
|
||||
expected = "No such image: test456:latest"
|
||||
c.Assert(strings.TrimSpace(string(resp)), checker.Equals, expected)
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, expected)
|
||||
|
||||
config3 := map[string]interface{}{
|
||||
"Image": "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
|
||||
}
|
||||
|
||||
status, resp, err = sockRequest("POST", "/containers/create?name="+name, config3)
|
||||
status, body, err = sockRequest("POST", "/containers/create?name="+name, config3)
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(status, check.Equals, http.StatusNotFound)
|
||||
expected = "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa"
|
||||
c.Assert(strings.TrimSpace(string(resp)), checker.Equals, expected)
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, expected)
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func (s *DockerSuite) TestExecApiCreateNoCmd(c *check.C) {
|
||||
c.Assert(status, checker.Equals, http.StatusInternalServerError)
|
||||
|
||||
comment := check.Commentf("Expected message when creating exec command with no Cmd specified")
|
||||
c.Assert(string(body), checker.Contains, "No exec command specified", comment)
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, "No exec command specified", comment)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecApiCreateNoValidContentType(c *check.C) {
|
||||
@@ -44,7 +44,7 @@ func (s *DockerSuite) TestExecApiCreateNoValidContentType(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
comment := check.Commentf("Expected message when creating exec command with invalid Content-Type specified")
|
||||
c.Assert(string(b), checker.Contains, "Content-Type specified", comment)
|
||||
c.Assert(getErrorMessage(c, b), checker.Contains, "Content-Type specified", comment)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecApiCreateContainerPaused(c *check.C) {
|
||||
@@ -59,7 +59,7 @@ func (s *DockerSuite) TestExecApiCreateContainerPaused(c *check.C) {
|
||||
c.Assert(status, checker.Equals, http.StatusConflict)
|
||||
|
||||
comment := check.Commentf("Expected message when creating exec command with Container %s is paused", name)
|
||||
c.Assert(string(body), checker.Contains, "Container "+name+" is paused, unpause the container before exec", comment)
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, "Container "+name+" is paused, unpause the container before exec", comment)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestExecApiStart(c *check.C) {
|
||||
|
||||
@@ -60,9 +60,7 @@ func (s *DockerSuite) TestLogsApiNoStdoutNorStderr(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expected := "Bad parameters: you must choose at least one stream"
|
||||
if !bytes.Contains(body, []byte(expected)) {
|
||||
c.Fatalf("Expected %s, got %s", expected, string(body[:]))
|
||||
}
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, expected)
|
||||
}
|
||||
|
||||
// Regression test for #12704
|
||||
|
||||
@@ -40,5 +40,5 @@ func (s *DockerSuite) TestResizeApiResponseWhenContainerNotStarted(c *check.C) {
|
||||
c.Assert(status, check.Equals, http.StatusInternalServerError)
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
c.Assert(string(body), checker.Contains, "is not running", check.Commentf("resize should fail with message 'Container is not running'"))
|
||||
c.Assert(getErrorMessage(c, body), checker.Contains, "is not running", check.Commentf("resize should fail with message 'Container is not running'"))
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func (s *DockerSuite) TestApiClientVersionNewerThanServer(c *check.C) {
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusBadRequest)
|
||||
expected := fmt.Sprintf("client is newer than server (client API version: %s, server API version: %s)", version, api.DefaultVersion)
|
||||
c.Assert(strings.TrimSpace(string(body)), checker.Equals, expected)
|
||||
c.Assert(getErrorMessage(c, body), checker.Equals, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiClientVersionOldNotSupported(c *check.C) {
|
||||
@@ -99,3 +99,44 @@ func (s *DockerSuite) TestApiDockerApiVersion(c *check.C) {
|
||||
c.Fatalf("Out didn't have 'xxx' for the API version, had:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
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 := 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) TestApiErrorPlainText(c *check.C) {
|
||||
httpResp, body, err := sockRequestRaw("POST", "/v1.23/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.Contains, "text/plain")
|
||||
b, err := 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")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestApiErrorNotFoundJSON(c *check.C) {
|
||||
// 404 is a different code path to normal errors, so test separately
|
||||
httpResp, body, err := sockRequestRaw("GET", "/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.Equals, "application/json")
|
||||
b, err := readBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(getErrorMessage(c, b), checker.Equals, "page not found")
|
||||
}
|
||||
|
||||
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 := readBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(string(b)), checker.Equals, "page not found")
|
||||
}
|
||||
|
||||
@@ -1507,3 +1507,10 @@ func waitForGoroutines(expected int) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getErrorMessage returns the error message from an error API response
|
||||
func getErrorMessage(c *check.C, body []byte) string {
|
||||
var resp types.ErrorResponse
|
||||
c.Assert(json.Unmarshal(body, &resp), check.IsNil)
|
||||
return strings.TrimSpace(resp.Message)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user