Skip to content

Commit f257f77

Browse files
committed
choose rpc code to determine status code
Signed-off-by: allencloud <[email protected]>
1 parent c8141a1 commit f257f77

10 files changed

+68
-10
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ RUN set -x \
186186
&& rm -rf "$GOPATH"
187187

188188
# Get the "docker-py" source so we can run their integration tests
189-
ENV DOCKER_PY_COMMIT 4a08d04aef0595322e1b5ac7c52f28a931da85a5
189+
ENV DOCKER_PY_COMMIT dc2b24dcdd4ed7c8f6874ee5dd95716761ab6c93
190190
# To run integration tests docker-pycreds is required.
191191
# Before running the integration tests conftest.py is
192192
# loaded which results in loads auth.py that

Dockerfile.aarch64

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ RUN set -x \
142142
&& rm -rf "$GOPATH"
143143

144144
# Get the "docker-py" source so we can run their integration tests
145-
ENV DOCKER_PY_COMMIT 4a08d04aef0595322e1b5ac7c52f28a931da85a5
145+
ENV DOCKER_PY_COMMIT dc2b24dcdd4ed7c8f6874ee5dd95716761ab6c93
146146
# Before running the integration tests conftest.py is
147147
# loaded which results in loads auth.py that
148148
# imports the docker-pycreds module.

Dockerfile.armhf

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ RUN set -x \
137137
&& rm -rf "$GOPATH"
138138

139139
# Get the "docker-py" source so we can run their integration tests
140-
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
140+
ENV DOCKER_PY_COMMIT dc2b24dcdd4ed7c8f6874ee5dd95716761ab6c93
141141
RUN git clone https://github.com/docker/docker-py.git /docker-py \
142142
&& cd /docker-py \
143143
&& git checkout -q $DOCKER_PY_COMMIT \

Dockerfile.ppc64le

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ RUN set -x \
143143
&& rm -rf "$GOPATH"
144144

145145
# Get the "docker-py" source so we can run their integration tests
146-
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
146+
ENV DOCKER_PY_COMMIT dc2b24dcdd4ed7c8f6874ee5dd95716761ab6c93
147147
RUN git clone https://github.com/docker/docker-py.git /docker-py \
148148
&& cd /docker-py \
149149
&& git checkout -q $DOCKER_PY_COMMIT \

Dockerfile.s390x

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ RUN set -x \
136136
&& rm -rf "$GOPATH"
137137

138138
# Get the "docker-py" source so we can run their integration tests
139-
ENV DOCKER_PY_COMMIT e2655f658408f9ad1f62abdef3eb6ed43c0cf324
139+
ENV DOCKER_PY_COMMIT dc2b24dcdd4ed7c8f6874ee5dd95716761ab6c93
140140
RUN git clone https://github.com/docker/docker-py.git /docker-py \
141141
&& cd /docker-py \
142142
&& git checkout -q $DOCKER_PY_COMMIT \

api/server/httputils/errors.go

+40
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/docker/docker/api/types/versions"
1010
"github.com/gorilla/mux"
1111
"google.golang.org/grpc"
12+
"google.golang.org/grpc/codes"
1213
)
1314

1415
// httpStatusError is an interface
@@ -44,11 +45,17 @@ func GetHTTPErrorStatusCode(err error) int {
4445
case inputValidationError:
4546
statusCode = http.StatusBadRequest
4647
default:
48+
statusCode = statusCodeFromGRPCError(err)
49+
if statusCode != http.StatusInternalServerError {
50+
return statusCode
51+
}
52+
4753
// FIXME: this is brittle and should not be necessary, but we still need to identify if
4854
// there are errors falling back into this logic.
4955
// If we need to differentiate between different possible error types,
5056
// we should create appropriate error types that implement the httpStatusError interface.
5157
errStr := strings.ToLower(errMsg)
58+
5259
for _, status := range []struct {
5360
keyword string
5461
code int
@@ -102,3 +109,36 @@ func MakeErrorHandler(err error) http.HandlerFunc {
102109
}
103110
}
104111
}
112+
113+
// statusCodeFromGRPCError returns status code according to gRPC error
114+
func statusCodeFromGRPCError(err error) int {
115+
switch grpc.Code(err) {
116+
case codes.InvalidArgument: // code 3
117+
return http.StatusBadRequest
118+
case codes.NotFound: // code 5
119+
return http.StatusNotFound
120+
case codes.AlreadyExists: // code 6
121+
return http.StatusConflict
122+
case codes.PermissionDenied: // code 7
123+
return http.StatusForbidden
124+
case codes.FailedPrecondition: // code 9
125+
return http.StatusBadRequest
126+
case codes.Unauthenticated: // code 16
127+
return http.StatusUnauthorized
128+
case codes.OutOfRange: // code 11
129+
return http.StatusBadRequest
130+
case codes.Unimplemented: // code 12
131+
return http.StatusNotImplemented
132+
case codes.Unavailable: // code 14
133+
return http.StatusServiceUnavailable
134+
default:
135+
// codes.Canceled(1)
136+
// codes.Unknown(2)
137+
// codes.DeadlineExceeded(4)
138+
// codes.ResourceExhausted(8)
139+
// codes.Aborted(10)
140+
// codes.Internal(13)
141+
// codes.DataLoss(15)
142+
return http.StatusInternalServerError
143+
}
144+
}

