mirror of
https://github.com/moby/moby.git
synced 2026-08-03 22:51:03 +00:00
Remove string checking in API error handling
Use strongly typed errors to set HTTP status codes. Error interfaces are defined in the api/errors package and errors returned from controllers are checked against these interfaces. Errors can be wraeped in a pkg/errors.Causer, as long as somewhere in the line of causes one of the interfaces is implemented. The special error interfaces take precedence over Causer, meaning if both Causer and one of the new error interfaces are implemented, the Causer is not traversed. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
@@ -43,6 +43,7 @@ import (
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
agentexec "github.com/docker/swarmkit/agent/exec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -55,8 +56,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidEndpoint = fmt.Errorf("invalid endpoint while building port map info")
|
||||
errInvalidNetwork = fmt.Errorf("invalid network settings while building port map info")
|
||||
errInvalidEndpoint = errors.New("invalid endpoint while building port map info")
|
||||
errInvalidNetwork = errors.New("invalid network settings while building port map info")
|
||||
)
|
||||
|
||||
// Container holds the structure defining a container object.
|
||||
@@ -274,7 +275,7 @@ func (container *Container) SetupWorkingDirectory(rootIDs idtools.IDPair) error
|
||||
if err := idtools.MkdirAllAndChownNew(pth, 0755, rootIDs); err != nil {
|
||||
pthInfo, err2 := os.Stat(pth)
|
||||
if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
|
||||
return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
|
||||
return errors.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -357,7 +358,7 @@ func (container *Container) StartLogger() (logger.Logger, error) {
|
||||
cfg := container.HostConfig.LogConfig
|
||||
initDriver, err := logger.GetLogDriver(cfg.Type)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get logging factory: %v", err)
|
||||
return nil, errors.Wrap(err, "failed to get logging factory")
|
||||
}
|
||||
info := logger.Info{
|
||||
Config: cfg.Config,
|
||||
@@ -723,18 +724,18 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
|
||||
|
||||
for _, ips := range ipam.LinkLocalIPs {
|
||||
if linkip = net.ParseIP(ips); linkip == nil && ips != "" {
|
||||
return nil, fmt.Errorf("Invalid link-local IP address:%s", ipam.LinkLocalIPs)
|
||||
return nil, errors.Errorf("Invalid link-local IP address: %s", ipam.LinkLocalIPs)
|
||||
}
|
||||
ipList = append(ipList, linkip)
|
||||
|
||||
}
|
||||
|
||||
if ip = net.ParseIP(ipam.IPv4Address); ip == nil && ipam.IPv4Address != "" {
|
||||
return nil, fmt.Errorf("Invalid IPv4 address:%s)", ipam.IPv4Address)
|
||||
return nil, errors.Errorf("Invalid IPv4 address: %s)", ipam.IPv4Address)
|
||||
}
|
||||
|
||||
if ip6 = net.ParseIP(ipam.IPv6Address); ip6 == nil && ipam.IPv6Address != "" {
|
||||
return nil, fmt.Errorf("Invalid IPv6 address:%s)", ipam.IPv6Address)
|
||||
return nil, errors.Errorf("Invalid IPv6 address: %s)", ipam.IPv6Address)
|
||||
}
|
||||
|
||||
createOptions = append(createOptions,
|
||||
@@ -838,7 +839,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
|
||||
portStart, portEnd, err = newP.Range()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
|
||||
return nil, errors.Wrapf(err, "Error parsing HostPort value (%s)", binding[i].HostPort)
|
||||
}
|
||||
pbCopy.HostPort = uint16(portStart)
|
||||
pbCopy.HostPortEnd = uint16(portEnd)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -262,6 +261,14 @@ func (container *Container) ConfigMounts() []Mount {
|
||||
return mounts
|
||||
}
|
||||
|
||||
type conflictingUpdateOptions string
|
||||
|
||||
func (e conflictingUpdateOptions) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (e conflictingUpdateOptions) Conflict() {}
|
||||
|
||||
// UpdateContainer updates configuration of a container. Callers must hold a Lock on the Container.
|
||||
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
|
||||
// update resources of container
|
||||
@@ -273,16 +280,16 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
|
||||
// once NanoCPU is already set, updating CPUPeriod/CPUQuota will be blocked, and vice versa.
|
||||
// In the following we make sure the intended update (resources) does not conflict with the existing (cResource).
|
||||
if resources.NanoCPUs > 0 && cResources.CPUPeriod > 0 {
|
||||
return fmt.Errorf("Conflicting options: Nano CPUs cannot be updated as CPU Period has already been set")
|
||||
return conflictingUpdateOptions("Conflicting options: Nano CPUs cannot be updated as CPU Period has already been set")
|
||||
}
|
||||
if resources.NanoCPUs > 0 && cResources.CPUQuota > 0 {
|
||||
return fmt.Errorf("Conflicting options: Nano CPUs cannot be updated as CPU Quota has already been set")
|
||||
return conflictingUpdateOptions("Conflicting options: Nano CPUs cannot be updated as CPU Quota has already been set")
|
||||
}
|
||||
if resources.CPUPeriod > 0 && cResources.NanoCPUs > 0 {
|
||||
return fmt.Errorf("Conflicting options: CPU Period cannot be updated as NanoCPUs has already been set")
|
||||
return conflictingUpdateOptions("Conflicting options: CPU Period cannot be updated as NanoCPUs has already been set")
|
||||
}
|
||||
if resources.CPUQuota > 0 && cResources.NanoCPUs > 0 {
|
||||
return fmt.Errorf("Conflicting options: CPU Quota cannot be updated as NanoCPUs has already been set")
|
||||
return conflictingUpdateOptions("Conflicting options: CPU Quota cannot be updated as NanoCPUs has already been set")
|
||||
}
|
||||
|
||||
if resources.BlkioWeight != 0 {
|
||||
@@ -310,7 +317,7 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
|
||||
// if memory limit smaller than already set memoryswap limit and doesn't
|
||||
// update the memoryswap limit, then error out.
|
||||
if resources.Memory > cResources.MemorySwap && resources.MemorySwap == 0 {
|
||||
return fmt.Errorf("Memory limit should be smaller than already set memoryswap limit, update the memoryswap at the same time")
|
||||
return conflictingUpdateOptions("Memory limit should be smaller than already set memoryswap limit, update the memoryswap at the same time")
|
||||
}
|
||||
cResources.Memory = resources.Memory
|
||||
}
|
||||
@@ -327,7 +334,7 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
|
||||
// update HostConfig of container
|
||||
if hostConfig.RestartPolicy.Name != "" {
|
||||
if container.HostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
|
||||
return fmt.Errorf("Restart policy cannot be updated because AutoRemove is enabled for the container")
|
||||
return conflictingUpdateOptions("Restart policy cannot be updated because AutoRemove is enabled for the container")
|
||||
}
|
||||
container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user