Merge pull request #20699 from calavera/remove_static_error_declarations
Remove static errors from errors package.
This commit is contained in:
commit
df2b74188e
67 changed files with 452 additions and 1626 deletions
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
Cli "github.com/docker/docker/cli"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
|
@ -21,6 +20,11 @@ import (
|
|||
"github.com/docker/libnetwork/resolvconf/dns"
|
||||
)
|
||||
|
||||
const (
|
||||
errCmdNotFound = "Container command not found or does not exist."
|
||||
errCmdCouldNotBeInvoked = "Container command could not be invoked."
|
||||
)
|
||||
|
||||
func (cid *cidFile) Close() error {
|
||||
cid.file.Close()
|
||||
|
||||
|
@ -46,20 +50,13 @@ func (cid *cidFile) Write(id string) error {
|
|||
// return 125 for generic docker daemon failures
|
||||
func runStartContainerErr(err error) error {
|
||||
trimmedErr := strings.Trim(err.Error(), "Error response from daemon: ")
|
||||
statusError := Cli.StatusError{}
|
||||
derrCmdNotFound := derr.ErrorCodeCmdNotFound.Message()
|
||||
derrCouldNotInvoke := derr.ErrorCodeCmdCouldNotBeInvoked.Message()
|
||||
derrNoSuchImage := derr.ErrorCodeNoSuchImageHash.Message()
|
||||
derrNoSuchImageTag := derr.ErrorCodeNoSuchImageTag.Message()
|
||||
statusError := Cli.StatusError{StatusCode: 125}
|
||||
|
||||
switch trimmedErr {
|
||||
case derrCmdNotFound:
|
||||
case errCmdNotFound:
|
||||
statusError = Cli.StatusError{StatusCode: 127}
|
||||
case derrCouldNotInvoke:
|
||||
case errCmdCouldNotBeInvoked:
|
||||
statusError = Cli.StatusError{StatusCode: 126}
|
||||
case derrNoSuchImage, derrNoSuchImageTag:
|
||||
statusError = Cli.StatusError{StatusCode: 125}
|
||||
default:
|
||||
statusError = Cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
return statusError
|
||||
}
|
||||
|
|
69
api/server/httputils/errors.go
Normal file
69
api/server/httputils/errors.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package httputils
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
// httpStatusError is an interface
|
||||
// that errors with custom status codes
|
||||
// implement to tell the api layer
|
||||
// which response status to set.
|
||||
type httpStatusError interface {
|
||||
HTTPErrorStatusCode() int
|
||||
}
|
||||
|
||||
// inputValidationError is an interface
|
||||
// that errors generated by invalid
|
||||
// inputs can implement to tell the
|
||||
// api layer to set a 400 status code
|
||||
// in the response.
|
||||
type inputValidationError interface {
|
||||
IsValidationError() bool
|
||||
}
|
||||
|
||||
// WriteError decodes a specific docker error and sends it in the response.
|
||||
func WriteError(w http.ResponseWriter, err error) {
|
||||
if err == nil || w == nil {
|
||||
logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling")
|
||||
return
|
||||
}
|
||||
|
||||
var statusCode int
|
||||
errMsg := err.Error()
|
||||
|
||||
switch e := err.(type) {
|
||||
case httpStatusError:
|
||||
statusCode = e.HTTPErrorStatusCode()
|
||||
case inputValidationError:
|
||||
statusCode = http.StatusBadRequest
|
||||
default:
|
||||
// FIXME: this is brittle and should not be necessary, but we still need to identify if
|
||||
// there are errors falling back into this logic.
|
||||
// If we need to differentiate between different possible error types,
|
||||
// we should create appropriate error types that implement the httpStatusError interface.
|
||||
errStr := strings.ToLower(errMsg)
|
||||
for keyword, status := range map[string]int{
|
||||
"not found": http.StatusNotFound,
|
||||
"no such": http.StatusNotFound,
|
||||
"bad parameter": http.StatusBadRequest,
|
||||
"conflict": http.StatusConflict,
|
||||
"impossible": http.StatusNotAcceptable,
|
||||
"wrong login/password": http.StatusUnauthorized,
|
||||
"hasn't been activated": http.StatusForbidden,
|
||||
} {
|
||||
if strings.Contains(errStr, keyword) {
|
||||
statusCode = status
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if statusCode == 0 {
|
||||
statusCode = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
http.Error(w, errMsg, statusCode)
|
||||
}
|
|
@ -9,8 +9,6 @@ import (
|
|||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/pkg/version"
|
||||
)
|
||||
|
@ -85,78 +83,6 @@ func ParseMultipartForm(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// WriteError decodes a specific docker error and sends it in the response.
|
||||
func WriteError(w http.ResponseWriter, err error) {
|
||||
if err == nil || w == nil {
|
||||
logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling")
|
||||
return
|
||||
}
|
||||
|
||||
statusCode := http.StatusInternalServerError
|
||||
errMsg := err.Error()
|
||||
|
||||
// Based on the type of error we get we need to process things
|
||||
// slightly differently to extract the error message.
|
||||
// In the 'errcode.*' cases there are two different type of
|
||||
// error that could be returned. errocode.ErrorCode is the base
|
||||
// type of error object - it is just an 'int' that can then be
|
||||
// used as the look-up key to find the message. errorcode.Error
|
||||
// extends errorcode.Error by adding error-instance specific
|
||||
// data, like 'details' or variable strings to be inserted into
|
||||
// the message.
|
||||
//
|
||||
// Ideally, we should just be able to call err.Error() for all
|
||||
// cases but the errcode package doesn't support that yet.
|
||||
//
|
||||
// Additionally, in both errcode cases, there might be an http
|
||||
// status code associated with it, and if so use it.
|
||||
switch err.(type) {
|
||||
case errcode.ErrorCode:
|
||||
daError, _ := err.(errcode.ErrorCode)
|
||||
statusCode = daError.Descriptor().HTTPStatusCode
|
||||
errMsg = daError.Message()
|
||||
|
||||
case errcode.Error:
|
||||
// For reference, if you're looking for a particular error
|
||||
// then you can do something like :
|
||||
// import ( derr "github.com/docker/docker/errors" )
|
||||
// if daError.ErrorCode() == derr.ErrorCodeNoSuchContainer { ... }
|
||||
|
||||
daError, _ := err.(errcode.Error)
|
||||
statusCode = daError.ErrorCode().Descriptor().HTTPStatusCode
|
||||
errMsg = daError.Message
|
||||
|
||||
default:
|
||||
// This part of will be removed once we've
|
||||
// converted everything over to use the errcode package
|
||||
|
||||
// FIXME: this is brittle and should not be necessary.
|
||||
// If we need to differentiate between different possible error types,
|
||||
// we should create appropriate error types with clearly defined meaning
|
||||
errStr := strings.ToLower(err.Error())
|
||||
for keyword, status := range map[string]int{
|
||||
"not found": http.StatusNotFound,
|
||||
"no such": http.StatusNotFound,
|
||||
"bad parameter": http.StatusBadRequest,
|
||||
"conflict": http.StatusConflict,
|
||||
"impossible": http.StatusNotAcceptable,
|
||||
"wrong login/password": http.StatusUnauthorized,
|
||||
"hasn't been activated": http.StatusForbidden,
|
||||
} {
|
||||
if strings.Contains(errStr, keyword) {
|
||||
statusCode = status
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if statusCode == 0 {
|
||||
statusCode = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
http.Error(w, errMsg, statusCode)
|
||||
}
|
||||
|
||||
// WriteJSON writes the value v to the http response stream as json with standard json encoding.
|
||||
func WriteJSON(w http.ResponseWriter, code int, v interface{}) error {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
|
|
@ -6,11 +6,18 @@ import (
|
|||
"runtime"
|
||||
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/version"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type badRequestError struct {
|
||||
error
|
||||
}
|
||||
|
||||
func (badRequestError) HTTPErrorStatusCode() int {
|
||||
return http.StatusBadRequest
|
||||
}
|
||||
|
||||
// NewVersionMiddleware creates a new Version middleware.
|
||||
func NewVersionMiddleware(versionCheck string, defaultVersion, minVersion version.Version) Middleware {
|
||||
serverVersion := version.Version(versionCheck)
|
||||
|
@ -23,10 +30,10 @@ func NewVersionMiddleware(versionCheck string, defaultVersion, minVersion versio
|
|||
}
|
||||
|
||||
if apiVersion.GreaterThan(defaultVersion) {
|
||||
return errors.ErrorCodeNewerClientVersion.WithArgs(apiVersion, defaultVersion)
|
||||
return badRequestError{fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", apiVersion, defaultVersion)}
|
||||
}
|
||||
if apiVersion.LessThan(minVersion) {
|
||||
return errors.ErrorCodeOldClientVersion.WithArgs(apiVersion, minVersion)
|
||||
return badRequestError{fmt.Errorf("client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", apiVersion, minVersion)}
|
||||
}
|
||||
|
||||
header := fmt.Sprintf("Docker/%s (%s)", serverVersion, runtime.GOOS)
|
||||
|
|
|
@ -53,12 +53,12 @@ func TestVersionMiddlewareWithErrors(t *testing.T) {
|
|||
err := h(ctx, resp, req, vars)
|
||||
|
||||
if !strings.Contains(err.Error(), "client version 0.1 is too old. Minimum supported API version is 1.2.0") {
|
||||
t.Fatalf("Expected ErrorCodeOldClientVersion, got %v", err)
|
||||
t.Fatalf("Expected too old client error, got %v", err)
|
||||
}
|
||||
|
||||
vars["version"] = "100000"
|
||||
err = h(ctx, resp, req, vars)
|
||||
if !strings.Contains(err.Error(), "client is newer than server") {
|
||||
t.Fatalf("Expected ErrorCodeNewerClientVersion, got %v", err)
|
||||
t.Fatalf("Expected client newer than server error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -17,7 +16,6 @@ import (
|
|||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/progress"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
"github.com/docker/go-units"
|
||||
|
@ -117,7 +115,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|||
if !output.Flushed() {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(sf.FormatError(errors.New(utils.GetErrorMessage(err))))
|
||||
_, err = w.Write(sf.FormatError(err))
|
||||
if err != nil {
|
||||
logrus.Warnf("could not write error response: %v", err)
|
||||
}
|
||||
|
|
|
@ -11,15 +11,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
"github.com/docker/engine-api/types/filters"
|
||||
|
@ -126,7 +123,7 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response
|
|||
// The client may be expecting all of the data we're sending to
|
||||
// be multiplexed, so send it through OutStream, which will
|
||||
// have been set up to handle that if needed.
|
||||
fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %s\n", utils.GetErrorMessage(err))
|
||||
fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %v\n", err)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
|
@ -182,6 +179,10 @@ func (s *containerRouter) postContainersStop(ctx context.Context, w http.Respons
|
|||
return nil
|
||||
}
|
||||
|
||||
type errContainerIsRunning interface {
|
||||
ContainerIsRunning() bool
|
||||
}
|
||||
|
||||
func (s *containerRouter) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
|
@ -199,15 +200,17 @@ func (s *containerRouter) postContainersKill(ctx context.Context, w http.Respons
|
|||
}
|
||||
|
||||
if err := s.backend.ContainerKill(name, uint64(sig)); err != nil {
|
||||
theErr, isDerr := err.(errcode.ErrorCoder)
|
||||
isStopped := isDerr && theErr.ErrorCode() == derr.ErrorCodeNotRunning
|
||||
var isStopped bool
|
||||
if e, ok := err.(errContainerIsRunning); ok {
|
||||
isStopped = !e.ContainerIsRunning()
|
||||
}
|
||||
|
||||
// Return error that's not caused because the container is stopped.
|
||||
// Return error if the container is not running and the api is >= 1.20
|
||||
// to keep backwards compatibility.
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
if version.GreaterThanOrEqualTo("1.20") || !isStopped {
|
||||
return fmt.Errorf("Cannot kill container %s: %v", name, utils.GetErrorMessage(err))
|
||||
return fmt.Errorf("Cannot kill container %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,7 +433,7 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
|
|||
|
||||
hijacker, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
return derr.ErrorCodeNoHijackConnection.WithArgs(containerName)
|
||||
return fmt.Errorf("error attaching to container %s, hijack connection missing", containerName)
|
||||
}
|
||||
|
||||
setupStreams := func() (io.ReadCloser, io.Writer, io.Writer, error) {
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/engine-api/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -46,7 +45,7 @@ func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.Re
|
|||
// Register an instance of Exec in container.
|
||||
id, err := s.backend.ContainerExecCreate(execConfig)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error setting up exec command in container %s: %s", name, utils.GetErrorMessage(err))
|
||||
logrus.Errorf("Error setting up exec command in container %s: %v", name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -113,7 +112,7 @@ func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.Res
|
|||
if execStartCheck.Detach {
|
||||
return err
|
||||
}
|
||||
logrus.Errorf("Error running exec in container: %v\n", utils.GetErrorMessage(err))
|
||||
logrus.Errorf("Error running exec in container: %v\n", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ type Backend interface {
|
|||
|
||||
type containerBackend interface {
|
||||
Commit(name string, config *types.ContainerCommitConfig) (imageID string, err error)
|
||||
Exists(containerName string) bool
|
||||
}
|
||||
|
||||
type imageBackend interface {
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/builder/dockerfile"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/streamformatter"
|
||||
"github.com/docker/docker/reference"
|
||||
|
@ -49,10 +48,6 @@ func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *
|
|||
c = &container.Config{}
|
||||
}
|
||||
|
||||
if !s.backend.Exists(cname) {
|
||||
return derr.ErrorCodeNoSuchContainer.WithArgs(cname)
|
||||
}
|
||||
|
||||
newConfig, err := dockerfile.BuildFromConfig(c, r.Form["changes"])
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -8,8 +8,6 @@ import (
|
|||
// Backend is all the methods that need to be implemented
|
||||
// to provide network specific functionality.
|
||||
type Backend interface {
|
||||
NetworkControllerEnabled() bool
|
||||
|
||||
FindNetwork(idName string) (libnetwork.Network, error)
|
||||
GetNetworkByName(idName string) (libnetwork.Network, error)
|
||||
GetNetworksByID(partialID string) []libnetwork.Network
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/errors"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
import "github.com/docker/docker/api/server/router"
|
||||
|
||||
// networkRouter is a router to talk with the network controller
|
||||
type networkRouter struct {
|
||||
|
@ -32,24 +25,13 @@ func (r *networkRouter) Routes() []router.Route {
|
|||
func (r *networkRouter) initRoutes() {
|
||||
r.routes = []router.Route{
|
||||
// GET
|
||||
router.NewGetRoute("/networks", r.controllerEnabledMiddleware(r.getNetworksList)),
|
||||
router.NewGetRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.getNetwork)),
|
||||
router.NewGetRoute("/networks", r.getNetworksList),
|
||||
router.NewGetRoute("/networks/{id:.*}", r.getNetwork),
|
||||
// POST
|
||||
router.NewPostRoute("/networks/create", r.controllerEnabledMiddleware(r.postNetworkCreate)),
|
||||
router.NewPostRoute("/networks/{id:.*}/connect", r.controllerEnabledMiddleware(r.postNetworkConnect)),
|
||||
router.NewPostRoute("/networks/{id:.*}/disconnect", r.controllerEnabledMiddleware(r.postNetworkDisconnect)),
|
||||
router.NewPostRoute("/networks/create", r.postNetworkCreate),
|
||||
router.NewPostRoute("/networks/{id:.*}/connect", r.postNetworkConnect),
|
||||
router.NewPostRoute("/networks/{id:.*}/disconnect", r.postNetworkDisconnect),
|
||||
// DELETE
|
||||
router.NewDeleteRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.deleteNetwork)),
|
||||
router.NewDeleteRoute("/networks/{id:.*}", r.deleteNetwork),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *networkRouter) controllerEnabledMiddleware(handler httputils.APIFunc) httputils.APIFunc {
|
||||
if r.backend.NetworkControllerEnabled() {
|
||||
return handler
|
||||
}
|
||||
return networkControllerDisabled
|
||||
}
|
||||
|
||||
func networkControllerDisabled(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
return errors.ErrorNetworkControllerNotEnabled.WithArgs()
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/pkg/authorization"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -134,7 +133,7 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
|
|||
}
|
||||
|
||||
if err := handlerFunc(ctx, w, r, vars); err != nil {
|
||||
logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.URL.Path, utils.GetErrorMessage(err))
|
||||
logrus.Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err)
|
||||
httputils.WriteError(w, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/builder"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||
|
@ -40,12 +39,12 @@ func nullDispatch(b *Builder, args []string, attributes map[string]bool, origina
|
|||
//
|
||||
func env(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) == 0 {
|
||||
return derr.ErrorCodeAtLeastOneArg.WithArgs("ENV")
|
||||
return errAtLeastOneArgument("ENV")
|
||||
}
|
||||
|
||||
if len(args)%2 != 0 {
|
||||
// should never get here, but just in case
|
||||
return derr.ErrorCodeTooManyArgs.WithArgs("ENV")
|
||||
return errTooManyArguments("ENV")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -99,7 +98,7 @@ func env(b *Builder, args []string, attributes map[string]bool, original string)
|
|||
// Sets the maintainer metadata.
|
||||
func maintainer(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) != 1 {
|
||||
return derr.ErrorCodeExactlyOneArg.WithArgs("MAINTAINER")
|
||||
return errExactlyOneArgument("MAINTAINER")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -116,11 +115,11 @@ func maintainer(b *Builder, args []string, attributes map[string]bool, original
|
|||
//
|
||||
func label(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) == 0 {
|
||||
return derr.ErrorCodeAtLeastOneArg.WithArgs("LABEL")
|
||||
return errAtLeastOneArgument("LABEL")
|
||||
}
|
||||
if len(args)%2 != 0 {
|
||||
// should never get here, but just in case
|
||||
return derr.ErrorCodeTooManyArgs.WithArgs("LABEL")
|
||||
return errTooManyArguments("LABEL")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -152,7 +151,7 @@ func label(b *Builder, args []string, attributes map[string]bool, original strin
|
|||
//
|
||||
func add(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) < 2 {
|
||||
return derr.ErrorCodeAtLeastTwoArgs.WithArgs("ADD")
|
||||
return errAtLeastOneArgument("ADD")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -168,7 +167,7 @@ func add(b *Builder, args []string, attributes map[string]bool, original string)
|
|||
//
|
||||
func dispatchCopy(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) < 2 {
|
||||
return derr.ErrorCodeAtLeastTwoArgs.WithArgs("COPY")
|
||||
return errAtLeastOneArgument("COPY")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -184,7 +183,7 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, origina
|
|||
//
|
||||
func from(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) != 1 {
|
||||
return derr.ErrorCodeExactlyOneArg.WithArgs("FROM")
|
||||
return errExactlyOneArgument("FROM")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -233,7 +232,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
|
|||
//
|
||||
func onbuild(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) == 0 {
|
||||
return derr.ErrorCodeAtLeastOneArg.WithArgs("ONBUILD")
|
||||
return errAtLeastOneArgument("ONBUILD")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -243,9 +242,9 @@ func onbuild(b *Builder, args []string, attributes map[string]bool, original str
|
|||
triggerInstruction := strings.ToUpper(strings.TrimSpace(args[0]))
|
||||
switch triggerInstruction {
|
||||
case "ONBUILD":
|
||||
return derr.ErrorCodeChainOnBuild
|
||||
return fmt.Errorf("Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed")
|
||||
case "MAINTAINER", "FROM":
|
||||
return derr.ErrorCodeBadOnBuildCmd.WithArgs(triggerInstruction)
|
||||
return fmt.Errorf("%s isn't allowed as an ONBUILD trigger", triggerInstruction)
|
||||
}
|
||||
|
||||
original = regexp.MustCompile(`(?i)^\s*ONBUILD\s*`).ReplaceAllString(original, "")
|
||||
|
@ -260,7 +259,7 @@ func onbuild(b *Builder, args []string, attributes map[string]bool, original str
|
|||
//
|
||||
func workdir(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) != 1 {
|
||||
return derr.ErrorCodeExactlyOneArg.WithArgs("WORKDIR")
|
||||
return errExactlyOneArgument("WORKDIR")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -293,7 +292,7 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str
|
|||
//
|
||||
func run(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if b.image == "" && !b.noBaseImage {
|
||||
return derr.ErrorCodeMissingFrom
|
||||
return fmt.Errorf("Please provide a source image with `from` prior to run")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -491,7 +490,7 @@ func expose(b *Builder, args []string, attributes map[string]bool, original stri
|
|||
portsTab := args
|
||||
|
||||
if len(args) == 0 {
|
||||
return derr.ErrorCodeAtLeastOneArg.WithArgs("EXPOSE")
|
||||
return errAtLeastOneArgument("EXPOSE")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -530,7 +529,7 @@ func expose(b *Builder, args []string, attributes map[string]bool, original stri
|
|||
//
|
||||
func user(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) != 1 {
|
||||
return derr.ErrorCodeExactlyOneArg.WithArgs("USER")
|
||||
return errExactlyOneArgument("USER")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -547,7 +546,7 @@ func user(b *Builder, args []string, attributes map[string]bool, original string
|
|||
//
|
||||
func volume(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) == 0 {
|
||||
return derr.ErrorCodeAtLeastOneArg.WithArgs("VOLUME")
|
||||
return errAtLeastOneArgument("VOLUME")
|
||||
}
|
||||
|
||||
if err := b.flags.Parse(); err != nil {
|
||||
|
@ -560,7 +559,7 @@ func volume(b *Builder, args []string, attributes map[string]bool, original stri
|
|||
for _, v := range args {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
return derr.ErrorCodeVolumeEmpty
|
||||
return fmt.Errorf("Volume specified can not be an empty string")
|
||||
}
|
||||
b.runConfig.Volumes[v] = struct{}{}
|
||||
}
|
||||
|
@ -631,3 +630,15 @@ func arg(b *Builder, args []string, attributes map[string]bool, original string)
|
|||
|
||||
return b.commit("", b.runConfig.Cmd, fmt.Sprintf("ARG %s", arg))
|
||||
}
|
||||
|
||||
func errAtLeastOneArgument(command string) error {
|
||||
return fmt.Errorf("%s requires at least one argument", command)
|
||||
}
|
||||
|
||||
func errExactlyOneArgument(command string) error {
|
||||
return fmt.Errorf("%s requires exactly one argument", command)
|
||||
}
|
||||
|
||||
func errTooManyArguments(command string) error {
|
||||
return fmt.Errorf("Bad input to %s, too many arguments", command)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
|
@ -199,7 +198,7 @@ func (container *Container) SetupWorkingDirectory() error {
|
|||
if err := system.MkdirAll(pth, 0755); err != nil {
|
||||
pthInfo, err2 := os.Stat(pth)
|
||||
if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
|
||||
return derr.ErrorCodeNotADir.WithArgs(container.Config.WorkingDir)
|
||||
return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -277,13 +276,6 @@ func (container *Container) ConfigPath() (string, error) {
|
|||
return container.GetRootResourcePath(configFileName)
|
||||
}
|
||||
|
||||
func validateID(id string) error {
|
||||
if id == "" {
|
||||
return derr.ErrorCodeEmptyID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns true if the container exposes a certain port
|
||||
func (container *Container) exposes(p nat.Port) bool {
|
||||
_, exists := container.Config.ExposedPorts[p]
|
||||
|
@ -307,7 +299,7 @@ func (container *Container) GetLogConfig(defaultConfig containertypes.LogConfig)
|
|||
func (container *Container) StartLogger(cfg containertypes.LogConfig) (logger.Logger, error) {
|
||||
c, err := logger.GetLogDriver(cfg.Type)
|
||||
if err != nil {
|
||||
return nil, derr.ErrorCodeLoggingFactory.WithArgs(err)
|
||||
return nil, fmt.Errorf("Failed to get logging factory: %v", err)
|
||||
}
|
||||
ctx := logger.Context{
|
||||
Config: cfg.Config,
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/pkg/symlink"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
|
@ -34,6 +33,11 @@ import (
|
|||
// DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container
|
||||
const DefaultSHMSize int64 = 67108864
|
||||
|
||||
var (
|
||||
errInvalidEndpoint = fmt.Errorf("invalid endpoint while building port map info")
|
||||
errInvalidNetwork = fmt.Errorf("invalid network settings while building port map info")
|
||||
)
|
||||
|
||||
// Container holds the fields specific to unixen implementations.
|
||||
// See CommonContainer for standard fields common to all containers.
|
||||
type Container struct {
|
||||
|
@ -116,12 +120,12 @@ func (container *Container) GetEndpointInNetwork(n libnetwork.Network) (libnetwo
|
|||
|
||||
func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint) error {
|
||||
if ep == nil {
|
||||
return derr.ErrorCodeEmptyEndpoint
|
||||
return errInvalidEndpoint
|
||||
}
|
||||
|
||||
networkSettings := container.NetworkSettings
|
||||
if networkSettings == nil {
|
||||
return derr.ErrorCodeEmptyNetwork
|
||||
return errInvalidNetwork
|
||||
}
|
||||
|
||||
if len(networkSettings.Ports) == 0 {
|
||||
|
@ -151,7 +155,7 @@ func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
|
|||
for _, tp := range exposedPorts {
|
||||
natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
|
||||
if err != nil {
|
||||
return pm, derr.ErrorCodeParsingPort.WithArgs(tp.Port, err)
|
||||
return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err)
|
||||
}
|
||||
pm[natPort] = nil
|
||||
}
|
||||
|
@ -195,12 +199,12 @@ func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
|
|||
// BuildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint.
|
||||
func (container *Container) BuildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint) error {
|
||||
if ep == nil {
|
||||
return derr.ErrorCodeEmptyEndpoint
|
||||
return errInvalidEndpoint
|
||||
}
|
||||
|
||||
networkSettings := container.NetworkSettings
|
||||
if networkSettings == nil {
|
||||
return derr.ErrorCodeEmptyNetwork
|
||||
return errInvalidNetwork
|
||||
}
|
||||
|
||||
epInfo := ep.Info()
|
||||
|
@ -377,7 +381,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
|
|||
portStart, portEnd, err = newP.Range()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, derr.ErrorCodeHostPort.WithArgs(binding[i].HostPort, err)
|
||||
return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
|
||||
}
|
||||
pbCopy.HostPort = uint16(portStart)
|
||||
pbCopy.HostPortEnd = uint16(portEnd)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
@ -10,10 +11,8 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
)
|
||||
|
||||
|
@ -190,7 +189,7 @@ func (m *containerMonitor) start() error {
|
|||
if m.container.RestartCount == 0 {
|
||||
m.container.ExitCode = 127
|
||||
m.resetContainer(false)
|
||||
return derr.ErrorCodeCmdNotFound
|
||||
return fmt.Errorf("Container command not found or does not exist.")
|
||||
}
|
||||
}
|
||||
// set to 126 for container cmd can't be invoked errors
|
||||
|
@ -198,7 +197,7 @@ func (m *containerMonitor) start() error {
|
|||
if m.container.RestartCount == 0 {
|
||||
m.container.ExitCode = 126
|
||||
m.resetContainer(false)
|
||||
return derr.ErrorCodeCmdCouldNotBeInvoked
|
||||
return fmt.Errorf("Container command could not be invoked.")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +205,7 @@ func (m *containerMonitor) start() error {
|
|||
m.container.ExitCode = -1
|
||||
m.resetContainer(false)
|
||||
|
||||
return derr.ErrorCodeCantStart.WithArgs(m.container.ID, utils.GetErrorMessage(err))
|
||||
return fmt.Errorf("Cannot start container %s: %v", m.container.ID, err)
|
||||
}
|
||||
|
||||
logrus.Errorf("Error running container: %s", err)
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
|
@ -113,7 +112,7 @@ func wait(waitChan <-chan struct{}, timeout time.Duration) error {
|
|||
}
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
return derr.ErrorCodeTimedOut.WithArgs(timeout)
|
||||
return fmt.Errorf("Timed out: %v", timeout)
|
||||
case <-waitChan:
|
||||
return nil
|
||||
}
|
||||
|
@ -256,14 +255,15 @@ func (s *State) IsRestarting() bool {
|
|||
}
|
||||
|
||||
// SetRemovalInProgress sets the container state as being removed.
|
||||
func (s *State) SetRemovalInProgress() error {
|
||||
// It returns true if the container was already in that state.
|
||||
func (s *State) SetRemovalInProgress() bool {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
if s.RemovalInProgress {
|
||||
return derr.ErrorCodeAlreadyRemoving
|
||||
return true
|
||||
}
|
||||
s.RemovalInProgress = true
|
||||
return nil
|
||||
return false
|
||||
}
|
||||
|
||||
// ResetRemovalInProgress make the RemovalInProgress state to false.
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
)
|
||||
|
||||
|
@ -17,10 +17,11 @@ import (
|
|||
func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerAttachConfig) error {
|
||||
container, err := daemon.GetContainer(prefixOrName)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName)
|
||||
return err
|
||||
}
|
||||
if container.IsPaused() {
|
||||
return derr.ErrorCodePausedContainer.WithArgs(prefixOrName)
|
||||
err := fmt.Errorf("Container %s is paused. Unpause the container before attach", prefixOrName)
|
||||
return errors.NewRequestConflictError(err)
|
||||
}
|
||||
|
||||
inStream, outStream, errStream, err := c.GetStreams()
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/docker/docker/daemon/links"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/fileutils"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
|
@ -45,7 +45,7 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
|
|||
|
||||
for linkAlias, child := range children {
|
||||
if !child.IsRunning() {
|
||||
return nil, derr.ErrorCodeLinkNotRunning.WithArgs(child.Name, linkAlias)
|
||||
return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
|
||||
}
|
||||
|
||||
childBridgeSettings := child.NetworkSettings.Networks["bridge"]
|
||||
|
@ -509,7 +509,7 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error {
|
|||
|
||||
sb, err := ctrl.SandboxByID(sid)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeNoSandbox.WithArgs(sid, err)
|
||||
return fmt.Errorf("error locating sandbox id %s: %v", sid, err)
|
||||
}
|
||||
|
||||
// Find if container is connected to the default bridge network
|
||||
|
@ -532,11 +532,11 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error {
|
|||
|
||||
options, err := daemon.buildSandboxOptions(container, n)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeNetworkUpdate.WithArgs(err)
|
||||
return fmt.Errorf("Update network failed: %v", err)
|
||||
}
|
||||
|
||||
if err := sb.Refresh(options...); err != nil {
|
||||
return derr.ErrorCodeNetworkRefresh.WithArgs(sid, err)
|
||||
return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -730,7 +730,7 @@ func (daemon *Daemon) updateNetworkConfig(container *container.Container, idOrNa
|
|||
func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error {
|
||||
if !container.Running {
|
||||
if container.RemovalInProgress || container.Dead {
|
||||
return derr.ErrorCodeRemovalContainer.WithArgs(container.ID)
|
||||
return errRemovalContainer(container.ID)
|
||||
}
|
||||
if _, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, true); err != nil {
|
||||
return err
|
||||
|
@ -810,7 +810,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
|
|||
}
|
||||
|
||||
if err := container.UpdateJoinInfo(n, ep); err != nil {
|
||||
return derr.ErrorCodeJoinInfo.WithArgs(err)
|
||||
return fmt.Errorf("Updating join info failed: %v", err)
|
||||
}
|
||||
|
||||
daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
|
||||
|
@ -833,7 +833,7 @@ func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n li
|
|||
}
|
||||
if !container.Running {
|
||||
if container.RemovalInProgress || container.Dead {
|
||||
return derr.ErrorCodeRemovalContainer.WithArgs(container.ID)
|
||||
return errRemovalContainer(container.ID)
|
||||
}
|
||||
if _, ok := container.NetworkSettings.Networks[n.Name()]; ok {
|
||||
delete(container.NetworkSettings.Networks, n.Name())
|
||||
|
@ -950,7 +950,7 @@ func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error
|
|||
search := libnetwork.SandboxContainerWalker(&sandbox, containerID)
|
||||
daemon.netController.WalkSandboxes(search)
|
||||
if sandbox == nil {
|
||||
return derr.ErrorCodeNoSandbox.WithArgs(containerID, "no sandbox found")
|
||||
return fmt.Errorf("error locating sandbox id %s: no sandbox found", containerID)
|
||||
}
|
||||
|
||||
return sandbox.SetKey(path)
|
||||
|
@ -963,10 +963,10 @@ func (daemon *Daemon) getIpcContainer(container *container.Container) (*containe
|
|||
return nil, err
|
||||
}
|
||||
if !c.IsRunning() {
|
||||
return nil, derr.ErrorCodeIPCRunning.WithArgs(containerID)
|
||||
return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
|
||||
}
|
||||
if c.IsRestarting() {
|
||||
return nil, derr.ErrorCodeContainerRestarting.WithArgs(containerID)
|
||||
return nil, errContainerIsRestarting(container.ID)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
@ -977,13 +977,14 @@ func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID st
|
|||
return nil, err
|
||||
}
|
||||
if containerID == nc.ID {
|
||||
return nil, derr.ErrorCodeJoinSelf
|
||||
return nil, fmt.Errorf("cannot join own network")
|
||||
}
|
||||
if !nc.IsRunning() {
|
||||
return nil, derr.ErrorCodeJoinRunning.WithArgs(connectedContainerID)
|
||||
err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID)
|
||||
return nil, errors.NewRequestConflictError(err)
|
||||
}
|
||||
if nc.IsRestarting() {
|
||||
return nil, derr.ErrorCodeContainerRestarting.WithArgs(connectedContainerID)
|
||||
return nil, errContainerIsRestarting(connectedContainerID)
|
||||
}
|
||||
return nc, nil
|
||||
}
|
||||
|
@ -1141,7 +1142,7 @@ func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*con
|
|||
return devs, nil
|
||||
}
|
||||
|
||||
return devs, derr.ErrorCodeDeviceInfo.WithArgs(deviceMapping.PathOnHost, err)
|
||||
return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
|
||||
}
|
||||
|
||||
func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
|
||||
|
@ -1172,3 +1173,7 @@ func isLinkable(child *container.Container) bool {
|
|||
_, ok := child.NetworkSettings.Networks["bridge"]
|
||||
return ok
|
||||
}
|
||||
|
||||
func errRemovalContainer(containerID string) error {
|
||||
return fmt.Errorf("Container %s is marked for removal and cannot be connected or disconnected to the network", containerID)
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/docker/docker/daemon/execdriver/windows"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/layer"
|
||||
networktypes "github.com/docker/engine-api/types/network"
|
||||
"github.com/docker/libnetwork"
|
||||
|
@ -64,7 +64,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
|
|||
}
|
||||
}
|
||||
default:
|
||||
return derr.ErrorCodeInvalidNetworkMode.WithArgs(c.HostConfig.NetworkMode)
|
||||
return fmt.Errorf("invalid network mode: %s", c.HostConfig.NetworkMode)
|
||||
}
|
||||
|
||||
// TODO Windows. More resource controls to be implemented later.
|
||||
|
@ -88,7 +88,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
|
|||
var layerPaths []string
|
||||
img, err := daemon.imageStore.Get(c.ImageID)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeGetGraph.WithArgs(c.ImageID, err)
|
||||
return fmt.Errorf("Failed to graph.Get on ImageID %s - %s", c.ImageID, err)
|
||||
}
|
||||
|
||||
if img.RootFS != nil && img.RootFS.Type == "layers+base" {
|
||||
|
@ -97,7 +97,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
|
|||
img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i]
|
||||
path, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID())
|
||||
if err != nil {
|
||||
return derr.ErrorCodeGetLayer.WithArgs(err)
|
||||
return fmt.Errorf("Failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.layerStore, img.RootFS.ChainID(), err)
|
||||
}
|
||||
// Reverse order, expecting parent most first
|
||||
layerPaths = append([]string{path}, layerPaths...)
|
||||
|
@ -106,7 +106,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
|
|||
|
||||
m, err := c.RWLayer.Metadata()
|
||||
if err != nil {
|
||||
return derr.ErrorCodeGetLayerMetadata.WithArgs(err)
|
||||
return fmt.Errorf("Failed to get layer metadata - %s", err)
|
||||
}
|
||||
layerFolder := m["dir"]
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
|
@ -18,7 +19,7 @@ import (
|
|||
// ContainerCreate creates a container.
|
||||
func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types.ContainerCreateResponse, error) {
|
||||
if params.Config == nil {
|
||||
return types.ContainerCreateResponse{}, derr.ErrorCodeEmptyConfig
|
||||
return types.ContainerCreateResponse{}, fmt.Errorf("Config cannot be empty in order to create a container")
|
||||
}
|
||||
|
||||
warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false)
|
||||
|
@ -174,7 +175,7 @@ func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]stri
|
|||
v, err := daemon.volumes.Create(name, driverName, opts)
|
||||
if err != nil {
|
||||
if volumestore.IsNameConflict(err) {
|
||||
return nil, derr.ErrorVolumeNameTaken.WithArgs(name)
|
||||
return nil, fmt.Errorf("A volume named %s already exists. Choose a different volume name.", name)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
containertypes "github.com/docker/engine-api/types/container"
|
||||
"github.com/opencontainers/runc/libcontainer/label"
|
||||
|
@ -41,7 +41,7 @@ func (daemon *Daemon) createContainerPlatformSpecificSettings(container *contain
|
|||
|
||||
stat, err := os.Stat(path)
|
||||
if err == nil && !stat.IsDir() {
|
||||
return derr.ErrorCodeMountOverFile.WithArgs(path)
|
||||
return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
|
||||
}
|
||||
|
||||
v, err := daemon.volumes.CreateWithRef(name, hostConfig.VolumeDriver, container.ID, nil)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -15,6 +14,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/docker/docker/daemon/exec"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
"github.com/docker/docker/daemon/execdriver/execdrivers"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/engine-api/types"
|
||||
containertypes "github.com/docker/engine-api/types/container"
|
||||
eventtypes "github.com/docker/engine-api/types/events"
|
||||
|
@ -43,7 +44,6 @@ import (
|
|||
dmetadata "github.com/docker/docker/distribution/metadata"
|
||||
"github.com/docker/docker/distribution/xfer"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/image/tarexport"
|
||||
"github.com/docker/docker/layer"
|
||||
|
@ -90,7 +90,7 @@ var (
|
|||
validContainerNameChars = utils.RestrictedNameChars
|
||||
validContainerNamePattern = utils.RestrictedNamePattern
|
||||
|
||||
errSystemNotSupported = errors.New("The Docker daemon is not supported on this platform.")
|
||||
errSystemNotSupported = fmt.Errorf("The Docker daemon is not supported on this platform.")
|
||||
)
|
||||
|
||||
// ErrImageDoesNotExist is error returned when no image can be found for a reference.
|
||||
|
@ -157,7 +157,8 @@ func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, e
|
|||
if indexError != nil {
|
||||
// When truncindex defines an error type, use that instead
|
||||
if indexError == truncindex.ErrNotExist {
|
||||
return nil, derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName)
|
||||
err := fmt.Errorf("No such container: %s", prefixOrName)
|
||||
return nil, errors.NewRequestNotFoundError(err)
|
||||
}
|
||||
return nil, indexError
|
||||
}
|
||||
|
@ -1211,7 +1212,7 @@ func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) {
|
|||
|
||||
if !h.EmptyLayer {
|
||||
if len(img.RootFS.DiffIDs) <= layerCounter {
|
||||
return nil, errors.New("too many non-empty layers in History section")
|
||||
return nil, fmt.Errorf("too many non-empty layers in History section")
|
||||
}
|
||||
|
||||
rootFS.Append(img.RootFS.DiffIDs[layerCounter])
|
||||
|
@ -1499,7 +1500,8 @@ func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingCo
|
|||
for k := range nwConfig.EndpointsConfig {
|
||||
l = append(l, k)
|
||||
}
|
||||
return derr.ErrorCodeMultipleNetworkConnect.WithArgs(fmt.Sprintf("%v", l))
|
||||
err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
||||
return errors.NewBadRequestError(err)
|
||||
}
|
||||
|
||||
func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
|
||||
|
@ -1671,7 +1673,7 @@ func convertLnNetworkStats(name string, stats *lntypes.InterfaceStatistics) *lib
|
|||
|
||||
func validateID(id string) error {
|
||||
if id == "" {
|
||||
return derr.ErrorCodeEmptyID
|
||||
return fmt.Errorf("Invalid empty id")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
|
@ -312,17 +311,17 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
|
|||
}
|
||||
cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus)
|
||||
if err != nil {
|
||||
return warnings, derr.ErrorCodeInvalidCpusetCpus.WithArgs(resources.CpusetCpus)
|
||||
return warnings, fmt.Errorf("Invalid value %s for cpuset cpus.", resources.CpusetCpus)
|
||||
}
|
||||
if !cpusAvailable {
|
||||
return warnings, derr.ErrorCodeNotAvailableCpusetCpus.WithArgs(resources.CpusetCpus, sysInfo.Cpus)
|
||||
return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s.", resources.CpusetCpus, sysInfo.Cpus)
|
||||
}
|
||||
memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems)
|
||||
if err != nil {
|
||||
return warnings, derr.ErrorCodeInvalidCpusetMems.WithArgs(resources.CpusetMems)
|
||||
return warnings, fmt.Errorf("Invalid value %s for cpuset mems.", resources.CpusetMems)
|
||||
}
|
||||
if !memsAvailable {
|
||||
return warnings, derr.ErrorCodeNotAvailableCpusetMems.WithArgs(resources.CpusetMems, sysInfo.Mems)
|
||||
return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s.", resources.CpusetMems, sysInfo.Mems)
|
||||
}
|
||||
|
||||
// blkio subsystem checks and adjustments
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/layer"
|
||||
volumestore "github.com/docker/docker/volume/store"
|
||||
"github.com/docker/engine-api/types"
|
||||
|
@ -25,12 +25,8 @@ func (daemon *Daemon) ContainerRm(name string, config *types.ContainerRmConfig)
|
|||
}
|
||||
|
||||
// Container state RemovalInProgress should be used to avoid races.
|
||||
if err = container.SetRemovalInProgress(); err != nil {
|
||||
if err == derr.ErrorCodeAlreadyRemoving {
|
||||
// do not fail when the removal is in progress started by other request.
|
||||
return nil
|
||||
}
|
||||
return derr.ErrorCodeRmState.WithArgs(container.ID, err)
|
||||
if inProgress := container.SetRemovalInProgress(); inProgress {
|
||||
return nil
|
||||
}
|
||||
defer container.ResetRemovalInProgress()
|
||||
|
||||
|
@ -84,10 +80,11 @@ func (daemon *Daemon) rmLink(container *container.Container, name string) error
|
|||
func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemove bool) (err error) {
|
||||
if container.IsRunning() {
|
||||
if !forceRemove {
|
||||
return derr.ErrorCodeRmRunning.WithArgs(container.ID)
|
||||
err := fmt.Errorf("You cannot remove a running container %s. Stop the container before attempting removal or use -f", container.ID)
|
||||
return errors.NewRequestConflictError(err)
|
||||
}
|
||||
if err := daemon.Kill(container); err != nil {
|
||||
return derr.ErrorCodeRmFailed.WithArgs(container.ID, err)
|
||||
return fmt.Errorf("Could not kill running container %s, cannot remove - %v", container.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,17 +120,17 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
|
|||
}()
|
||||
|
||||
if err = os.RemoveAll(container.Root); err != nil {
|
||||
return derr.ErrorCodeRmFS.WithArgs(container.ID, err)
|
||||
return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err)
|
||||
}
|
||||
|
||||
metadata, err := daemon.layerStore.ReleaseRWLayer(container.RWLayer)
|
||||
layer.LogReleaseMetadata(metadata)
|
||||
if err != nil && err != layer.ErrMountDoesNotExist {
|
||||
return derr.ErrorCodeRmDriverFS.WithArgs(daemon.GraphDriverName(), container.ID, err)
|
||||
return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.GraphDriverName(), container.ID, err)
|
||||
}
|
||||
|
||||
if err = daemon.execDriver.Clean(container.ID); err != nil {
|
||||
return derr.ErrorCodeRmExecDriver.WithArgs(container.ID, err)
|
||||
return fmt.Errorf("Unable to remove execdriver data for %s: %s", container.ID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -149,9 +146,10 @@ func (daemon *Daemon) VolumeRm(name string) error {
|
|||
|
||||
if err := daemon.volumes.Remove(v); err != nil {
|
||||
if volumestore.IsInUse(err) {
|
||||
return derr.ErrorCodeRmVolumeInUse.WithArgs(err)
|
||||
err := fmt.Errorf("Unable to remove volume, volume still in use: %v", err)
|
||||
return errors.NewRequestConflictError(err)
|
||||
}
|
||||
return derr.ErrorCodeRmVolume.WithArgs(name, err)
|
||||
return fmt.Errorf("Error while removing volume %s: %v", name, err)
|
||||
}
|
||||
daemon.LogVolumeEvent(v.Name(), "destroy", map[string]string{"driver": v.DriverName()})
|
||||
return nil
|
||||
|
|
|
@ -32,9 +32,7 @@ func TestContainerDoubleDelete(t *testing.T) {
|
|||
daemon.containers.Add(container.ID, container)
|
||||
|
||||
// Mark the container as having a delete in progress
|
||||
if err := container.SetRemovalInProgress(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
container.SetRemovalInProgress()
|
||||
|
||||
// Try to remove the container when it's start is removalInProgress.
|
||||
// It should ignore the container and not return an error.
|
||||
|
|
|
@ -1,26 +1,57 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/reference"
|
||||
)
|
||||
|
||||
func (d *Daemon) imageNotExistToErrcode(err error) error {
|
||||
if dne, isDNE := err.(ErrImageDoesNotExist); isDNE {
|
||||
if strings.Contains(dne.RefOrID, "@") {
|
||||
return derr.ErrorCodeNoSuchImageHash.WithArgs(dne.RefOrID)
|
||||
e := fmt.Errorf("No such image: %s", dne.RefOrID)
|
||||
return errors.NewRequestNotFoundError(e)
|
||||
}
|
||||
tag := reference.DefaultTag
|
||||
ref, err := reference.ParseNamed(dne.RefOrID)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeNoSuchImageTag.WithArgs(dne.RefOrID, tag)
|
||||
e := fmt.Errorf("No such image: %s:%s", dne.RefOrID, tag)
|
||||
return errors.NewRequestNotFoundError(e)
|
||||
}
|
||||
if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
|
||||
tag = tagged.Tag()
|
||||
}
|
||||
return derr.ErrorCodeNoSuchImageTag.WithArgs(ref.Name(), tag)
|
||||
e := fmt.Errorf("No such image: %s:%s", ref.Name(), tag)
|
||||
return errors.NewRequestNotFoundError(e)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type errNotRunning struct {
|
||||
containerID string
|
||||
}
|
||||
|
||||
func (e errNotRunning) Error() string {
|
||||
return fmt.Sprintf("Container %s is not running", e.containerID)
|
||||
}
|
||||
|
||||
func (e errNotRunning) ContainerIsRunning() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func errContainerIsRestarting(containerID string) error {
|
||||
err := fmt.Errorf("Container %s is restarting, wait until the container is running", containerID)
|
||||
return errors.NewRequestConflictError(err)
|
||||
}
|
||||
|
||||
func errExecNotFound(id string) error {
|
||||
err := fmt.Errorf("No such exec instance '%s' found in daemon", id)
|
||||
return errors.NewRequestNotFoundError(err)
|
||||
}
|
||||
|
||||
func errExecPaused(id string) error {
|
||||
err := fmt.Errorf("Container %s is paused, unpause the container before exec", id)
|
||||
return errors.NewRequestConflictError(err)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -9,7 +10,7 @@ import (
|
|||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/exec"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/pools"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
|
@ -47,19 +48,19 @@ func (d *Daemon) getExecConfig(name string) (*exec.Config, error) {
|
|||
if ec != nil {
|
||||
if container := d.containers.Get(ec.ContainerID); container != nil {
|
||||
if !container.IsRunning() {
|
||||
return nil, derr.ErrorCodeContainerNotRunning.WithArgs(container.ID, container.State.String())
|
||||
return nil, fmt.Errorf("Container %s is not running: %s", container.ID, container.State.String())
|
||||
}
|
||||
if container.IsPaused() {
|
||||
return nil, derr.ErrorCodeExecPaused.WithArgs(container.ID)
|
||||
return nil, errExecPaused(container.ID)
|
||||
}
|
||||
if container.IsRestarting() {
|
||||
return nil, derr.ErrorCodeContainerRestarting.WithArgs(container.ID)
|
||||
return nil, errContainerIsRestarting(container.ID)
|
||||
}
|
||||
return ec, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, derr.ErrorCodeNoExecID.WithArgs(name)
|
||||
return nil, errExecNotFound(name)
|
||||
}
|
||||
|
||||
func (d *Daemon) unregisterExecCommand(container *container.Container, execConfig *exec.Config) {
|
||||
|
@ -74,13 +75,13 @@ func (d *Daemon) getActiveContainer(name string) (*container.Container, error) {
|
|||
}
|
||||
|
||||
if !container.IsRunning() {
|
||||
return nil, derr.ErrorCodeNotRunning.WithArgs(name)
|
||||
return nil, errNotRunning{container.ID}
|
||||
}
|
||||
if container.IsPaused() {
|
||||
return nil, derr.ErrorCodeExecPaused.WithArgs(name)
|
||||
return nil, errExecPaused(name)
|
||||
}
|
||||
if container.IsRestarting() {
|
||||
return nil, derr.ErrorCodeContainerRestarting.WithArgs(name)
|
||||
return nil, errContainerIsRestarting(container.ID)
|
||||
}
|
||||
return container, nil
|
||||
}
|
||||
|
@ -137,18 +138,19 @@ func (d *Daemon) ContainerExecStart(name string, stdin io.ReadCloser, stdout io.
|
|||
|
||||
ec, err := d.getExecConfig(name)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeNoExecID.WithArgs(name)
|
||||
return errExecNotFound(name)
|
||||
}
|
||||
|
||||
ec.Lock()
|
||||
if ec.ExitCode != nil {
|
||||
ec.Unlock()
|
||||
return derr.ErrorCodeExecExited.WithArgs(ec.ID)
|
||||
err := fmt.Errorf("Error: Exec command %s has already run", ec.ID)
|
||||
return errors.NewRequestConflictError(err)
|
||||
}
|
||||
|
||||
if ec.Running {
|
||||
ec.Unlock()
|
||||
return derr.ErrorCodeExecRunning.WithArgs(ec.ID)
|
||||
return fmt.Errorf("Error: Exec command %s is already running", ec.ID)
|
||||
}
|
||||
ec.Running = true
|
||||
ec.Unlock()
|
||||
|
@ -194,12 +196,12 @@ func (d *Daemon) ContainerExecStart(name string, stdin io.ReadCloser, stdout io.
|
|||
select {
|
||||
case err := <-attachErr:
|
||||
if err != nil {
|
||||
return derr.ErrorCodeExecAttach.WithArgs(err)
|
||||
return fmt.Errorf("attach failed with error: %v", err)
|
||||
}
|
||||
return nil
|
||||
case err := <-execErr:
|
||||
if aErr := <-attachErr; aErr != nil && err == nil {
|
||||
return derr.ErrorCodeExecAttach.WithArgs(aErr)
|
||||
return fmt.Errorf("attach failed with error: %v", aErr)
|
||||
}
|
||||
if err == nil {
|
||||
return nil
|
||||
|
@ -207,9 +209,9 @@ func (d *Daemon) ContainerExecStart(name string, stdin io.ReadCloser, stdout io.
|
|||
|
||||
// Maybe the container stopped while we were trying to exec
|
||||
if !c.IsRunning() {
|
||||
return derr.ErrorCodeExecContainerStopped
|
||||
return fmt.Errorf("container stopped while running exec: %s", c.ID)
|
||||
}
|
||||
return derr.ErrorCodeExecCantRun.WithArgs(ec.ID, c.ID, err)
|
||||
return fmt.Errorf("Cannot run exec command %s in container %s: %s", ec.ID, c.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package exec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/runconfig"
|
||||
)
|
||||
|
@ -116,7 +116,7 @@ func (c *Config) Resize(h, w int) error {
|
|||
select {
|
||||
case <-c.waitStart:
|
||||
case <-time.After(time.Second):
|
||||
return derr.ErrorCodeExecResize.WithArgs(c.ID)
|
||||
return fmt.Errorf("Exec %s is not running, so it can not be resized.", c.ID)
|
||||
}
|
||||
return c.ProcessConfig.Terminal.Resize(h, w)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"syscall"
|
||||
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/profiles/seccomp"
|
||||
|
||||
|
@ -430,7 +429,7 @@ func (d *Driver) setupMounts(container *configs.Config, c *execdriver.Command) e
|
|||
for _, m := range c.Mounts {
|
||||
for _, cm := range container.Mounts {
|
||||
if cm.Destination == m.Destination {
|
||||
return derr.ErrorCodeMountDup.WithArgs(m.Destination)
|
||||
return fmt.Errorf("Duplicate mount point '%s'", m.Destination)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
)
|
||||
|
@ -19,13 +19,13 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
|
|||
|
||||
data, err := daemon.containerExport(container)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeExportFailed.WithArgs(name, err)
|
||||
return fmt.Errorf("Error exporting container %s: %v", name, err)
|
||||
}
|
||||
defer data.Close()
|
||||
|
||||
// Stream the entire contents of the container (basically a volatile snapshot)
|
||||
if _, err := io.Copy(out, data); err != nil {
|
||||
return derr.ErrorCodeExportFailed.WithArgs(name, err)
|
||||
return fmt.Errorf("Error exporting container %s: %v", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/reference"
|
||||
|
@ -82,7 +82,8 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
|
|||
// this image would remain "dangling" and since
|
||||
// we really want to avoid that the client must
|
||||
// explicitly force its removal.
|
||||
return nil, derr.ErrorCodeImgDelUsed.WithArgs(imageRef, stringid.TruncateID(container.ID), stringid.TruncateID(imgID.String()))
|
||||
err := fmt.Errorf("conflict: unable to remove repository reference %q (must force) - container %s is using its referenced image %s", imageRef, stringid.TruncateID(container.ID), stringid.TruncateID(imgID.String()))
|
||||
return nil, errors.NewRequestConflictError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
)
|
||||
|
||||
|
@ -45,11 +44,11 @@ func (daemon *Daemon) killWithSignal(container *container.Container, sig int) er
|
|||
|
||||
// We could unpause the container for them rather than returning this error
|
||||
if container.Paused {
|
||||
return derr.ErrorCodeUnpauseContainer.WithArgs(container.ID)
|
||||
return fmt.Errorf("Container %s is paused. Unpause the container before stopping", container.ID)
|
||||
}
|
||||
|
||||
if !container.Running {
|
||||
return derr.ErrorCodeNotRunning.WithArgs(container.ID)
|
||||
return errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
container.ExitOnNext()
|
||||
|
@ -62,7 +61,7 @@ func (daemon *Daemon) killWithSignal(container *container.Container, sig int) er
|
|||
}
|
||||
|
||||
if err := daemon.kill(container, sig); err != nil {
|
||||
return derr.ErrorCodeCantKill.WithArgs(container.ID, err)
|
||||
return fmt.Errorf("Cannot kill container %s: %s", container.ID, err)
|
||||
}
|
||||
|
||||
attributes := map[string]string{
|
||||
|
@ -75,7 +74,7 @@ func (daemon *Daemon) killWithSignal(container *container.Container, sig int) er
|
|||
// Kill forcefully terminates a container.
|
||||
func (daemon *Daemon) Kill(container *container.Container) error {
|
||||
if !container.IsRunning() {
|
||||
return derr.ErrorCodeNotRunning.WithArgs(container.ID)
|
||||
return errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
// 1. Send SIGKILL
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -10,7 +11,6 @@ import (
|
|||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
timetypes "github.com/docker/engine-api/types/time"
|
||||
|
@ -21,11 +21,11 @@ import (
|
|||
func (daemon *Daemon) ContainerLogs(containerName string, config *backend.ContainerLogsConfig, started chan struct{}) error {
|
||||
container, err := daemon.GetContainer(containerName)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
|
||||
return err
|
||||
}
|
||||
|
||||
if !(config.ShowStdout || config.ShowStderr) {
|
||||
return derr.ErrorCodeNeedStream
|
||||
return fmt.Errorf("You must choose at least one stream")
|
||||
}
|
||||
|
||||
cLog, err := daemon.getLogger(container)
|
||||
|
@ -122,7 +122,7 @@ func (daemon *Daemon) StartLogging(container *container.Container) error {
|
|||
}
|
||||
l, err := container.StartLogger(cfg)
|
||||
if err != nil {
|
||||
return derr.ErrorCodeInitLogger.WithArgs(err)
|
||||
return fmt.Errorf("Failed to initialize logging driver: %v", err)
|
||||
}
|
||||
|
||||
copier := logger.NewCopier(container.ID, map[string]io.Reader{"stdout": container.StdoutPipe(), "stderr": container.StderrPipe()}, l)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
volumestore "github.com/docker/docker/volume/store"
|
||||
)
|
||||
|
||||
|
@ -42,7 +42,7 @@ func (daemon *Daemon) removeMountPoints(container *container.Container, rm bool)
|
|||
}
|
||||
}
|
||||
if len(rmErrors) > 0 {
|
||||
return derr.ErrorCodeRemovingVolume.WithArgs(strings.Join(rmErrors, "\n"))
|
||||
return fmt.Errorf("Error removing volumes:\n%v", strings.Join(rmErrors, "\n"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,9 +3,10 @@ package daemon
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/engine-api/types/network"
|
||||
"github.com/docker/libnetwork"
|
||||
|
@ -191,7 +192,8 @@ func (daemon *Daemon) DeleteNetwork(networkID string) error {
|
|||
}
|
||||
|
||||
if runconfig.IsPreDefinedNetwork(nw.Name()) {
|
||||
return derr.ErrorCodeCantDeletePredefinedNetwork.WithArgs(nw.Name())
|
||||
err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
|
||||
return errors.NewErrorWithStatusCode(err, http.StatusForbidden)
|
||||
}
|
||||
|
||||
if err := nw.Delete(); err != nil {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
)
|
||||
|
||||
// ContainerPause pauses a container
|
||||
|
@ -27,21 +28,21 @@ func (daemon *Daemon) containerPause(container *container.Container) error {
|
|||
|
||||
// We cannot Pause the container which is not running
|
||||
if !container.Running {
|
||||
return derr.ErrorCodeNotRunning.WithArgs(container.ID)
|
||||
return errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
// We cannot Pause the container which is already paused
|
||||
if container.Paused {
|
||||
return derr.ErrorCodeAlreadyPaused.WithArgs(container.ID)
|
||||
return fmt.Errorf("Container %s is already paused", container.ID)
|
||||
}
|
||||
|
||||
// We cannot Pause the container which is restarting
|
||||
if container.Restarting {
|
||||
return derr.ErrorCodeContainerRestarting.WithArgs(container.ID)
|
||||
return errContainerIsRestarting(container.ID)
|
||||
}
|
||||
|
||||
if err := daemon.execDriver.Pause(container.Command); err != nil {
|
||||
return derr.ErrorCodeCantPause.WithArgs(container.ID, err)
|
||||
return fmt.Errorf("Cannot pause container %s: %s", container.ID, err)
|
||||
}
|
||||
container.Paused = true
|
||||
daemon.LogContainerEvent(container, "pause")
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/libnetwork"
|
||||
)
|
||||
|
||||
|
@ -18,7 +18,7 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error {
|
|||
)
|
||||
|
||||
if oldName == "" || newName == "" {
|
||||
return derr.ErrorCodeEmptyRename
|
||||
return fmt.Errorf("Neither old nor new names may be empty")
|
||||
}
|
||||
|
||||
container, err := daemon.GetContainer(oldName)
|
||||
|
@ -31,7 +31,7 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error {
|
|||
container.Lock()
|
||||
defer container.Unlock()
|
||||
if newName, err = daemon.reserveName(container.ID, newName); err != nil {
|
||||
return derr.ErrorCodeRenameTaken.WithArgs(err)
|
||||
return fmt.Errorf("Error when allocating new name: %v", err)
|
||||
}
|
||||
|
||||
container.Name = newName
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
)
|
||||
import "fmt"
|
||||
|
||||
// ContainerResize changes the size of the TTY of the process running
|
||||
// in the container with the given name to the given height and width.
|
||||
|
@ -15,7 +11,7 @@ func (daemon *Daemon) ContainerResize(name string, height, width int) error {
|
|||
}
|
||||
|
||||
if !container.IsRunning() {
|
||||
return derr.ErrorCodeNotRunning.WithArgs(container.ID)
|
||||
return errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
if err = container.Resize(height, width); err == nil {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
)
|
||||
|
||||
// ContainerRestart stops and starts a container. It attempts to
|
||||
|
@ -17,7 +18,7 @@ func (daemon *Daemon) ContainerRestart(name string, seconds int) error {
|
|||
return err
|
||||
}
|
||||
if err := daemon.containerRestart(container, seconds); err != nil {
|
||||
return derr.ErrorCodeCantRestart.WithArgs(name, err)
|
||||
return fmt.Errorf("Cannot restart container %s: %v", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ package daemon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/runconfig"
|
||||
containertypes "github.com/docker/engine-api/types/container"
|
||||
)
|
||||
|
@ -19,11 +20,12 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
|
|||
}
|
||||
|
||||
if container.IsPaused() {
|
||||
return derr.ErrorCodeStartPaused
|
||||
return fmt.Errorf("Cannot start a paused container, try unpause instead.")
|
||||
}
|
||||
|
||||
if container.IsRunning() {
|
||||
return derr.ErrorCodeAlreadyStarted
|
||||
err := fmt.Errorf("Container already started")
|
||||
return errors.NewErrorWithStatusCode(err, http.StatusNotModified)
|
||||
}
|
||||
|
||||
// Windows does not have the backwards compatibility issue here.
|
||||
|
@ -52,7 +54,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
|
|||
}
|
||||
} else {
|
||||
if hostConfig != nil {
|
||||
return derr.ErrorCodeHostConfigStart
|
||||
return fmt.Errorf("Supplying a hostconfig on start is not supported. It should be supplied on create")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +90,7 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error)
|
|||
}
|
||||
|
||||
if container.RemovalInProgress || container.Dead {
|
||||
return derr.ErrorCodeContainerBeingRemoved
|
||||
return fmt.Errorf("Container is marked for removal and cannot be started.")
|
||||
}
|
||||
|
||||
// if we encounter an error during start we need to ensure that any other
|
||||
|
|
|
@ -4,6 +4,7 @@ package daemon
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -13,7 +14,6 @@ import (
|
|||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/pubsub"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
)
|
||||
|
@ -163,13 +163,13 @@ func (s *statsCollector) getSystemCPUUsage() (uint64, error) {
|
|||
switch parts[0] {
|
||||
case "cpu":
|
||||
if len(parts) < 8 {
|
||||
return 0, derr.ErrorCodeBadCPUFields
|
||||
return 0, fmt.Errorf("invalid number of cpu fields")
|
||||
}
|
||||
var totalClockTicks uint64
|
||||
for _, i := range parts[1:8] {
|
||||
v, err := strconv.ParseUint(i, 10, 64)
|
||||
if err != nil {
|
||||
return 0, derr.ErrorCodeBadCPUInt.WithArgs(i, err)
|
||||
return 0, fmt.Errorf("Unable to convert value %s to int: %s", i, err)
|
||||
}
|
||||
totalClockTicks += v
|
||||
}
|
||||
|
@ -177,5 +177,5 @@ func (s *statsCollector) getSystemCPUUsage() (uint64, error) {
|
|||
s.clockTicksPerSecond, nil
|
||||
}
|
||||
}
|
||||
return 0, derr.ErrorCodeBadStatFormat
|
||||
return 0, fmt.Errorf("invalid stat format. Error trying to parse the '/proc/stat' file")
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/errors"
|
||||
)
|
||||
|
||||
// ContainerStop looks for the given container and terminates it,
|
||||
|
@ -20,10 +22,11 @@ func (daemon *Daemon) ContainerStop(name string, seconds int) error {
|
|||
return err
|
||||
}
|
||||
if !container.IsRunning() {
|
||||
return derr.ErrorCodeStopped.WithArgs(name)
|
||||
err := fmt.Errorf("Container %s is already stopped", name)
|
||||
return errors.NewErrorWithStatusCode(err, http.StatusNotModified)
|
||||
}
|
||||
if err := daemon.containerStop(container, seconds); err != nil {
|
||||
return derr.ErrorCodeCantStop.WithArgs(name, err)
|
||||
return fmt.Errorf("Cannot stop container %s: %v", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
|
@ -27,11 +27,11 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.Container
|
|||
}
|
||||
|
||||
if !container.IsRunning() {
|
||||
return nil, derr.ErrorCodeNotRunning.WithArgs(name)
|
||||
return nil, errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
if container.IsRestarting() {
|
||||
return nil, derr.ErrorCodeContainerRestarting.WithArgs(name)
|
||||
return nil, errContainerIsRestarting(container.ID)
|
||||
}
|
||||
pids, err := daemon.ExecutionDriver().GetPidsForContainer(container.ID)
|
||||
if err != nil {
|
||||
|
@ -40,7 +40,7 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.Container
|
|||
|
||||
output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output()
|
||||
if err != nil {
|
||||
return nil, derr.ErrorCodePSError.WithArgs(err)
|
||||
return nil, fmt.Errorf("Error running ps: %v", err)
|
||||
}
|
||||
|
||||
procList := &types.ContainerProcessList{}
|
||||
|
@ -55,7 +55,7 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.Container
|
|||
}
|
||||
}
|
||||
if pidIndex == -1 {
|
||||
return nil, derr.ErrorCodeNoPID
|
||||
return nil, fmt.Errorf("Couldn't find PID field in ps output")
|
||||
}
|
||||
|
||||
// loop through the output and extract the PID from each line
|
||||
|
@ -66,7 +66,7 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.Container
|
|||
fields := strings.Fields(line)
|
||||
p, err := strconv.Atoi(fields[pidIndex])
|
||||
if err != nil {
|
||||
return nil, derr.ErrorCodeBadPID.WithArgs(fields[pidIndex], err)
|
||||
return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
|
||||
}
|
||||
|
||||
for _, pid := range pids {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
derr "github.com/docker/docker/errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
// ContainerTop is not supported on Windows and returns an error.
|
||||
func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) {
|
||||
return nil, derr.ErrorCodeNoTop
|
||||
return nil, fmt.Errorf("Top is not supported on Windows")
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
derr "github.com/docker/docker/errors"
|
||||
)
|
||||
|
||||
// ContainerUnpause unpauses a container
|
||||
|
@ -26,16 +27,16 @@ func (daemon *Daemon) containerUnpause(container *container.Container) error {
|
|||
|
||||
// We cannot unpause the container which is not running
|
||||
if !container.Running {
|
||||
return derr.ErrorCodeNotRunning.WithArgs(container.ID)
|
||||
return errNotRunning{container.ID}
|
||||
}
|
||||
|
||||
// We cannot unpause the container which is not paused
|
||||
if !container.Paused {
|
||||
return derr.ErrorCodeNotPaused.WithArgs(container.ID)
|
||||
return fmt.Errorf("Container %s is not paused", container.ID)
|
||||
}
|
||||
|
||||
if err := daemon.execDriver.Unpause(container.Command); err != nil {
|
||||
return derr.ErrorCodeCantUnpause.WithArgs(container.ID, err)
|
||||
return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
}
|
||||
|
||||
container.Paused = false
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
)
|
||||
|
||||
|
@ -57,18 +56,16 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
|
|||
}()
|
||||
|
||||
if container.RemovalInProgress || container.Dead {
|
||||
errMsg := fmt.Errorf("Container is marked for removal and cannot be \"update\".")
|
||||
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, errMsg)
|
||||
return errCannotUpdate(container.ID, fmt.Errorf("Container is marked for removal and cannot be \"update\"."))
|
||||
}
|
||||
|
||||
if container.IsRunning() && hostConfig.KernelMemory != 0 {
|
||||
errMsg := fmt.Errorf("Can not update kernel memory to a running container, please stop it first.")
|
||||
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, errMsg)
|
||||
return errCannotUpdate(container.ID, fmt.Errorf("Can not update kernel memory to a running container, please stop it first."))
|
||||
}
|
||||
|
||||
if err := container.UpdateContainer(hostConfig); err != nil {
|
||||
restoreConfig = true
|
||||
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
|
||||
return errCannotUpdate(container.ID, err)
|
||||
}
|
||||
|
||||
// if Restart Policy changed, we need to update container monitor
|
||||
|
@ -86,7 +83,7 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
|
|||
if container.IsRunning() && !container.IsRestarting() {
|
||||
if err := daemon.execDriver.Update(container.Command); err != nil {
|
||||
restoreConfig = true
|
||||
return derr.ErrorCodeCantUpdate.WithArgs(container.ID, err.Error())
|
||||
return errCannotUpdate(container.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,3 +91,7 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func errCannotUpdate(containerID string, err error) error {
|
||||
return fmt.Errorf("Cannot update container %s: %v", containerID, err)
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package daemon
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/docker/engine-api/types"
|
||||
containertypes "github.com/docker/engine-api/types/container"
|
||||
|
@ -114,7 +114,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
|
|||
}
|
||||
|
||||
if binds[bind.Destination] {
|
||||
return derr.ErrorCodeMountDup.WithArgs(bind.Destination)
|
||||
return fmt.Errorf("Duplicate mount point '%s'", bind.Destination)
|
||||
}
|
||||
|
||||
if len(bind.Name) > 0 {
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/execdriver"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/volume"
|
||||
)
|
||||
|
||||
|
@ -27,7 +27,7 @@ func (daemon *Daemon) setupMounts(container *container.Container) ([]execdriver.
|
|||
s = mount.Volume.Path()
|
||||
}
|
||||
if s == "" {
|
||||
return nil, derr.ErrorCodeVolumeNoSourceForMount.WithArgs(mount.Name, mount.Driver, mount.Destination)
|
||||
return nil, fmt.Errorf("No source for mount name '%s' driver %q destination '%s'", mount.Name, mount.Driver, mount.Destination)
|
||||
}
|
||||
mnts = append(mnts, execdriver.Mount{
|
||||
Source: s,
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/distribution/uuid"
|
||||
apiserver "github.com/docker/docker/api/server"
|
||||
"github.com/docker/docker/api/server/router"
|
||||
"github.com/docker/docker/api/server/router/build"
|
||||
"github.com/docker/docker/api/server/router/container"
|
||||
"github.com/docker/docker/api/server/router/image"
|
||||
|
@ -396,11 +397,16 @@ func loadDaemonCliConfig(config *daemon.Config, daemonFlags *flag.FlagSet, commo
|
|||
}
|
||||
|
||||
func initRouter(s *apiserver.Server, d *daemon.Daemon) {
|
||||
s.InitRouter(utils.IsDebugEnabled(),
|
||||
routers := []router.Router{
|
||||
container.NewRouter(d),
|
||||
image.NewRouter(d),
|
||||
network.NewRouter(d),
|
||||
systemrouter.NewRouter(d),
|
||||
volume.NewRouter(d),
|
||||
build.NewRouter(dockerfile.NewBuildManager(d)))
|
||||
build.NewRouter(dockerfile.NewBuildManager(d)),
|
||||
}
|
||||
if d.NetworkControllerEnabled() {
|
||||
routers = append(routers, network.NewRouter(d))
|
||||
}
|
||||
|
||||
s.InitRouter(utils.IsDebugEnabled(), routers...)
|
||||
}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
Docker 'errors' package
|
||||
=======================
|
||||
|
||||
This package contains all of the error messages generated by the Docker
|
||||
engine that might be exposed via the Docker engine's REST API.
|
||||
|
||||
Each top-level engine package will have its own file in this directory
|
||||
so that there's a clear grouping of errors, instead of just one big
|
||||
file. The errors for each package are defined here instead of within
|
||||
their respective package structure so that Docker CLI code that may need
|
||||
to import these error definition files will not need to know or understand
|
||||
the engine's package/directory structure. In other words, all they should
|
||||
need to do is import `.../docker/errors` and they will automatically
|
||||
pick up all Docker engine defined errors. This also gives the engine
|
||||
developers the freedom to change the engine packaging structure (e.g. to
|
||||
CRUD packages) without worrying about breaking existing clients.
|
||||
|
||||
These errors are defined using the 'errcode' package. The `errcode` package
|
||||
allows for each error to be typed and include all information necessary to
|
||||
have further processing done on them if necessary. In particular, each error
|
||||
includes:
|
||||
|
||||
* Value - a unique string (in all caps) associated with this error.
|
||||
Typically, this string is the same name as the variable name of the error
|
||||
(w/o the `ErrorCode` text) but in all caps.
|
||||
|
||||
* Message - the human readable sentence that will be displayed for this
|
||||
error. It can contain '%s' substitutions that allows for the code generating
|
||||
the error to specify values that will be inserted in the string prior to
|
||||
being displayed to the end-user. The `WithArgs()` function can be used to
|
||||
specify the insertion strings. Note, the evaluation of the strings will be
|
||||
done at the time `WithArgs()` is called.
|
||||
|
||||
* Description - additional human readable text to further explain the
|
||||
circumstances of the error situation.
|
||||
|
||||
* HTTPStatusCode - when the error is returned back to a CLI, this value
|
||||
will be used to populate the HTTP status code. If not present the default
|
||||
value will be `StatusInternalServerError`, 500.
|
||||
|
||||
Not all errors generated within the engine's executable will be propagated
|
||||
back to the engine's API layer. For example, it is expected that errors
|
||||
generated by vendored code (under `docker/vendor`) and packaged code
|
||||
(under `docker/pkg`) will be converted into errors defined by this package.
|
||||
|
||||
When processing an errcode error, if you are looking for a particular
|
||||
error then you can do something like:
|
||||
|
||||
```
|
||||
import derr "github.com/docker/docker/errors"
|
||||
|
||||
...
|
||||
|
||||
err := someFunc()
|
||||
if err.ErrorCode() == derr.ErrorCodeNoSuchContainer {
|
||||
...
|
||||
}
|
||||
```
|
|
@ -1,93 +0,0 @@
|
|||
package errors
|
||||
|
||||
// This file contains all of the errors that can be generated from the
|
||||
// docker/builder component.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorCodeAtLeastOneArg is generated when the parser comes across a
|
||||
// Dockerfile command that doesn't have any args.
|
||||
ErrorCodeAtLeastOneArg = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "ATLEASTONEARG",
|
||||
Message: "%s requires at least one argument",
|
||||
Description: "The specified command requires at least one argument",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeExactlyOneArg is generated when the parser comes across a
|
||||
// Dockerfile command that requires exactly one arg but got less/more.
|
||||
ErrorCodeExactlyOneArg = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "EXACTLYONEARG",
|
||||
Message: "%s requires exactly one argument",
|
||||
Description: "The specified command requires exactly one argument",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeAtLeastTwoArgs is generated when the parser comes across a
|
||||
// Dockerfile command that requires at least two args but got less.
|
||||
ErrorCodeAtLeastTwoArgs = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "ATLEASTTWOARGS",
|
||||
Message: "%s requires at least two arguments",
|
||||
Description: "The specified command requires at least two arguments",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeTooManyArgs is generated when the parser comes across a
|
||||
// Dockerfile command that has more args than it should
|
||||
ErrorCodeTooManyArgs = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "TOOMANYARGS",
|
||||
Message: "Bad input to %s, too many args",
|
||||
Description: "The specified command was passed too many arguments",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeChainOnBuild is generated when the parser comes across a
|
||||
// Dockerfile command that is trying to chain ONBUILD commands.
|
||||
ErrorCodeChainOnBuild = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "CHAINONBUILD",
|
||||
Message: "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed",
|
||||
Description: "ONBUILD Dockerfile commands aren't allow on ONBUILD commands",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeBadOnBuildCmd is generated when the parser comes across a
|
||||
// an ONBUILD Dockerfile command with an invalid trigger/command.
|
||||
ErrorCodeBadOnBuildCmd = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "BADONBUILDCMD",
|
||||
Message: "%s isn't allowed as an ONBUILD trigger",
|
||||
Description: "The specified ONBUILD command isn't allowed",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeMissingFrom is generated when the Dockerfile is missing
|
||||
// a FROM command.
|
||||
ErrorCodeMissingFrom = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "MISSINGFROM",
|
||||
Message: "Please provide a source image with `from` prior to run",
|
||||
Description: "The Dockerfile is missing a FROM command",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeNotOnWindows is generated when the specified Dockerfile
|
||||
// command is not supported on Windows.
|
||||
ErrorCodeNotOnWindows = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "NOTONWINDOWS",
|
||||
Message: "%s is not supported on Windows",
|
||||
Description: "The specified Dockerfile command is not supported on Windows",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeVolumeEmpty is generated when the specified Volume string
|
||||
// is empty.
|
||||
ErrorCodeVolumeEmpty = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "VOLUMEEMPTY",
|
||||
Message: "Volume specified can not be an empty string",
|
||||
Description: "The specified volume can not be an empty string",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
)
|
1013
errors/daemon.go
1013
errors/daemon.go
File diff suppressed because it is too large
Load diff
|
@ -1,6 +0,0 @@
|
|||
package errors
|
||||
|
||||
// This file contains all of the errors that can be generated from the
|
||||
// docker engine but are not tied to any specific top-level component.
|
||||
|
||||
const errGroup = "engine"
|
41
errors/errors.go
Normal file
41
errors/errors.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package errors
|
||||
|
||||
import "net/http"
|
||||
|
||||
// apiError is an error wrapper that also
|
||||
// holds information about response status codes.
|
||||
type apiError struct {
|
||||
error
|
||||
statusCode int
|
||||
}
|
||||
|
||||
// HTTPErrorStatusCode returns a status code.
|
||||
func (e apiError) HTTPErrorStatusCode() int {
|
||||
return e.statusCode
|
||||
}
|
||||
|
||||
// NewErrorWithStatusCode allows you to associate
|
||||
// a specific HTTP Status Code to an error.
|
||||
// The Server will take that code and set
|
||||
// it as the response status.
|
||||
func NewErrorWithStatusCode(err error, code int) error {
|
||||
return apiError{err, code}
|
||||
}
|
||||
|
||||
// NewBadRequestError creates a new API error
|
||||
// that has the 400 HTTP status code associated to it.
|
||||
func NewBadRequestError(err error) error {
|
||||
return NewErrorWithStatusCode(err, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// NewRequestNotFoundError creates a new API error
|
||||
// that has the 404 HTTP status code associated to it.
|
||||
func NewRequestNotFoundError(err error) error {
|
||||
return NewErrorWithStatusCode(err, http.StatusNotFound)
|
||||
}
|
||||
|
||||
// NewRequestConflictError creates a new API error
|
||||
// that has the 409 HTTP status code associated to it.
|
||||
func NewRequestConflictError(err error) error {
|
||||
return NewErrorWithStatusCode(err, http.StatusConflict)
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package errors
|
||||
|
||||
// This file contains all of the errors that can be generated from the
|
||||
// docker/image component.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorCodeInvalidImageID is generated when image id specified is incorrectly formatted.
|
||||
ErrorCodeInvalidImageID = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "INVALIDIMAGEID",
|
||||
Message: "image ID '%s' is invalid ",
|
||||
Description: "The specified image id is incorrectly formatted",
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
)
|
|
@ -1,45 +0,0 @@
|
|||
package errors
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorCodeNewerClientVersion is generated when a request from a client
|
||||
// specifies a higher version than the server supports.
|
||||
ErrorCodeNewerClientVersion = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "NEWERCLIENTVERSION",
|
||||
Message: "client is newer than server (client API version: %s, server API version: %s)",
|
||||
Description: "The client version is higher than the server version",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorCodeOldClientVersion is generated when a request from a client
|
||||
// specifies a version lower than the minimum version supported by the server.
|
||||
ErrorCodeOldClientVersion = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "OLDCLIENTVERSION",
|
||||
Message: "client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version",
|
||||
Description: "The client version is too old for the server",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
|
||||
// ErrorNetworkControllerNotEnabled is generated when the networking stack in not enabled
|
||||
// for certain platforms, like windows.
|
||||
ErrorNetworkControllerNotEnabled = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "NETWORK_CONTROLLER_NOT_ENABLED",
|
||||
Message: "the network controller is not enabled for this platform",
|
||||
Description: "Docker's networking stack is disabled for this platform",
|
||||
HTTPStatusCode: http.StatusNotFound,
|
||||
})
|
||||
|
||||
// ErrorCodeNoHijackConnection is generated when a request tries to attach to a container
|
||||
// but the connection to hijack is not provided.
|
||||
ErrorCodeNoHijackConnection = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "HIJACK_CONNECTION_MISSING",
|
||||
Message: "error attaching to container %s, hijack connection missing",
|
||||
Description: "The caller didn't provide a connection to hijack",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
})
|
||||
)
|
|
@ -643,7 +643,7 @@ func (s *DockerSuite) TestContainerApiCreateMultipleNetworksConfig(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusBadRequest)
|
||||
// network name order in error message is not deterministic
|
||||
c.Assert(string(b), checker.Contains, "Container cannot be connected to [")
|
||||
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")
|
||||
|
|
|
@ -463,7 +463,7 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
|
|||
dockerCmd(c, "run", "--name", "parent", "-v", volumeDir, "busybox", "true")
|
||||
dockerCmd(c, "run", "--volumes-from", "parent:rw", "busybox", "touch", fileInVol)
|
||||
|
||||
if out, _, err := dockerCmdWithError("run", "--volumes-from", "parent:bar", "busybox", "touch", fileInVol); err == nil || !strings.Contains(out, `invalid mode: "bar"`) {
|
||||
if out, _, err := dockerCmdWithError("run", "--volumes-from", "parent:bar", "busybox", "touch", fileInVol); err == nil || !strings.Contains(out, `invalid mode: bar`) {
|
||||
c.Fatalf("running --volumes-from parent:bar should have failed with invalid mode: %q", out)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
)
|
||||
|
@ -86,22 +85,3 @@ func ReplaceOrAppendEnvValues(defaults, overrides []string) []string {
|
|||
|
||||
return defaults
|
||||
}
|
||||
|
||||
// GetErrorMessage returns the human readable message associated with
|
||||
// the passed-in error. In some cases the default Error() func returns
|
||||
// something that is less than useful so based on its types this func
|
||||
// will go and get a better piece of text.
|
||||
func GetErrorMessage(err error) string {
|
||||
switch err.(type) {
|
||||
case errcode.Error:
|
||||
e, _ := err.(errcode.Error)
|
||||
return e.Message
|
||||
|
||||
case errcode.ErrorCode:
|
||||
ec, _ := err.(errcode.ErrorCode)
|
||||
return ec.Message()
|
||||
|
||||
default:
|
||||
return err.Error()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
package local
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/docker/docker/volume"
|
||||
|
@ -27,13 +25,21 @@ const (
|
|||
|
||||
var (
|
||||
// ErrNotFound is the typed error returned when the requested volume name can't be found
|
||||
ErrNotFound = errors.New("volume not found")
|
||||
ErrNotFound = fmt.Errorf("volume not found")
|
||||
// volumeNameRegex ensures the name assigned for the volume is valid.
|
||||
// This name is used to create the bind directory, so we need to avoid characters that
|
||||
// would make the path to escape the root directory.
|
||||
volumeNameRegex = utils.RestrictedVolumeNamePattern
|
||||
)
|
||||
|
||||
type validationError struct {
|
||||
error
|
||||
}
|
||||
|
||||
func (validationError) IsValidationError() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// New instantiates a new Root instance with the provided scope. Scope
|
||||
// is the base path that the Root instance uses to store its
|
||||
// volumes. The base path is created here if it does not exist.
|
||||
|
@ -142,7 +148,7 @@ func (r *Root) Remove(v volume.Volume) error {
|
|||
|
||||
lv, ok := v.(*localVolume)
|
||||
if !ok {
|
||||
return errors.New("unknown volume type")
|
||||
return fmt.Errorf("unknown volume type")
|
||||
}
|
||||
|
||||
realPath, err := filepath.EvalSymlinks(lv.path)
|
||||
|
@ -188,7 +194,7 @@ func (r *Root) Get(name string) (volume.Volume, error) {
|
|||
|
||||
func (r *Root) validateName(name string) error {
|
||||
if !volumeNameRegex.MatchString(name) {
|
||||
return derr.ErrorCodeVolumeName.WithArgs(name, utils.RestrictedNameChars)
|
||||
return validationError{fmt.Errorf("%q includes invalid characters for a local volume name, only %q are allowed", name, utils.RestrictedNameChars)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
derr "github.com/docker/docker/errors"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
)
|
||||
|
||||
|
@ -82,7 +82,7 @@ func (m *MountPoint) Setup() (string, error) {
|
|||
}
|
||||
return m.Source, nil
|
||||
}
|
||||
return "", derr.ErrorCodeMountSetup
|
||||
return "", fmt.Errorf("Unable to setup mount point, neither source nor volume defined")
|
||||
}
|
||||
|
||||
// Path returns the path of a volume in a mount point.
|
||||
|
@ -96,7 +96,7 @@ func (m *MountPoint) Path() string {
|
|||
// ParseVolumesFrom ensure that the supplied volumes-from is valid.
|
||||
func ParseVolumesFrom(spec string) (string, string, error) {
|
||||
if len(spec) == 0 {
|
||||
return "", "", derr.ErrorCodeVolumeFromBlank.WithArgs(spec)
|
||||
return "", "", fmt.Errorf("malformed volumes-from specification: %s", spec)
|
||||
}
|
||||
|
||||
specParts := strings.SplitN(spec, ":", 2)
|
||||
|
@ -106,15 +106,23 @@ func ParseVolumesFrom(spec string) (string, string, error) {
|
|||
if len(specParts) == 2 {
|
||||
mode = specParts[1]
|
||||
if !ValidMountMode(mode) {
|
||||
return "", "", derr.ErrorCodeVolumeInvalidMode.WithArgs(mode)
|
||||
return "", "", errInvalidMode(mode)
|
||||
}
|
||||
// For now don't allow propagation properties while importing
|
||||
// volumes from data container. These volumes will inherit
|
||||
// the same propagation property as of the original volume
|
||||
// in data container. This probably can be relaxed in future.
|
||||
if HasPropagation(mode) {
|
||||
return "", "", derr.ErrorCodeVolumeInvalidMode.WithArgs(mode)
|
||||
return "", "", errInvalidMode(mode)
|
||||
}
|
||||
}
|
||||
return id, mode, nil
|
||||
}
|
||||
|
||||
func errInvalidMode(mode string) error {
|
||||
return fmt.Errorf("invalid mode: %v", mode)
|
||||
}
|
||||
|
||||
func errInvalidSpec(spec string) error {
|
||||
return fmt.Errorf("Invalid volume specification: '%s'", spec)
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ func TestParseMountSpecPropagation(t *testing.T) {
|
|||
"/hostPath:/containerPath:ro,Z,rprivate",
|
||||
}
|
||||
invalid = map[string]string{
|
||||
"/path:/path:ro,rshared,rslave": `invalid mode: "ro,rshared,rslave"`,
|
||||
"/path:/path:ro,z,rshared,rslave": `invalid mode: "ro,z,rshared,rslave"`,
|
||||
"/path:/path:ro,rshared,rslave": `invalid mode: ro,rshared,rslave`,
|
||||
"/path:/path:ro,z,rshared,rslave": `invalid mode: ro,z,rshared,rslave`,
|
||||
"/path:shared": "Invalid volume specification",
|
||||
"/path:slave": "Invalid volume specification",
|
||||
"/path:private": "Invalid volume specification",
|
||||
|
|
|
@ -111,8 +111,8 @@ func TestParseMountSpec(t *testing.T) {
|
|||
"/path:ro": "Invalid volume specification",
|
||||
"/rw:rw": "Invalid volume specification",
|
||||
"path:ro": "Invalid volume specification",
|
||||
"/path:/path:sw": `invalid mode: "sw"`,
|
||||
"/path:/path:rwz": `invalid mode: "rwz"`,
|
||||
"/path:/path:sw": `invalid mode: sw`,
|
||||
"/path:/path:rwz": `invalid mode: rwz`,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
derr "github.com/docker/docker/errors"
|
||||
)
|
||||
|
||||
// read-write modes
|
||||
|
@ -47,12 +45,12 @@ func ParseMountSpec(spec, volumeDriver string) (*MountPoint, error) {
|
|||
Propagation: DefaultPropagationMode,
|
||||
}
|
||||
if strings.Count(spec, ":") > 2 {
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
|
||||
arr := strings.SplitN(spec, ":", 3)
|
||||
if arr[0] == "" {
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
|
||||
switch len(arr) {
|
||||
|
@ -63,7 +61,7 @@ func ParseMountSpec(spec, volumeDriver string) (*MountPoint, error) {
|
|||
if isValid := ValidMountMode(arr[1]); isValid {
|
||||
// Destination + Mode is not a valid volume - volumes
|
||||
// cannot include a mode. eg /foo:rw
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
// Host Source Path or Name + Destination
|
||||
mp.Source = arr[0]
|
||||
|
@ -74,23 +72,23 @@ func ParseMountSpec(spec, volumeDriver string) (*MountPoint, error) {
|
|||
mp.Destination = arr[1]
|
||||
mp.Mode = arr[2] // Mode field is used by SELinux to decide whether to apply label
|
||||
if !ValidMountMode(mp.Mode) {
|
||||
return nil, derr.ErrorCodeVolumeInvalidMode.WithArgs(mp.Mode)
|
||||
return nil, errInvalidMode(mp.Mode)
|
||||
}
|
||||
mp.RW = ReadWrite(mp.Mode)
|
||||
mp.Propagation = GetPropagation(mp.Mode)
|
||||
default:
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
|
||||
//validate the volumes destination path
|
||||
mp.Destination = filepath.Clean(mp.Destination)
|
||||
if !filepath.IsAbs(mp.Destination) {
|
||||
return nil, derr.ErrorCodeVolumeAbs.WithArgs(mp.Destination)
|
||||
return nil, fmt.Errorf("Invalid volume destination path: '%s' mount path must be absolute.", mp.Destination)
|
||||
}
|
||||
|
||||
// Destination cannot be "/"
|
||||
if mp.Destination == "/" {
|
||||
return nil, derr.ErrorCodeVolumeSlash.WithArgs(spec)
|
||||
return nil, fmt.Errorf("Invalid specification: destination can't be '/' in '%s'", spec)
|
||||
}
|
||||
|
||||
name, source := ParseVolumeSource(mp.Source)
|
||||
|
@ -106,7 +104,7 @@ func ParseMountSpec(spec, volumeDriver string) (*MountPoint, error) {
|
|||
// cleanup becomes an issue if container does not unmount
|
||||
// submounts explicitly.
|
||||
if HasPropagation(mp.Mode) {
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
} else {
|
||||
mp.Source = filepath.Clean(source)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package volume
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
derr "github.com/docker/docker/errors"
|
||||
)
|
||||
|
||||
// read-write modes
|
||||
|
@ -96,7 +96,7 @@ func ParseMountSpec(spec string, volumeDriver string) (*MountPoint, error) {
|
|||
|
||||
// Must have something back
|
||||
if len(match) == 0 {
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
|
||||
// Pull out the sub expressions from the named capture groups
|
||||
|
@ -116,7 +116,7 @@ func ParseMountSpec(spec string, volumeDriver string) (*MountPoint, error) {
|
|||
|
||||
// Volumes cannot include an explicitly supplied mode eg c:\path:rw
|
||||
if mp.Source == "" && mp.Destination != "" && matchgroups["mode"] != "" {
|
||||
return nil, derr.ErrorCodeVolumeInvalid.WithArgs(spec)
|
||||
return nil, errInvalidSpec(spec)
|
||||
}
|
||||
|
||||
// Note: No need to check if destination is absolute as it must be by
|
||||
|
@ -125,14 +125,14 @@ func ParseMountSpec(spec string, volumeDriver string) (*MountPoint, error) {
|
|||
if filepath.VolumeName(mp.Destination) == mp.Destination {
|
||||
// Ensure the destination path, if a drive letter, is not the c drive
|
||||
if strings.ToLower(mp.Destination) == "c:" {
|
||||
return nil, derr.ErrorCodeVolumeDestIsC.WithArgs(spec)
|
||||
return nil, fmt.Errorf("Destination drive letter in '%s' cannot be c:", spec)
|
||||
}
|
||||
} else {
|
||||
// So we know the destination is a path, not drive letter. Clean it up.
|
||||
mp.Destination = filepath.Clean(mp.Destination)
|
||||
// Ensure the destination path, if a path, is not the c root directory
|
||||
if strings.ToLower(mp.Destination) == `c:\` {
|
||||
return nil, derr.ErrorCodeVolumeDestIsCRoot.WithArgs(spec)
|
||||
return nil, fmt.Errorf(`Destination path in '%s' cannot be c:\`, spec)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,10 +163,10 @@ func ParseMountSpec(spec string, volumeDriver string) (*MountPoint, error) {
|
|||
var fi os.FileInfo
|
||||
var err error
|
||||
if fi, err = os.Stat(mp.Source); err != nil {
|
||||
return nil, derr.ErrorCodeVolumeSourceNotFound.WithArgs(mp.Source, err)
|
||||
return nil, fmt.Errorf("Source directory '%s' could not be found: %s", mp.Source, err)
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
return nil, derr.ErrorCodeVolumeSourceNotDirectory.WithArgs(mp.Source)
|
||||
return nil, fmt.Errorf("Source '%s' is not a directory", mp.Source)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ func IsVolumeNameValid(name string) (bool, error) {
|
|||
}
|
||||
nameExp = regexp.MustCompile(`^` + RXReservedNames + `$`)
|
||||
if nameExp.MatchString(name) {
|
||||
return false, derr.ErrorCodeVolumeNameReservedWord.WithArgs(name)
|
||||
return false, fmt.Errorf("Volume name %q cannot be a reserved word for Windows filenames", name)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue