diff --git a/api/server/router/swarm/cluster_routes.go b/api/server/router/swarm/cluster_routes.go index fe976434bc..59420fe905 100644 --- a/api/server/router/swarm/cluster_routes.go +++ b/api/server/router/swarm/cluster_routes.go @@ -65,7 +65,8 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, rawVersion := r.URL.Query().Get("version") version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { - return fmt.Errorf("Invalid swarm version '%s': %s", rawVersion, err.Error()) + err := fmt.Errorf("invalid swarm version '%s': %v", rawVersion, err) + return errors.NewBadRequestError(err) } var flags types.UpdateFlags @@ -73,7 +74,8 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, if value := r.URL.Query().Get("rotateWorkerToken"); value != "" { rot, err := strconv.ParseBool(value) if err != nil { - return fmt.Errorf("invalid value for rotateWorkerToken: %s", value) + err := fmt.Errorf("invalid value for rotateWorkerToken: %s", value) + return errors.NewBadRequestError(err) } flags.RotateWorkerToken = rot @@ -82,7 +84,8 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, if value := r.URL.Query().Get("rotateManagerToken"); value != "" { rot, err := strconv.ParseBool(value) if err != nil { - return fmt.Errorf("invalid value for rotateManagerToken: %s", value) + err := fmt.Errorf("invalid value for rotateManagerToken: %s", value) + return errors.NewBadRequestError(err) } flags.RotateManagerToken = rot @@ -91,7 +94,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, if value := r.URL.Query().Get("rotateManagerUnlockKey"); value != "" { rot, err := strconv.ParseBool(value) if err != nil { - return fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value) + return errors.NewBadRequestError(fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value)) } flags.RotateManagerUnlockKey = rot @@ -184,7 +187,8 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, rawVersion := r.URL.Query().Get("version") version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { - return fmt.Errorf("Invalid service version '%s': %s", rawVersion, err.Error()) + err := fmt.Errorf("invalid service version '%s': %v", rawVersion, err) + return errors.NewBadRequestError(err) } // Get returns "" if the header does not exist @@ -294,7 +298,8 @@ func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r rawVersion := r.URL.Query().Get("version") version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { - return fmt.Errorf("Invalid node version '%s': %s", rawVersion, err.Error()) + err := fmt.Errorf("invalid node version '%s': %v", rawVersion, err) + return errors.NewBadRequestError(err) } if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil { diff --git a/api/swagger.yaml b/api/swagger.yaml index 91519c8dcc..09881f0073 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -6730,10 +6730,22 @@ paths: type: "array" items: $ref: "#/definitions/Node" + 400: + description: "bad parameter" + schema: + $ref: "#/definitions/ErrorResponse" + 404: + description: "no such node" + schema: + $ref: "#/definitions/ErrorResponse" 500: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "filters" in: "query" @@ -6765,6 +6777,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -6786,6 +6802,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -6813,6 +6833,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -6877,10 +6901,18 @@ paths: UpdatedAt: "2016-08-15T16:32:09.623207604Z" Version: Index: 51 + 404: + description: "no such swarm" + schema: + $ref: "#/definitions/ErrorResponse" 500: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" tags: ["Swarm"] /swarm/init: post: @@ -6900,14 +6932,14 @@ paths: description: "bad parameter" schema: $ref: "#/definitions/ErrorResponse" - 406: - description: "node is already part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" 500: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is already part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "body" in: "body" @@ -7073,6 +7105,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" tags: ["Swarm"] /swarm/unlock: post: @@ -7101,6 +7137,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" tags: ["Swarm"] /services: get: @@ -7117,6 +7157,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "filters" in: "query" @@ -7151,6 +7195,10 @@ paths: example: ID: "ak7w3gjqoa3kuz8xcpnyy0pvl" Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found" + 400: + description: "bad parameter" + schema: + $ref: "#/definitions/ErrorResponse" 403: description: "network is not eligible for services" schema: @@ -7164,7 +7212,7 @@ paths: schema: $ref: "#/definitions/ErrorResponse" 503: - description: "server error or node is not part of a swarm" + description: "node is not part of a swarm" schema: $ref: "#/definitions/ErrorResponse" parameters: @@ -7246,6 +7294,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -7267,6 +7319,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -7285,6 +7341,10 @@ paths: description: "no error" schema: $ref: "#/definitions/ImageDeleteResponse" + 400: + description: "bad parameter" + schema: + $ref: "#/definitions/ErrorResponse" 404: description: "no such service" schema: @@ -7293,6 +7353,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -7381,6 +7445,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -7550,11 +7618,14 @@ paths: Gateway: "10.255.0.1" Addresses: - "10.255.0.5/16" - 500: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "filters" in: "query" @@ -7588,6 +7659,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -7620,6 +7695,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "filters" in: "query" @@ -7648,10 +7727,6 @@ paths: type: "string" example: ID: "ktnbjxoalbkvbvedmg1urrz8h" - 406: - description: "server error or node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" 409: description: "name conflicts with an existing object" schema: @@ -7660,6 +7735,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "body" in: "body" @@ -7696,14 +7775,14 @@ paths: description: "secret not found" schema: $ref: "#/definitions/ErrorResponse" - 406: - description: "node is not part of a swarm" - schema: - $ref: "#/definitions/ErrorResponse" 500: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" @@ -7727,6 +7806,10 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + 503: + description: "node is not part of a swarm" + schema: + $ref: "#/definitions/ErrorResponse" parameters: - name: "id" in: "path" diff --git a/daemon/cluster/cluster.go b/daemon/cluster/cluster.go index ea8ac62e91..aee9c7dc10 100644 --- a/daemon/cluster/cluster.go +++ b/daemon/cluster/cluster.go @@ -268,7 +268,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) { c.mu.Unlock() if err := validateAndSanitizeInitRequest(&req); err != nil { - return "", err + return "", apierrors.NewBadRequestError(err) } listenHost, listenPort, err := resolveListenAddr(req.ListenAddr) @@ -363,7 +363,7 @@ func (c *Cluster) Join(req types.JoinRequest) error { c.mu.Unlock() if err := validateAndSanitizeJoinRequest(&req); err != nil { - return err + return apierrors.NewBadRequestError(err) } listenHost, listenPort, err := resolveListenAddr(req.ListenAddr) @@ -628,7 +628,7 @@ func (c *Cluster) Update(version uint64, spec types.Spec, flags types.UpdateFlag // will be used to swarmkit. clusterSpec, err := convert.SwarmSpecToGRPC(spec) if err != nil { - return err + return apierrors.NewBadRequestError(err) } _, err = state.controlClient.UpdateCluster( @@ -891,7 +891,7 @@ func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string) (*apity serviceSpec, err := convert.ServiceSpecToGRPC(s) if err != nil { - return nil, err + return nil, apierrors.NewBadRequestError(err) } ctnr := serviceSpec.Task.GetContainer() @@ -976,7 +976,7 @@ func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec typ serviceSpec, err := convert.ServiceSpecToGRPC(spec) if err != nil { - return nil, err + return nil, apierrors.NewBadRequestError(err) } currentService, err := getService(ctx, state.controlClient, serviceIDOrName) @@ -1194,7 +1194,7 @@ func (c *Cluster) GetNodes(options apitypes.NodeListOptions) ([]types.Node, erro return nodes, nil } -// GetNode returns a node based on an ID or name. +// GetNode returns a node based on an ID. func (c *Cluster) GetNode(input string) (types.Node, error) { c.mu.RLock() defer c.mu.RUnlock() @@ -1226,7 +1226,7 @@ func (c *Cluster) UpdateNode(input string, version uint64, spec types.NodeSpec) nodeSpec, err := convert.NodeSpecToGRPC(spec) if err != nil { - return err + return apierrors.NewBadRequestError(err) } ctx, cancel := c.getRequestContext() diff --git a/daemon/cluster/helpers.go b/daemon/cluster/helpers.go index bd94df4ab9..eee426bd48 100644 --- a/daemon/cluster/helpers.go +++ b/daemon/cluster/helpers.go @@ -3,6 +3,7 @@ package cluster import ( "fmt" + "github.com/docker/docker/api/errors" swarmapi "github.com/docker/swarmkit/api" "golang.org/x/net/context" ) @@ -14,7 +15,7 @@ func getSwarm(ctx context.Context, c swarmapi.ControlClient) (*swarmapi.Cluster, } if len(rl.Clusters) == 0 { - return nil, fmt.Errorf("swarm not found") + return nil, errors.NewRequestNotFoundError(errNoSwarm) } // TODO: assume one cluster only @@ -38,7 +39,8 @@ func getNode(ctx context.Context, c swarmapi.ControlClient, input string) (*swar } if len(rl.Nodes) == 0 { - return nil, fmt.Errorf("node %s not found", input) + err := fmt.Errorf("node %s not found", input) + return nil, errors.NewRequestNotFoundError(err) } if l := len(rl.Nodes); l > 1 { @@ -66,7 +68,8 @@ func getService(ctx context.Context, c swarmapi.ControlClient, input string) (*s } if len(rl.Services) == 0 { - return nil, fmt.Errorf("service %s not found", input) + err := fmt.Errorf("service %s not found", input) + return nil, errors.NewRequestNotFoundError(err) } if l := len(rl.Services); l > 1 { @@ -95,7 +98,8 @@ func getTask(ctx context.Context, c swarmapi.ControlClient, input string) (*swar } if len(rl.Tasks) == 0 { - return nil, fmt.Errorf("task %s not found", input) + err := fmt.Errorf("task %s not found", input) + return nil, errors.NewRequestNotFoundError(err) } if l := len(rl.Tasks); l > 1 { diff --git a/integration-cli/docker_api_swarm_test.go b/integration-cli/docker_api_swarm_test.go index 497da43415..3eb9ebdc61 100644 --- a/integration-cli/docker_api_swarm_test.go +++ b/integration-cli/docker_api_swarm_test.go @@ -962,7 +962,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) { } status, _, err := d.SockRequest("POST", "/swarm/init", req) c.Assert(err, checker.IsNil) - c.Assert(status, checker.Equals, http.StatusInternalServerError) + c.Assert(status, checker.Equals, http.StatusBadRequest) req2 := swarm.JoinRequest{ ListenAddr: "0.0.0.0:2377", @@ -970,7 +970,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) { } status, _, err = d.SockRequest("POST", "/swarm/join", req2) c.Assert(err, checker.IsNil) - c.Assert(status, checker.Equals, http.StatusInternalServerError) + c.Assert(status, checker.Equals, http.StatusBadRequest) } func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *check.C) {