docs/api/version-history.md

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ keywords: "API, Docker, rcli, REST, documentation"
2929
generate and rotate to a new CA certificate/key pair.
3030
* `POST /service/create` and `POST /services/(id or name)/update` now take the field `Platforms` as part of the service `Placement`, allowing to specify platforms supported by the service.
3131
* `POST /containers/(name)/wait` now accepts a `condition` query parameter to indicate which state change condition to wait for. Also, response headers are now returned immediately to acknowledge that the server has registered a wait callback for the client.
32+
* `DELETE /secrets/(name)` now returns status code 404 instead of 500 when the secret does not exist.
33+
* `POST /secrets/create` now returns status code 409 instead of 500 when creating an already existing secret.
34+
* `POST /secrets/(name)/update` now returns status code 400 instead of 500 when updating a secret's content which is not the labels.
35+
* `POST /nodes/(name)/update` now returns status code 400 instead of 500 when demoting last node fails.
3236

3337
## v1.29 API changes
3438

integration-cli/docker_api_swarm_config_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,5 @@ func (s *DockerSwarmSuite) TestAPISwarmConfigsUpdate(c *check.C) {
114114
status, out, err := d.SockRequest("POST", url, config.Spec)
115115

116116
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
117-
c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("output: %q", string(out)))
117+
c.Assert(status, checker.Equals, http.StatusBadRequest, check.Commentf("output: %q", string(out)))
118118
}

integration-cli/docker_api_swarm_secret_test.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,25 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsCreate(c *check.C) {
2323
d := s.AddDaemon(c, true, true)
2424

2525
testName := "test_secret"
26-
id := d.CreateSecret(c, swarm.SecretSpec{
26+
secretSpec := swarm.SecretSpec{
2727
Annotations: swarm.Annotations{
2828
Name: testName,
2929
},
3030
Data: []byte("TESTINGDATA"),
31-
})
31+
}
32+
33+
id := d.CreateSecret(c, secretSpec)
3234
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
3335

3436
secrets := d.ListSecrets(c)
3537
c.Assert(len(secrets), checker.Equals, 1, check.Commentf("secrets: %#v", secrets))
3638
name := secrets[0].Spec.Annotations.Name
3739
c.Assert(name, checker.Equals, testName, check.Commentf("secret: %s", name))
40+
41+
// create an already existing secret, daemon should return a status code of 409
42+
status, out, err := d.SockRequest("POST", "/secrets/create", secretSpec)
43+
c.Assert(err, checker.IsNil)
44+
c.Assert(status, checker.Equals, http.StatusConflict, check.Commentf("secret create: %s", string(out)))
3845
}
3946

4047
func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
@@ -55,6 +62,13 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
5562
status, out, err := d.SockRequest("GET", "/secrets/"+id, nil)
5663
c.Assert(err, checker.IsNil)
5764
c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf("secret delete: %s", string(out)))
65+
66+
// delete non-existing secret, daemon should return a status code of 404
67+
id = "non-existing"
68+
status, out, err = d.SockRequest("DELETE", "/secrets/"+id, nil)
69+
c.Assert(err, checker.IsNil)
70+
c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf("secret delete: %s", string(out)))
71+
5872
}
5973

6074
func (s *DockerSwarmSuite) TestAPISwarmSecretsUpdate(c *check.C) {
@@ -114,5 +128,5 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsUpdate(c *check.C) {
114128
status, out, err := d.SockRequest("POST", url, secret.Spec)
115129

116130
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
117-
c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("output: %q", string(out)))
131+
c.Assert(status, checker.Equals, http.StatusBadRequest, check.Commentf("output: %q", string(out)))
118132
}

integration-cli/docker_api_swarm_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
229229
url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index)
230230
status, out, err := d1.SockRequest("POST", url, node.Spec)
231231
c.Assert(err, checker.IsNil)
232-
c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("output: %q", string(out)))
232+
c.Assert(status, checker.Equals, http.StatusBadRequest, check.Commentf("output: %q", string(out)))
233233
// The warning specific to demoting the last manager is best-effort and
234234
// won't appear until the Role field of the demoted manager has been
235235
// updated.

0 commit comments

Comments
 (0)