diff --git a/components/engine/api/client/client.go b/components/engine/api/client/client.go index 48420c44a5..7da14e2cbb 100644 --- a/components/engine/api/client/client.go +++ b/components/engine/api/client/client.go @@ -9,9 +9,9 @@ import ( "github.com/docker/docker/api/client/lib" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/runconfig" ) // apiClient is an interface that clients that talk with a docker server must implement. @@ -19,10 +19,10 @@ type apiClient interface { ClientVersion() string ContainerAttach(options types.ContainerAttachOptions) (types.HijackedResponse, error) ContainerCommit(options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) - ContainerCreate(config *runconfig.ContainerConfigWrapper, containerName string) (types.ContainerCreateResponse, error) + ContainerCreate(config *container.Config, hostConfig *container.HostConfig, containerName string) (types.ContainerCreateResponse, error) ContainerDiff(containerID string) ([]types.ContainerChange, error) - ContainerExecAttach(execID string, config runconfig.ExecConfig) (types.HijackedResponse, error) - ContainerExecCreate(config runconfig.ExecConfig) (types.ContainerExecCreateResponse, error) + ContainerExecAttach(execID string, config types.ExecConfig) (types.HijackedResponse, error) + ContainerExecCreate(config types.ExecConfig) (types.ContainerExecCreateResponse, error) ContainerExecInspect(execID string) (types.ContainerExecInspect, error) ContainerExecResize(options types.ResizeOptions) error ContainerExecStart(execID string, config types.ExecStartCheck) error diff --git a/components/engine/api/client/commit.go b/components/engine/api/client/commit.go index e7550dc27b..48678d4d8f 100644 --- a/components/engine/api/client/commit.go +++ b/components/engine/api/client/commit.go @@ -6,11 +6,11 @@ import ( "fmt" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" Cli "github.com/docker/docker/cli" "github.com/docker/docker/opts" flag "github.com/docker/docker/pkg/mflag" "github.com/docker/docker/reference" - "github.com/docker/docker/runconfig" ) // CmdCommit creates a new image from a container's changes. @@ -54,9 +54,9 @@ func (cli *DockerCli) CmdCommit(args ...string) error { } } - var config *runconfig.Config + var config *container.Config if *flConfig != "" { - config = &runconfig.Config{} + config = &container.Config{} if err := json.Unmarshal([]byte(*flConfig), config); err != nil { return err } diff --git a/components/engine/api/client/create.go b/components/engine/api/client/create.go index 0336e86f33..7a4070b0b9 100644 --- a/components/engine/api/client/create.go +++ b/components/engine/api/client/create.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/api/client/lib" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" Cli "github.com/docker/docker/cli" "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/reference" @@ -78,9 +79,7 @@ func newCIDFile(path string) (*cidFile, error) { return &cidFile{path: path, file: f}, nil } -func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (*types.ContainerCreateResponse, error) { - mergedConfig := runconfig.MergeConfigs(config, hostConfig) - +func (cli *DockerCli) createContainer(config *container.Config, hostConfig *container.HostConfig, cidfile, name string) (*types.ContainerCreateResponse, error) { var containerIDFile *cidFile if cidfile != "" { var err error @@ -108,7 +107,7 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc } //create the container - response, err := cli.client.ContainerCreate(mergedConfig, name) + response, err := cli.client.ContainerCreate(config, hostConfig, name) //if image not found try to pull it if err != nil { if lib.IsErrImageNotFound(err) { @@ -125,7 +124,7 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc } // Retry var retryErr error - response, retryErr = cli.client.ContainerCreate(mergedConfig, name) + response, retryErr = cli.client.ContainerCreate(config, hostConfig, name) if retryErr != nil { return nil, retryErr } diff --git a/components/engine/api/client/lib/container_create.go b/components/engine/api/client/lib/container_create.go index a5f24b09fc..e563d7b5a2 100644 --- a/components/engine/api/client/lib/container_create.go +++ b/components/engine/api/client/lib/container_create.go @@ -6,19 +6,29 @@ import ( "strings" "github.com/docker/docker/api/types" - "github.com/docker/docker/runconfig" + "github.com/docker/docker/api/types/container" ) +type configWrapper struct { + *container.Config + HostConfig *container.HostConfig +} + // ContainerCreate creates a new container based in the given configuration. // It can be associated with a name, but it's not mandatory. -func (cli *Client) ContainerCreate(config *runconfig.ContainerConfigWrapper, containerName string) (types.ContainerCreateResponse, error) { +func (cli *Client) ContainerCreate(config *container.Config, hostConfig *container.HostConfig, containerName string) (types.ContainerCreateResponse, error) { var response types.ContainerCreateResponse query := url.Values{} if containerName != "" { query.Set("name", containerName) } - serverResp, err := cli.post("/containers/create", query, config, nil) + body := configWrapper{ + Config: config, + HostConfig: hostConfig, + } + + serverResp, err := cli.post("/containers/create", query, body, nil) if err != nil { if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), config.Image) { return response, imageNotFoundError{config.Image} diff --git a/components/engine/api/client/lib/exec.go b/components/engine/api/client/lib/exec.go index 4b042c71f2..8bcabb1657 100644 --- a/components/engine/api/client/lib/exec.go +++ b/components/engine/api/client/lib/exec.go @@ -4,11 +4,10 @@ import ( "encoding/json" "github.com/docker/docker/api/types" - "github.com/docker/docker/runconfig" ) // ContainerExecCreate creates a new exec configuration to run an exec process. -func (cli *Client) ContainerExecCreate(config runconfig.ExecConfig) (types.ContainerExecCreateResponse, error) { +func (cli *Client) ContainerExecCreate(config types.ExecConfig) (types.ContainerExecCreateResponse, error) { var response types.ContainerExecCreateResponse resp, err := cli.post("/containers/"+config.Container+"/exec", nil, config, nil) if err != nil { @@ -30,7 +29,7 @@ func (cli *Client) ContainerExecStart(execID string, config types.ExecStartCheck // It returns a types.HijackedConnection with the hijacked connection // and the a reader to get output. It's up to the called to close // the hijacked connection by calling types.HijackedResponse.Close. -func (cli *Client) ContainerExecAttach(execID string, config runconfig.ExecConfig) (types.HijackedResponse, error) { +func (cli *Client) ContainerExecAttach(execID string, config types.ExecConfig) (types.HijackedResponse, error) { headers := map[string][]string{"Content-Type": {"application/json"}} return cli.postHijacked("/exec/"+execID+"/start", nil, config, headers) } diff --git a/components/engine/api/client/lib/image_build.go b/components/engine/api/client/lib/image_build.go index ffe8b42282..0ed5da8dc1 100644 --- a/components/engine/api/client/lib/image_build.go +++ b/components/engine/api/client/lib/image_build.go @@ -7,9 +7,10 @@ import ( "net/url" "regexp" "strconv" + "strings" "github.com/docker/docker/api/types" - "github.com/docker/docker/runconfig" + "github.com/docker/docker/api/types/container" "github.com/docker/go-units" ) @@ -72,7 +73,7 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro query.Set("pull", "1") } - if !runconfig.IsolationLevel.IsDefault(runconfig.IsolationLevel(options.Isolation)) { + if !container.IsolationLevel.IsDefault(container.IsolationLevel(options.Isolation)) { query.Set("isolation", options.Isolation) } @@ -101,7 +102,7 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro } query.Set("ulimits", string(ulimitsJSON)) - buildArgs := runconfig.ConvertKVStringsToMap(options.BuildArgs) + buildArgs := convertKVStringsToMap(options.BuildArgs) buildArgsJSON, err := json.Marshal(buildArgs) if err != nil { return query, err @@ -119,3 +120,18 @@ func getDockerOS(serverHeader string) string { } return osType } + +// convertKVStringsToMap converts ["key=value"] to {"key":"value"} +func convertKVStringsToMap(values []string) map[string]string { + result := make(map[string]string, len(values)) + for _, value := range values { + kv := strings.SplitN(value, "=", 2) + if len(kv) == 1 { + result[kv[0]] = "" + } else { + result[kv[0]] = kv[1] + } + } + + return result +} diff --git a/components/engine/api/client/port.go b/components/engine/api/client/port.go index ac673267ea..0dd3da4517 100644 --- a/components/engine/api/client/port.go +++ b/components/engine/api/client/port.go @@ -6,7 +6,7 @@ import ( Cli "github.com/docker/docker/cli" flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/nat" + "github.com/docker/go-connections/nat" ) // CmdPort lists port mappings for a container. diff --git a/components/engine/api/server/router/build/build_routes.go b/components/engine/api/server/router/build/build_routes.go index 8b1ff8fa78..9744033f76 100644 --- a/components/engine/api/server/router/build/build_routes.go +++ b/components/engine/api/server/router/build/build_routes.go @@ -14,6 +14,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/builder" "github.com/docker/docker/builder/dockerfile" "github.com/docker/docker/daemon/daemonbuilder" @@ -24,7 +25,6 @@ import ( "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/ulimit" "github.com/docker/docker/reference" - "github.com/docker/docker/runconfig" "github.com/docker/docker/utils" "golang.org/x/net/context" ) @@ -144,8 +144,8 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r * buildConfig.ShmSize = &shmSize } - if i := runconfig.IsolationLevel(r.FormValue("isolation")); i != "" { - if !runconfig.IsolationLevel.IsValid(i) { + if i := container.IsolationLevel(r.FormValue("isolation")); i != "" { + if !container.IsolationLevel.IsValid(i) { return errf(fmt.Errorf("Unsupported isolation: %q", i)) } buildConfig.Isolation = i diff --git a/components/engine/api/server/router/container/backend.go b/components/engine/api/server/router/container/backend.go index 0f2f06bfcc..fa58324f85 100644 --- a/components/engine/api/server/router/container/backend.go +++ b/components/engine/api/server/router/container/backend.go @@ -5,16 +5,16 @@ import ( "time" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/daemon" "github.com/docker/docker/daemon/exec" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/version" - "github.com/docker/docker/runconfig" ) // execBackend includes functions to implement to provide exec functionality. type execBackend interface { - ContainerExecCreate(config *runconfig.ExecConfig) (string, error) + ContainerExecCreate(config *types.ExecConfig) (string, error) ContainerExecInspect(id string) (*exec.Config, error) ContainerExecResize(name string, height, width int) error ContainerExecStart(name string, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) error @@ -39,7 +39,7 @@ type stateBackend interface { ContainerResize(name string, height, width int) error ContainerRestart(name string, seconds int) error ContainerRm(name string, config *types.ContainerRmConfig) error - ContainerStart(name string, hostConfig *runconfig.HostConfig) error + ContainerStart(name string, hostConfig *container.HostConfig) error ContainerStop(name string, seconds int) error ContainerUnpause(name string) error ContainerWait(name string, timeout time.Duration) (int, error) diff --git a/components/engine/api/server/router/container/container_routes.go b/components/engine/api/server/router/container/container_routes.go index beea7a8f25..461d784124 100644 --- a/components/engine/api/server/router/container/container_routes.go +++ b/components/engine/api/server/router/container/container_routes.go @@ -13,6 +13,7 @@ import ( "github.com/docker/distribution/registry/api/errcode" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" timetypes "github.com/docker/docker/api/types/time" "github.com/docker/docker/daemon" derr "github.com/docker/docker/errors" @@ -162,7 +163,7 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon // net/http otherwise seems to swallow any headers related to chunked encoding // including r.TransferEncoding // allow a nil body for backwards compatibility - var hostConfig *runconfig.HostConfig + var hostConfig *container.HostConfig if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) { if err := httputils.CheckForJSON(r); err != nil { return err diff --git a/components/engine/api/server/router/container/exec.go b/components/engine/api/server/router/container/exec.go index a4b1f700fa..4b54efde50 100644 --- a/components/engine/api/server/router/container/exec.go +++ b/components/engine/api/server/router/container/exec.go @@ -11,7 +11,6 @@ import ( "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/docker/runconfig" "golang.org/x/net/context" ) @@ -33,7 +32,7 @@ func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.Re } name := vars["name"] - execConfig := &runconfig.ExecConfig{} + execConfig := &types.ExecConfig{} if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil { return err } diff --git a/components/engine/api/server/router/local/image.go b/components/engine/api/server/router/local/image.go index ffd7bbb8f6..450c6dd65e 100644 --- a/components/engine/api/server/router/local/image.go +++ b/components/engine/api/server/router/local/image.go @@ -12,6 +12,7 @@ import ( "github.com/docker/distribution/digest" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/builder/dockerfile" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/ioutils" @@ -43,7 +44,7 @@ func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http. return err } if c == nil { - c = &runconfig.Config{} + c = &container.Config{} } if !s.daemon.Exists(cname) { @@ -162,8 +163,8 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r // 'err' MUST NOT be defined within this block, we need any error // generated from the download to be available to the output // stream processing below - var newConfig *runconfig.Config - newConfig, err = dockerfile.BuildFromConfig(&runconfig.Config{}, r.Form["changes"]) + var newConfig *container.Config + newConfig, err = dockerfile.BuildFromConfig(&container.Config{}, r.Form["changes"]) if err != nil { return err } diff --git a/components/engine/pkg/blkiodev/blkiodev.go b/components/engine/api/types/blkiodev/blkio.go similarity index 96% rename from components/engine/pkg/blkiodev/blkiodev.go rename to components/engine/api/types/blkiodev/blkio.go index e9a3649fce..458a9c96bb 100644 --- a/components/engine/pkg/blkiodev/blkiodev.go +++ b/components/engine/api/types/blkiodev/blkio.go @@ -1,8 +1,6 @@ package blkiodev -import ( - "fmt" -) +import "fmt" // WeightDevice is a structure that hold device:weight pair type WeightDevice struct { diff --git a/components/engine/api/types/client.go b/components/engine/api/types/client.go index 4846e502b7..4a0877f97f 100644 --- a/components/engine/api/types/client.go +++ b/components/engine/api/types/client.go @@ -5,9 +5,9 @@ import ( "io" "net" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/pkg/ulimit" - "github.com/docker/docker/runconfig" ) // ContainerAttachOptions holds parameters to attach to a container. @@ -28,7 +28,7 @@ type ContainerCommitOptions struct { Author string Changes []string Pause bool - Config *runconfig.Config + Config *container.Config } // ContainerExecInspect holds information returned by exec inspect. diff --git a/components/engine/api/types/configs.go b/components/engine/api/types/configs.go index c166ac7e51..ba8f0e006f 100644 --- a/components/engine/api/types/configs.go +++ b/components/engine/api/types/configs.go @@ -1,18 +1,16 @@ package types +import "github.com/docker/docker/api/types/container" + // configs holds structs used for internal communication between the // frontend (such as an http server) and the backend (such as the // docker daemon). -import ( - "github.com/docker/docker/runconfig" -) - // ContainerCreateConfig is the parameter set to ContainerCreate() type ContainerCreateConfig struct { Name string - Config *runconfig.Config - HostConfig *runconfig.HostConfig + Config *container.Config + HostConfig *container.HostConfig AdjustCPUShares bool } @@ -33,5 +31,19 @@ type ContainerCommitConfig struct { Comment string // merge container config into commit config before commit MergeConfigs bool - Config *runconfig.Config + Config *container.Config +} + +// ExecConfig is a small subset of the Config struct that hold the configuration +// for the exec feature of docker. +type ExecConfig struct { + User string // User that will run the command + Privileged bool // Is the container in privileged mode + Tty bool // Attach standard streams to a tty. + Container string // Name of the container (to execute in) + AttachStdin bool // Attach the standard input, makes possible user interaction + AttachStderr bool // Attach the standard output + AttachStdout bool // Attach the standard error + Detach bool // Execute in detach mode + Cmd []string // Execution commands and args } diff --git a/components/engine/api/types/container/config.go b/components/engine/api/types/container/config.go new file mode 100644 index 0000000000..5459b5dbaf --- /dev/null +++ b/components/engine/api/types/container/config.go @@ -0,0 +1,38 @@ +package container + +import ( + "github.com/docker/docker/api/types/strslice" + "github.com/docker/go-connections/nat" +) + +// Config contains the configuration data about a container. +// It should hold only portable information about the container. +// Here, "portable" means "independent from the host we are running on". +// Non-portable information *should* appear in HostConfig. +// All fields added to this struct must be marked `omitempty` to keep getting +// predictable hashes from the old `v1Compatibility` configuration. +type Config struct { + Hostname string // Hostname + Domainname string // Domainname + User string // User that will run the command(s) inside the container + AttachStdin bool // Attach the standard input, makes possible user interaction + AttachStdout bool // Attach the standard output + AttachStderr bool // Attach the standard error + ExposedPorts map[nat.Port]struct{} `json:",omitempty"` // List of exposed ports + PublishService string `json:",omitempty"` // Name of the network service exposed by the container + Tty bool // Attach standard streams to a tty, including stdin if it is not closed. + OpenStdin bool // Open stdin + StdinOnce bool // If true, close stdin after the 1 attached client disconnects. + Env []string // List of environment variable to set in the container + Cmd *strslice.StrSlice // Command to run when starting the container + ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific) + Image string // Name of the image as it was passed by the operator (eg. could be symbolic) + Volumes map[string]struct{} // List of volumes (mounts) used for the container + WorkingDir string // Current directory (PWD) in the command will be launched + Entrypoint *strslice.StrSlice // Entrypoint to run when starting the container + NetworkDisabled bool `json:",omitempty"` // Is network disabled + MacAddress string `json:",omitempty"` // Mac Address of the container + OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile + Labels map[string]string // List of labels set to this container + StopSignal string `json:",omitempty"` // Signal to stop a container +} diff --git a/components/engine/api/types/container/host_config.go b/components/engine/api/types/container/host_config.go new file mode 100644 index 0000000000..e1d4ea4095 --- /dev/null +++ b/components/engine/api/types/container/host_config.go @@ -0,0 +1,228 @@ +package container + +import ( + "strings" + + "github.com/docker/docker/api/types/blkiodev" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/docker/pkg/ulimit" + "github.com/docker/go-connections/nat" +) + +// NetworkMode represents the container network stack. +type NetworkMode string + +// IsolationLevel represents the isolation level of a container. The supported +// values are platform specific +type IsolationLevel string + +// IsDefault indicates the default isolation level of a container. On Linux this +// is the native driver. On Windows, this is a Windows Server Container. +func (i IsolationLevel) IsDefault() bool { + return strings.ToLower(string(i)) == "default" || string(i) == "" +} + +// IpcMode represents the container ipc stack. +type IpcMode string + +// IsPrivate indicates whether the container uses it's private ipc stack. +func (n IpcMode) IsPrivate() bool { + return !(n.IsHost() || n.IsContainer()) +} + +// IsHost indicates whether the container uses the host's ipc stack. +func (n IpcMode) IsHost() bool { + return n == "host" +} + +// IsContainer indicates whether the container uses a container's ipc stack. +func (n IpcMode) IsContainer() bool { + parts := strings.SplitN(string(n), ":", 2) + return len(parts) > 1 && parts[0] == "container" +} + +// Valid indicates whether the ipc stack is valid. +func (n IpcMode) Valid() bool { + parts := strings.Split(string(n), ":") + switch mode := parts[0]; mode { + case "", "host": + case "container": + if len(parts) != 2 || parts[1] == "" { + return false + } + default: + return false + } + return true +} + +// Container returns the name of the container ipc stack is going to be used. +func (n IpcMode) Container() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + +// UTSMode represents the UTS namespace of the container. +type UTSMode string + +// IsPrivate indicates whether the container uses it's private UTS namespace. +func (n UTSMode) IsPrivate() bool { + return !(n.IsHost()) +} + +// IsHost indicates whether the container uses the host's UTS namespace. +func (n UTSMode) IsHost() bool { + return n == "host" +} + +// Valid indicates whether the UTS namespace is valid. +func (n UTSMode) Valid() bool { + parts := strings.Split(string(n), ":") + switch mode := parts[0]; mode { + case "", "host": + default: + return false + } + return true +} + +// PidMode represents the pid stack of the container. +type PidMode string + +// IsPrivate indicates whether the container uses it's private pid stack. +func (n PidMode) IsPrivate() bool { + return !(n.IsHost()) +} + +// IsHost indicates whether the container uses the host's pid stack. +func (n PidMode) IsHost() bool { + return n == "host" +} + +// Valid indicates whether the pid stack is valid. +func (n PidMode) Valid() bool { + parts := strings.Split(string(n), ":") + switch mode := parts[0]; mode { + case "", "host": + default: + return false + } + return true +} + +// DeviceMapping represents the device mapping between the host and the container. +type DeviceMapping struct { + PathOnHost string + PathInContainer string + CgroupPermissions string +} + +// RestartPolicy represents the restart policies of the container. +type RestartPolicy struct { + Name string + MaximumRetryCount int +} + +// IsNone indicates whether the container has the "no" restart policy. +// This means the container will not automatically restart when exiting. +func (rp *RestartPolicy) IsNone() bool { + return rp.Name == "no" +} + +// IsAlways indicates whether the container has the "always" restart policy. +// This means the container will automatically restart regardless of the exit status. +func (rp *RestartPolicy) IsAlways() bool { + return rp.Name == "always" +} + +// IsOnFailure indicates whether the container has the "on-failure" restart policy. +// This means the contain will automatically restart of exiting with a non-zero exit status. +func (rp *RestartPolicy) IsOnFailure() bool { + return rp.Name == "on-failure" +} + +// IsUnlessStopped indicates whether the container has the +// "unless-stopped" restart policy. This means the container will +// automatically restart unless user has put it to stopped state. +func (rp *RestartPolicy) IsUnlessStopped() bool { + return rp.Name == "unless-stopped" +} + +// LogConfig represents the logging configuration of the container. +type LogConfig struct { + Type string + Config map[string]string +} + +// Resources contains container's resources (cgroups config, ulimits...) +type Resources struct { + // Applicable to all platforms + CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers) + + // Applicable to UNIX platforms + CgroupParent string // Parent cgroup. + BlkioWeight uint16 // Block IO weight (relative weight vs. other containers) + BlkioWeightDevice []*blkiodev.WeightDevice + BlkioDeviceReadBps []*blkiodev.ThrottleDevice + BlkioDeviceWriteBps []*blkiodev.ThrottleDevice + BlkioDeviceReadIOps []*blkiodev.ThrottleDevice + BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice + CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period + CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota + CpusetCpus string // CpusetCpus 0-2, 0,1 + CpusetMems string // CpusetMems 0-2, 0,1 + Devices []DeviceMapping // List of devices to map inside the container + KernelMemory int64 // Kernel memory limit (in bytes) + Memory int64 // Memory limit (in bytes) + MemoryReservation int64 // Memory soft limit (in bytes) + MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap + MemorySwappiness *int64 // Tuning container memory swappiness behaviour + OomKillDisable bool // Whether to disable OOM Killer or not + Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container +} + +// HostConfig the non-portable Config structure of a container. +// Here, "non-portable" means "dependent of the host we are running on". +// Portable information *should* appear in Config. +type HostConfig struct { + // Applicable to all platforms + Binds []string // List of volume bindings for this container + ContainerIDFile string // File (path) where the containerId is written + LogConfig LogConfig // Configuration of the logs for this container + NetworkMode NetworkMode // Network mode to use for the container + PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host + RestartPolicy RestartPolicy // Restart policy to be used for the container + VolumeDriver string // Name of the volume driver used to mount volumes + VolumesFrom []string // List of volumes to take from other container + + // Applicable to UNIX platforms + CapAdd *strslice.StrSlice // List of kernel capabilities to add to the container + CapDrop *strslice.StrSlice // List of kernel capabilities to remove from the container + DNS []string `json:"Dns"` // List of DNS server to lookup + DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for + DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for + ExtraHosts []string // List of extra hosts + GroupAdd []string // List of additional groups that the container process will run as + IpcMode IpcMode // IPC namespace to use for the container + Links []string // List of links (in the name:alias form) + OomScoreAdj int // Container preference for OOM-killing + OomKillDisable bool // Whether to disable OOM Killer or not + PidMode PidMode // PID namespace to use for the container + Privileged bool // Is the container in privileged mode + PublishAllPorts bool // Should docker publish all exposed port for the container + ReadonlyRootfs bool // Is the container root filesystem in read-only + SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. + Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container + UTSMode UTSMode // UTS namespace to use for the container + ShmSize *int64 // Total shm memory usage + + // Applicable to Windows + ConsoleSize [2]int // Initial console size + Isolation IsolationLevel // Isolation level of the container (eg default, hyperv) + + // Contains container's resources (cgroups, ulimits) + Resources +} diff --git a/components/engine/api/types/container/hostconfig_unix.go b/components/engine/api/types/container/hostconfig_unix.go new file mode 100644 index 0000000000..775e903f1c --- /dev/null +++ b/components/engine/api/types/container/hostconfig_unix.go @@ -0,0 +1,87 @@ +// +build !windows + +package container + +import "strings" + +// IsValid indicates is an isolation level is valid +func (i IsolationLevel) IsValid() bool { + return i.IsDefault() +} + +// IsPrivate indicates whether container uses it's private network stack. +func (n NetworkMode) IsPrivate() bool { + return !(n.IsHost() || n.IsContainer()) +} + +// IsDefault indicates whether container uses the default network stack. +func (n NetworkMode) IsDefault() bool { + return n == "default" +} + +// NetworkName returns the name of the network stack. +func (n NetworkMode) NetworkName() string { + if n.IsBridge() { + return "bridge" + } else if n.IsHost() { + return "host" + } else if n.IsContainer() { + return "container" + } else if n.IsNone() { + return "none" + } else if n.IsDefault() { + return "default" + } else if n.IsUserDefined() { + return n.UserDefined() + } + return "" +} + +// IsBridge indicates whether container uses the bridge network stack +func (n NetworkMode) IsBridge() bool { + return n == "bridge" +} + +// IsHost indicates whether container uses the host network stack. +func (n NetworkMode) IsHost() bool { + return n == "host" +} + +// IsContainer indicates whether container uses a container network stack. +func (n NetworkMode) IsContainer() bool { + parts := strings.SplitN(string(n), ":", 2) + return len(parts) > 1 && parts[0] == "container" +} + +// IsNone indicates whether container isn't using a network stack. +func (n NetworkMode) IsNone() bool { + return n == "none" +} + +// ConnectedContainer is the id of the container which network this container is connected to. +func (n NetworkMode) ConnectedContainer() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + +// IsUserDefined indicates user-created network +func (n NetworkMode) IsUserDefined() bool { + return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() +} + +// IsPreDefinedNetwork indicates if a network is predefined by the daemon +func IsPreDefinedNetwork(network string) bool { + n := NetworkMode(network) + return n.IsBridge() || n.IsHost() || n.IsNone() +} + +//UserDefined indicates user-created network +func (n NetworkMode) UserDefined() string { + if n.IsUserDefined() { + return string(n) + } + return "" +} diff --git a/components/engine/api/types/container/hostconfig_windows.go b/components/engine/api/types/container/hostconfig_windows.go new file mode 100644 index 0000000000..16267ff416 --- /dev/null +++ b/components/engine/api/types/container/hostconfig_windows.go @@ -0,0 +1,75 @@ +package container + +import ( + "fmt" + "strings" +) + +// IsDefault indicates whether container uses the default network stack. +func (n NetworkMode) IsDefault() bool { + return n == "default" +} + +// IsHyperV indicates the use of a Hyper-V partition for isolation +func (i IsolationLevel) IsHyperV() bool { + return strings.ToLower(string(i)) == "hyperv" +} + +// IsProcess indicates the use of process isolation +func (i IsolationLevel) IsProcess() bool { + return strings.ToLower(string(i)) == "process" +} + +// IsValid indicates is an isolation level is valid +func (i IsolationLevel) IsValid() bool { + return i.IsDefault() || i.IsHyperV() || i.IsProcess() +} + +// DefaultDaemonNetworkMode returns the default network stack the daemon should +// use. +func DefaultDaemonNetworkMode() NetworkMode { + return NetworkMode("default") +} + +// NetworkName returns the name of the network stack. +func (n NetworkMode) NetworkName() string { + if n.IsDefault() { + return "default" + } + return "" +} + +// IsPreDefinedNetwork indicates if a network is predefined by the daemon +func IsPreDefinedNetwork(network string) bool { + return false +} + +// ValidateNetMode ensures that the various combinations of requested +// network settings are valid. +func ValidateNetMode(c *Config, hc *HostConfig) error { + // We may not be passed a host config, such as in the case of docker commit + if hc == nil { + return nil + } + parts := strings.Split(string(hc.NetworkMode), ":") + switch mode := parts[0]; mode { + case "default", "none": + default: + return fmt.Errorf("invalid --net: %s", hc.NetworkMode) + } + return nil +} + +// ValidateIsolationLevel performs platform specific validation of the +// isolation level in the hostconfig structure. Windows supports 'default' (or +// blank), 'process', or 'hyperv'. +func ValidateIsolationLevel(hc *HostConfig) error { + // We may not be passed a host config, such as in the case of docker commit + if hc == nil { + return nil + } + if !hc.Isolation.IsValid() { + return fmt.Errorf("invalid --isolation: %q. Windows supports 'default', 'process', or 'hyperv'", hc.Isolation) + } + return nil +} diff --git a/components/engine/pkg/stringutils/strslice.go b/components/engine/api/types/strslice/strslice.go similarity index 90% rename from components/engine/pkg/stringutils/strslice.go rename to components/engine/api/types/strslice/strslice.go index dfe535edd7..9f3ee620a3 100644 --- a/components/engine/pkg/stringutils/strslice.go +++ b/components/engine/api/types/strslice/strslice.go @@ -1,4 +1,4 @@ -package stringutils +package strslice import ( "encoding/json" @@ -65,7 +65,7 @@ func (e *StrSlice) ToString() string { return strings.Join(s, " ") } -// NewStrSlice creates an StrSlice based on the specified parts (as strings). -func NewStrSlice(parts ...string) *StrSlice { +// New creates an StrSlice based on the specified parts (as strings). +func New(parts ...string) *StrSlice { return &StrSlice{parts} } diff --git a/components/engine/pkg/stringutils/strslice_test.go b/components/engine/api/types/strslice/strslice_test.go similarity index 87% rename from components/engine/pkg/stringutils/strslice_test.go rename to components/engine/api/types/strslice/strslice_test.go index a587784eb9..50955c1be2 100644 --- a/components/engine/pkg/stringutils/strslice_test.go +++ b/components/engine/api/types/strslice/strslice_test.go @@ -1,4 +1,4 @@ -package stringutils +package strslice import ( "encoding/json" @@ -93,9 +93,9 @@ func TestStrSliceUnmarshalSlice(t *testing.T) { func TestStrSliceToString(t *testing.T) { slices := map[*StrSlice]string{ - NewStrSlice(""): "", - NewStrSlice("one"): "one", - NewStrSlice("one", "two"): "one two", + New(""): "", + New("one"): "one", + New("one", "two"): "one two", } for s, expected := range slices { toString := s.ToString() @@ -108,10 +108,10 @@ func TestStrSliceToString(t *testing.T) { func TestStrSliceLen(t *testing.T) { var emptyStrSlice *StrSlice slices := map[*StrSlice]int{ - NewStrSlice(""): 1, - NewStrSlice("one"): 1, - NewStrSlice("one", "two"): 2, - emptyStrSlice: 0, + New(""): 1, + New("one"): 1, + New("one", "two"): 2, + emptyStrSlice: 0, } for s, expected := range slices { if s.Len() != expected { @@ -123,9 +123,9 @@ func TestStrSliceLen(t *testing.T) { func TestStrSliceSlice(t *testing.T) { var emptyStrSlice *StrSlice slices := map[*StrSlice][]string{ - NewStrSlice("one"): {"one"}, - NewStrSlice("one", "two"): {"one", "two"}, - emptyStrSlice: nil, + New("one"): {"one"}, + New("one", "two"): {"one", "two"}, + emptyStrSlice: nil, } for s, expected := range slices { if !reflect.DeepEqual(s.Slice(), expected) { diff --git a/components/engine/api/types/types.go b/components/engine/api/types/types.go index 3a8870cee3..9965cce118 100644 --- a/components/engine/api/types/types.go +++ b/components/engine/api/types/types.go @@ -4,11 +4,11 @@ import ( "os" "time" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/version" - "github.com/docker/docker/runconfig" + "github.com/docker/go-connections/nat" ) // ContainerCreateResponse contains the information returned to a client on the @@ -103,10 +103,10 @@ type ImageInspect struct { Comment string Created string Container string - ContainerConfig *runconfig.Config + ContainerConfig *container.Config DockerVersion string Author string - Config *runconfig.Config + Config *container.Config Architecture string Os string Size int64 @@ -283,7 +283,7 @@ type ContainerJSONBase struct { ProcessLabel string AppArmorProfile string ExecIDs []string - HostConfig *runconfig.HostConfig + HostConfig *container.HostConfig GraphDriver GraphDriverData SizeRw *int64 `json:",omitempty"` SizeRootFs *int64 `json:",omitempty"` @@ -293,7 +293,7 @@ type ContainerJSONBase struct { type ContainerJSON struct { *ContainerJSONBase Mounts []MountPoint - Config *runconfig.Config + Config *container.Config NetworkSettings *NetworkSettings } diff --git a/components/engine/api/types/versions/v1p19/types.go b/components/engine/api/types/versions/v1p19/types.go index a66aa9d5e5..dc13150545 100644 --- a/components/engine/api/types/versions/v1p19/types.go +++ b/components/engine/api/types/versions/v1p19/types.go @@ -3,9 +3,9 @@ package v1p19 import ( "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/versions/v1p20" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/runconfig" + "github.com/docker/go-connections/nat" ) // ContainerJSON is a backcompatibility struct for APIs prior to 1.20. @@ -20,7 +20,7 @@ type ContainerJSON struct { // ContainerConfig is a backcompatibility struct for APIs prior to 1.20. type ContainerConfig struct { - *runconfig.Config + *container.Config MacAddress string NetworkDisabled bool diff --git a/components/engine/api/types/versions/v1p20/types.go b/components/engine/api/types/versions/v1p20/types.go index 0facbb66ca..fa395ac1f6 100644 --- a/components/engine/api/types/versions/v1p20/types.go +++ b/components/engine/api/types/versions/v1p20/types.go @@ -3,8 +3,8 @@ package v1p20 import ( "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/runconfig" + "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" ) // ContainerJSON is a backcompatibility struct for the API 1.20 @@ -17,7 +17,7 @@ type ContainerJSON struct { // ContainerConfig is a backcompatibility struct used in ContainerJSON for the API 1.20 type ContainerConfig struct { - *runconfig.Config + *container.Config MacAddress string NetworkDisabled bool diff --git a/components/engine/builder/builder.go b/components/engine/builder/builder.go index 97e0ad092b..90ab204f8e 100644 --- a/components/engine/builder/builder.go +++ b/components/engine/builder/builder.go @@ -10,7 +10,7 @@ import ( "time" "github.com/docker/docker/api/types" - "github.com/docker/docker/runconfig" + "github.com/docker/docker/api/types/container" ) // Context represents a file system tree. @@ -113,7 +113,7 @@ type Backend interface { // Kill stops the container execution abruptly. ContainerKill(containerID string, sig uint64) error // Start starts a new container - ContainerStart(containerID string, hostConfig *runconfig.HostConfig) error + ContainerStart(containerID string, hostConfig *container.HostConfig) error // ContainerWait stops processing until the given container is stopped. ContainerWait(containerID string, timeout time.Duration) (int, error) @@ -135,5 +135,5 @@ type Backend interface { type ImageCache interface { // GetCachedImage returns a reference to a cached image whose parent equals `parent` // and runconfig equals `cfg`. A cache miss is expected to return an empty ID and a nil error. - GetCachedImage(parentID string, cfg *runconfig.Config) (imageID string, err error) + GetCachedImage(parentID string, cfg *container.Config) (imageID string, err error) } diff --git a/components/engine/builder/dockerfile/builder.go b/components/engine/builder/dockerfile/builder.go index b4f7a6a779..0db8c41880 100644 --- a/components/engine/builder/dockerfile/builder.go +++ b/components/engine/builder/dockerfile/builder.go @@ -10,11 +10,11 @@ import ( "sync" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/builder" "github.com/docker/docker/builder/dockerfile/parser" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/ulimit" - "github.com/docker/docker/runconfig" ) var validCommitCommands = map[string]bool{ @@ -52,7 +52,7 @@ type Config struct { ForceRemove bool Pull bool BuildArgs map[string]string // build-time args received in build context for expansion/substitution and commands in 'run'. - Isolation runconfig.IsolationLevel + Isolation container.IsolationLevel // resource constraints // TODO: factor out to be reused with Run ? @@ -81,7 +81,7 @@ type Builder struct { context builder.Context dockerfile *parser.Node - runConfig *runconfig.Config // runconfig for cmd, run, entrypoint etc. + runConfig *container.Config // runconfig for cmd, run, entrypoint etc. flags *BFlags tmpContainers map[string]struct{} image string // imageID @@ -114,7 +114,7 @@ func NewBuilder(config *Config, docker builder.Backend, context builder.Context, Stderr: os.Stderr, docker: docker, context: context, - runConfig: new(runconfig.Config), + runConfig: new(container.Config), tmpContainers: map[string]struct{}{}, cancelled: make(chan struct{}), id: stringid.GenerateNonCryptoID(), @@ -206,7 +206,7 @@ func (b *Builder) Cancel() { // - call parse.Parse() to get AST root from Dockerfile entries // - do build by calling builder.dispatch() to call all entries' handling routines // TODO: remove? -func BuildFromConfig(config *runconfig.Config, changes []string) (*runconfig.Config, error) { +func BuildFromConfig(config *container.Config, changes []string) (*container.Config, error) { ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n"))) if err != nil { return nil, err diff --git a/components/engine/builder/dockerfile/dispatchers.go b/components/engine/builder/dockerfile/dispatchers.go index 0f6c0b78d2..03849fcc94 100644 --- a/components/engine/builder/dockerfile/dispatchers.go +++ b/components/engine/builder/dockerfile/dispatchers.go @@ -18,14 +18,14 @@ import ( "strings" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/builder" derr "github.com/docker/docker/errors" flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/stringutils" "github.com/docker/docker/pkg/system" "github.com/docker/docker/runconfig" + "github.com/docker/go-connections/nat" ) const ( @@ -330,7 +330,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string) // stash the config environment env := b.runConfig.Env - defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd) + defer func(cmd *strslice.StrSlice) { b.runConfig.Cmd = cmd }(cmd) defer func(env []string) { b.runConfig.Env = env }(env) // derive the net build-time environment for this run. We let config @@ -373,7 +373,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string) if len(cmdBuildEnv) > 0 { sort.Strings(cmdBuildEnv) tmpEnv := append([]string{fmt.Sprintf("|%d", len(cmdBuildEnv))}, cmdBuildEnv...) - saveCmd = stringutils.NewStrSlice(append(tmpEnv, saveCmd.Slice()...)...) + saveCmd = strslice.New(append(tmpEnv, saveCmd.Slice()...)...) } b.runConfig.Cmd = saveCmd @@ -431,7 +431,7 @@ func cmd(b *Builder, args []string, attributes map[string]bool, original string) } } - b.runConfig.Cmd = stringutils.NewStrSlice(cmdSlice...) + b.runConfig.Cmd = strslice.New(cmdSlice...) if err := b.commit("", b.runConfig.Cmd, fmt.Sprintf("CMD %q", cmdSlice)); err != nil { return err @@ -462,16 +462,16 @@ func entrypoint(b *Builder, args []string, attributes map[string]bool, original switch { case attributes["json"]: // ENTRYPOINT ["echo", "hi"] - b.runConfig.Entrypoint = stringutils.NewStrSlice(parsed...) + b.runConfig.Entrypoint = strslice.New(parsed...) case len(parsed) == 0: // ENTRYPOINT [] b.runConfig.Entrypoint = nil default: // ENTRYPOINT echo hi if runtime.GOOS != "windows" { - b.runConfig.Entrypoint = stringutils.NewStrSlice("/bin/sh", "-c", parsed[0]) + b.runConfig.Entrypoint = strslice.New("/bin/sh", "-c", parsed[0]) } else { - b.runConfig.Entrypoint = stringutils.NewStrSlice("cmd", "/S", "/C", parsed[0]) + b.runConfig.Entrypoint = strslice.New("cmd", "/S", "/C", parsed[0]) } } diff --git a/components/engine/builder/dockerfile/internals.go b/components/engine/builder/dockerfile/internals.go index 2af00bfe5d..ce5f457a5e 100644 --- a/components/engine/builder/dockerfile/internals.go +++ b/components/engine/builder/dockerfile/internals.go @@ -21,6 +21,8 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/builder" "github.com/docker/docker/builder/dockerfile/parser" "github.com/docker/docker/pkg/archive" @@ -30,14 +32,12 @@ import ( "github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" "github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/tarsum" "github.com/docker/docker/pkg/urlutil" - "github.com/docker/docker/runconfig" ) -func (b *Builder) commit(id string, autoCmd *stringutils.StrSlice, comment string) error { +func (b *Builder) commit(id string, autoCmd *strslice.StrSlice, comment string) error { if b.disableCommit { return nil } @@ -48,11 +48,11 @@ func (b *Builder) commit(id string, autoCmd *stringutils.StrSlice, comment strin if id == "" { cmd := b.runConfig.Cmd if runtime.GOOS != "windows" { - b.runConfig.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", "#(nop) "+comment) + b.runConfig.Cmd = strslice.New("/bin/sh", "-c", "#(nop) "+comment) } else { - b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S /C", "REM (nop) "+comment) + b.runConfig.Cmd = strslice.New("cmd", "/S /C", "REM (nop) "+comment) } - defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd) + defer func(cmd *strslice.StrSlice) { b.runConfig.Cmd = cmd }(cmd) hit, err := b.probeCache() if err != nil { @@ -171,11 +171,11 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD cmd := b.runConfig.Cmd if runtime.GOOS != "windows" { - b.runConfig.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest)) + b.runConfig.Cmd = strslice.New("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest)) } else { - b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S", "/C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest)) + b.runConfig.Cmd = strslice.New("cmd", "/S", "/C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest)) } - defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd) + defer func(cmd *strslice.StrSlice) { b.runConfig.Cmd = cmd }(cmd) if hit, err := b.probeCache(); err != nil { return err @@ -476,7 +476,7 @@ func (b *Builder) create() (string, error) { } b.runConfig.Image = b.image - resources := runconfig.Resources{ + resources := container.Resources{ CgroupParent: b.CgroupParent, CPUShares: b.CPUShares, CPUPeriod: b.CPUPeriod, @@ -489,7 +489,7 @@ func (b *Builder) create() (string, error) { } // TODO: why not embed a hostconfig in builder? - hostConfig := &runconfig.HostConfig{ + hostConfig := &container.HostConfig{ Isolation: b.Isolation, ShmSize: b.ShmSize, Resources: resources, diff --git a/components/engine/builder/image.go b/components/engine/builder/image.go index c8d5fc15d9..4de620fae6 100644 --- a/components/engine/builder/image.go +++ b/components/engine/builder/image.go @@ -1,9 +1,9 @@ package builder -import "github.com/docker/docker/runconfig" +import "github.com/docker/docker/api/types/container" // Image represents a Docker image used by the builder. type Image interface { ID() string - Config() *runconfig.Config + Config() *container.Config } diff --git a/components/engine/container/container.go b/components/engine/container/container.go index 8285d3196e..ebe70b44ea 100644 --- a/components/engine/container/container.go +++ b/components/engine/container/container.go @@ -11,6 +11,7 @@ import ( "time" "github.com/Sirupsen/logrus" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/daemon/exec" "github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/daemon/logger" @@ -19,12 +20,12 @@ import ( derr "github.com/docker/docker/errors" "github.com/docker/docker/image" "github.com/docker/docker/layer" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/promise" "github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/symlink" "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" + "github.com/docker/go-connections/nat" "github.com/opencontainers/runc/libcontainer/label" ) @@ -43,7 +44,7 @@ type CommonContainer struct { Created time.Time Path string Args []string - Config *runconfig.Config + Config *containertypes.Config ImageID image.ID `json:"Image"` NetworkSettings *network.Settings LogPath string @@ -56,8 +57,8 @@ type CommonContainer struct { HasBeenStartedBefore bool HasBeenManuallyStopped bool // used for unless-stopped restart policy MountPoints map[string]*volume.MountPoint - HostConfig *runconfig.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable - Command *execdriver.Command `json:"-"` + HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable + Command *execdriver.Command `json:"-"` monitor *containerMonitor ExecCommands *exec.Store `json:"-"` // logDriver for closing @@ -139,7 +140,7 @@ func (container *Container) ToDiskLocking() error { // readHostConfig reads the host configuration from disk for the container. func (container *Container) readHostConfig() error { - container.HostConfig = &runconfig.HostConfig{} + container.HostConfig = &containertypes.HostConfig{} // If the hostconfig file does not exist, do not read it. // (We still have to initialize container.HostConfig, // but that's OK, since we just did that above.) @@ -261,7 +262,7 @@ func (container *Container) exposes(p nat.Port) bool { } // GetLogConfig returns the log configuration for the container. -func (container *Container) GetLogConfig(defaultConfig runconfig.LogConfig) runconfig.LogConfig { +func (container *Container) GetLogConfig(defaultConfig containertypes.LogConfig) containertypes.LogConfig { cfg := container.HostConfig.LogConfig if cfg.Type != "" || len(cfg.Config) > 0 { // container has log driver configured if cfg.Type == "" { @@ -274,7 +275,7 @@ func (container *Container) GetLogConfig(defaultConfig runconfig.LogConfig) runc } // StartLogger starts a new logger driver for the container. -func (container *Container) StartLogger(cfg runconfig.LogConfig) (logger.Logger, error) { +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) diff --git a/components/engine/container/container_unit_test.go b/components/engine/container/container_unit_test.go index abc1033168..f14dc12e97 100644 --- a/components/engine/container/container_unit_test.go +++ b/components/engine/container/container_unit_test.go @@ -3,14 +3,14 @@ package container import ( "testing" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/runconfig" ) func TestContainerStopSignal(t *testing.T) { c := &Container{ CommonContainer: CommonContainer{ - Config: &runconfig.Config{}, + Config: &container.Config{}, }, } @@ -26,7 +26,7 @@ func TestContainerStopSignal(t *testing.T) { c = &Container{ CommonContainer: CommonContainer{ - Config: &runconfig.Config{StopSignal: "SIGKILL"}, + Config: &container.Config{StopSignal: "SIGKILL"}, }, } s = c.StopSignal() diff --git a/components/engine/container/container_unix.go b/components/engine/container/container_unix.go index 1740c536c5..f775871669 100644 --- a/components/engine/container/container_unix.go +++ b/components/engine/container/container_unix.go @@ -17,11 +17,11 @@ import ( "github.com/docker/docker/daemon/execdriver" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/chrootarchive" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/symlink" "github.com/docker/docker/pkg/system" "github.com/docker/docker/utils" "github.com/docker/docker/volume" + "github.com/docker/go-connections/nat" "github.com/docker/libnetwork" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/options" diff --git a/components/engine/container/monitor.go b/components/engine/container/monitor.go index 3c29ba362e..8098f23bae 100644 --- a/components/engine/container/monitor.go +++ b/components/engine/container/monitor.go @@ -9,11 +9,11 @@ import ( "time" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/container" "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/runconfig" "github.com/docker/docker/utils" ) @@ -51,7 +51,7 @@ type containerMonitor struct { container *Container // restartPolicy is the current policy being applied to the container monitor - restartPolicy runconfig.RestartPolicy + restartPolicy container.RestartPolicy // failureCount is the number of times the container has failed to // start in a row @@ -79,7 +79,7 @@ type containerMonitor struct { // StartMonitor initializes a containerMonitor for this container with the provided supervisor and restart policy // and starts the container's process. -func (container *Container) StartMonitor(s supervisor, policy runconfig.RestartPolicy) error { +func (container *Container) StartMonitor(s supervisor, policy container.RestartPolicy) error { container.monitor = &containerMonitor{ supervisor: s, container: container, diff --git a/components/engine/daemon/config.go b/components/engine/daemon/config.go index a842bda244..b6477a6f33 100644 --- a/components/engine/daemon/config.go +++ b/components/engine/daemon/config.go @@ -1,9 +1,9 @@ package daemon import ( + "github.com/docker/docker/api/types/container" "github.com/docker/docker/opts" flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/runconfig" ) const ( @@ -27,7 +27,7 @@ type CommonConfig struct { GraphDriver string GraphOptions []string Labels []string - LogConfig runconfig.LogConfig + LogConfig container.LogConfig Mtu int Pidfile string RemappedRoot string diff --git a/components/engine/daemon/container_operations_unix.go b/components/engine/daemon/container_operations_unix.go index 18de732983..6c4f17704a 100644 --- a/components/engine/daemon/container_operations_unix.go +++ b/components/engine/daemon/container_operations_unix.go @@ -13,6 +13,7 @@ import ( "time" "github.com/Sirupsen/logrus" + containertypes "github.com/docker/docker/api/types/container" networktypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/container" "github.com/docker/docker/daemon/execdriver" @@ -460,7 +461,7 @@ func (daemon *Daemon) updateNetworkSettings(container *container.Container, n li container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)} } - if !container.HostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() { + if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } @@ -474,12 +475,12 @@ func (daemon *Daemon) updateNetworkSettings(container *container.Container, n li // Avoid duplicate config return nil } - if !runconfig.NetworkMode(sn.Type()).IsPrivate() || - !runconfig.NetworkMode(n.Type()).IsPrivate() { + if !containertypes.NetworkMode(sn.Type()).IsPrivate() || + !containertypes.NetworkMode(n.Type()).IsPrivate() { return runconfig.ErrConflictSharedNetwork } - if runconfig.NetworkMode(sn.Name()).IsNone() || - runconfig.NetworkMode(n.Name()).IsNone() { + if containertypes.NetworkMode(sn.Name()).IsNone() || + containertypes.NetworkMode(n.Name()).IsNone() { return runconfig.ErrConflictNoNetwork } } @@ -493,7 +494,7 @@ func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Contain return err } - if container.HostConfig.NetworkMode == runconfig.NetworkMode("bridge") { + if container.HostConfig.NetworkMode == containertypes.NetworkMode("bridge") { container.NetworkSettings.Bridge = daemon.configStore.Bridge.Iface } @@ -625,7 +626,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName return runconfig.ErrConflictSharedNetwork } - if runconfig.NetworkMode(idOrName).IsBridge() && + if containertypes.NetworkMode(idOrName).IsBridge() && daemon.configStore.DisableBridge { container.Config.NetworkDisabled = true return nil @@ -706,7 +707,7 @@ func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n li return derr.ErrorCodeNotRunning.WithArgs(container.ID) } - if container.HostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() { + if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } @@ -955,7 +956,7 @@ func killProcessDirectly(container *container.Container) error { return nil } -func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) { +func getDevicesFromPath(deviceMapping containertypes.DeviceMapping) (devs []*configs.Device, err error) { device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions) // if there was no error, return the device if err == nil { diff --git a/components/engine/daemon/container_operations_windows.go b/components/engine/daemon/container_operations_windows.go index 37524d31ea..ebbefa3eb4 100644 --- a/components/engine/daemon/container_operations_windows.go +++ b/components/engine/daemon/container_operations_windows.go @@ -7,6 +7,7 @@ import ( "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" "github.com/docker/libnetwork" @@ -103,6 +104,16 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro } layerFolder := m["dir"] + var hvPartition bool + // Work out the isolation (whether it is a hypervisor partition) + if c.HostConfig.Isolation.IsDefault() { + // Not specified by caller. Take daemon default + hvPartition = windows.DefaultIsolation.IsHyperV() + } else { + // Take value specified by caller + hvPartition = c.HostConfig.Isolation.IsHyperV() + } + c.Command = &execdriver.Command{ CommonCommand: execdriver.CommonCommand{ ID: c.ID, @@ -119,8 +130,9 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro LayerFolder: layerFolder, LayerPaths: layerPaths, Hostname: c.Config.Hostname, - Isolation: c.HostConfig.Isolation, + Isolation: string(c.HostConfig.Isolation), ArgsEscaped: c.Config.ArgsEscaped, + HvPartition: hvPartition, } return nil diff --git a/components/engine/daemon/create.go b/components/engine/daemon/create.go index 4767874d8c..aa3d97896e 100644 --- a/components/engine/daemon/create.go +++ b/components/engine/daemon/create.go @@ -3,12 +3,12 @@ package daemon import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" derr "github.com/docker/docker/errors" "github.com/docker/docker/image" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" "github.com/opencontainers/runc/libcontainer/label" ) @@ -25,7 +25,7 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types } if params.HostConfig == nil { - params.HostConfig = &runconfig.HostConfig{} + params.HostConfig = &containertypes.HostConfig{} } err = daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares) if err != nil { @@ -111,7 +111,7 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig) (*container.Con return container, nil } -func (daemon *Daemon) generateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) { +func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMode containertypes.PidMode) ([]string, error) { if ipcMode.IsHost() || pidMode.IsHost() { return label.DisableSecOpt(), nil } diff --git a/components/engine/daemon/create_unix.go b/components/engine/daemon/create_unix.go index 741df132b7..25548d231e 100644 --- a/components/engine/daemon/create_unix.go +++ b/components/engine/daemon/create_unix.go @@ -6,17 +6,17 @@ import ( "os" "path/filepath" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" derr "github.com/docker/docker/errors" "github.com/docker/docker/image" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" "github.com/opencontainers/runc/libcontainer/label" ) // createContainerPlatformSpecificSettings performs platform specific container create functionality -func (daemon *Daemon) createContainerPlatformSpecificSettings(container *container.Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { +func (daemon *Daemon) createContainerPlatformSpecificSettings(container *container.Container, config *containertypes.Config, hostConfig *containertypes.HostConfig, img *image.Image) error { if err := daemon.Mount(container); err != nil { return err } diff --git a/components/engine/daemon/create_windows.go b/components/engine/daemon/create_windows.go index f150fcbab8..33e54141e2 100644 --- a/components/engine/daemon/create_windows.go +++ b/components/engine/daemon/create_windows.go @@ -3,15 +3,15 @@ package daemon import ( "fmt" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" "github.com/docker/docker/image" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" ) // createContainerPlatformSpecificSettings performs platform specific container create functionality -func (daemon *Daemon) createContainerPlatformSpecificSettings(container *container.Container, config *runconfig.Config, hostConfig *runconfig.HostConfig, img *image.Image) error { +func (daemon *Daemon) createContainerPlatformSpecificSettings(container *container.Container, config *containertypes.Config, hostConfig *containertypes.HostConfig, img *image.Image) error { for spec := range config.Volumes { mp, err := volume.ParseMountSpec(spec, hostConfig.VolumeDriver) diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go index 681c1c61a2..59bff4013f 100644 --- a/components/engine/daemon/daemon.go +++ b/components/engine/daemon/daemon.go @@ -21,8 +21,10 @@ import ( "github.com/docker/distribution/digest" "github.com/docker/docker/api" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" registrytypes "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/container" "github.com/docker/docker/daemon/events" "github.com/docker/docker/daemon/exec" @@ -48,12 +50,10 @@ import ( "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/namesgenerator" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" "github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/truncindex" @@ -64,6 +64,7 @@ import ( volumedrivers "github.com/docker/docker/volume/drivers" "github.com/docker/docker/volume/local" "github.com/docker/docker/volume/store" + "github.com/docker/go-connections/nat" "github.com/docker/libnetwork" lntypes "github.com/docker/libnetwork/types" "github.com/docker/libtrust" @@ -148,7 +149,7 @@ type Daemon struct { driver graphdriver.Driver execDriver execdriver.Driver statsCollector *statsCollector - defaultLogConfig runconfig.LogConfig + defaultLogConfig containertypes.LogConfig RegistryService *registry.Service EventsService *events.Events netController libnetwork.NetworkController @@ -390,7 +391,7 @@ func (daemon *Daemon) restore() error { return nil } -func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error { +func (daemon *Daemon) mergeAndVerifyConfig(config *containertypes.Config, img *image.Image) error { if img != nil && img.Config != nil { if err := runconfig.Merge(config, img.Config); err != nil { return err @@ -472,14 +473,14 @@ func (daemon *Daemon) generateNewName(id string) (string, error) { return name, nil } -func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) { +func (daemon *Daemon) generateHostname(id string, config *containertypes.Config) { // Generate default hostname if config.Hostname == "" { config.Hostname = id[:12] } } -func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlice, configCmd *stringutils.StrSlice) (string, []string) { +func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *strslice.StrSlice, configCmd *strslice.StrSlice) (string, []string) { cmdSlice := configCmd.Slice() if configEntrypoint.Len() != 0 { eSlice := configEntrypoint.Slice() @@ -488,7 +489,7 @@ func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlic return cmdSlice[0], cmdSlice[1:] } -func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID image.ID) (*container.Container, error) { +func (daemon *Daemon) newContainer(name string, config *containertypes.Config, imgID image.ID) (*container.Container, error) { var ( id string err error @@ -507,7 +508,7 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID base.Path = entrypoint base.Args = args //FIXME: de-duplicate from config base.Config = config - base.HostConfig = &runconfig.HostConfig{} + base.HostConfig = &containertypes.HostConfig{} base.ImageID = imgID base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName} base.Name = name @@ -1366,7 +1367,7 @@ func (daemon *Daemon) GetRemappedUIDGID() (int, int) { // of the image with imgID, that had the same config when it was // created. nil is returned if a child cannot be found. An error is // returned if the parent image cannot be found. -func (daemon *Daemon) ImageGetCached(imgID image.ID, config *runconfig.Config) (*image.Image, error) { +func (daemon *Daemon) ImageGetCached(imgID image.ID, config *containertypes.Config) (*image.Image, error) { // Retrieve all images imgs := daemon.Map() @@ -1402,7 +1403,7 @@ func tempDir(rootDir string, rootUID, rootGID int) (string, error) { return tmpDir, idtools.MkdirAllAs(tmpDir, 0700, rootUID, rootGID) } -func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *runconfig.HostConfig) error { +func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *containertypes.HostConfig) error { container.Lock() if err := parseSecurityOpt(container, hostConfig); err != nil { container.Unlock() @@ -1444,7 +1445,7 @@ func setDefaultMtu(config *Config) { // verifyContainerSettings performs validation of the hostconfig and config // structures. -func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { +func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { // First perform verification of settings common across all platforms. if config != nil { diff --git a/components/engine/daemon/daemon_experimental.go b/components/engine/daemon/daemon_experimental.go index 33d3168f11..d50a8fb283 100644 --- a/components/engine/daemon/daemon_experimental.go +++ b/components/engine/daemon/daemon_experimental.go @@ -9,9 +9,9 @@ import ( "runtime" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/directory" "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/runconfig" ) func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { @@ -99,7 +99,7 @@ func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error return nil } -func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { +func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) { if hostConfig.Privileged && daemon.configStore.RemappedRoot != "" { return nil, fmt.Errorf("Privileged mode is incompatible with user namespace mappings") } diff --git a/components/engine/daemon/daemon_stub.go b/components/engine/daemon/daemon_stub.go index 8fbb0508e9..20b2263071 100644 --- a/components/engine/daemon/daemon_stub.go +++ b/components/engine/daemon/daemon_stub.go @@ -5,9 +5,9 @@ package daemon import ( "os" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/system" - "github.com/docker/docker/runconfig" ) func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { @@ -23,6 +23,6 @@ func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error return nil } -func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { +func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) { return nil, nil } diff --git a/components/engine/daemon/daemon_test.go b/components/engine/daemon/daemon_test.go index 8802d5c65c..c09191b9ce 100644 --- a/components/engine/daemon/daemon_test.go +++ b/components/engine/daemon/daemon_test.go @@ -7,10 +7,10 @@ import ( "path/filepath" "testing" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" "github.com/docker/docker/pkg/graphdb" "github.com/docker/docker/pkg/truncindex" - "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" volumedrivers "github.com/docker/docker/volume/drivers" "github.com/docker/docker/volume/local" @@ -141,7 +141,7 @@ func initDaemonWithVolumeStore(tmp string) (*Daemon, error) { func TestParseSecurityOpt(t *testing.T) { container := &container.Container{} - config := &runconfig.HostConfig{} + config := &containertypes.HostConfig{} // test apparmor config.SecurityOpt = []string{"apparmor:test_profile"} diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go old mode 100755 new mode 100644 index b30b2dafc0..f9782a183e --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/daemon/daemon_unix.go @@ -12,12 +12,13 @@ import ( "syscall" "github.com/Sirupsen/logrus" + pblkiodev "github.com/docker/docker/api/types/blkiodev" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" "github.com/docker/docker/daemon/graphdriver" derr "github.com/docker/docker/errors" "github.com/docker/docker/image" "github.com/docker/docker/layer" - pblkiodev "github.com/docker/docker/pkg/blkiodev" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/sysinfo" @@ -43,7 +44,7 @@ const ( linuxMinMemory = 4194304 ) -func getBlkioWeightDevices(config *runconfig.HostConfig) ([]*blkiodev.WeightDevice, error) { +func getBlkioWeightDevices(config *containertypes.HostConfig) ([]*blkiodev.WeightDevice, error) { var stat syscall.Stat_t var blkioWeightDevices []*blkiodev.WeightDevice @@ -58,7 +59,7 @@ func getBlkioWeightDevices(config *runconfig.HostConfig) ([]*blkiodev.WeightDevi return blkioWeightDevices, nil } -func parseSecurityOpt(container *container.Container, config *runconfig.HostConfig) error { +func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error { var ( labelOpts []string err error @@ -85,7 +86,7 @@ func parseSecurityOpt(container *container.Container, config *runconfig.HostConf return err } -func getBlkioReadIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioReadIOpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { var blkioReadIOpsDevice []*blkiodev.ThrottleDevice var stat syscall.Stat_t @@ -100,7 +101,7 @@ func getBlkioReadIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.Throttle return blkioReadIOpsDevice, nil } -func getBlkioWriteIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioWriteIOpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { var blkioWriteIOpsDevice []*blkiodev.ThrottleDevice var stat syscall.Stat_t @@ -115,7 +116,7 @@ func getBlkioWriteIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.Throttl return blkioWriteIOpsDevice, nil } -func getBlkioReadBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioReadBpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { var blkioReadBpsDevice []*blkiodev.ThrottleDevice var stat syscall.Stat_t @@ -130,7 +131,7 @@ func getBlkioReadBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleD return blkioReadBpsDevice, nil } -func getBlkioWriteBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioWriteBpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { var blkioWriteBpsDevice []*blkiodev.ThrottleDevice var stat syscall.Stat_t @@ -175,7 +176,7 @@ func checkKernel() error { // adaptContainerSettings is called during container creation to modify any // settings necessary in the HostConfig structure. -func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) error { +func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error { if adjustCPUShares && hostConfig.CPUShares > 0 { // Handle unsupported CPUShares if hostConfig.CPUShares < linuxMinCPUShares { @@ -209,7 +210,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, a return nil } -func verifyContainerResources(resources *runconfig.Resources) ([]string, error) { +func verifyContainerResources(resources *containertypes.Resources) ([]string, error) { warnings := []string{} sysInfo := sysinfo.New(true) @@ -349,7 +350,7 @@ func verifyContainerResources(resources *runconfig.Resources) ([]string, error) // verifyPlatformContainerSettings performs platform-specific validation of the // hostconfig and config structures. -func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { +func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { warnings := []string{} sysInfo := sysinfo.New(true) @@ -680,7 +681,7 @@ func setupInitLayer(initLayer string, rootUID, rootGID int) error { } // registerLinks writes the links to a file. -func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *runconfig.HostConfig) error { +func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { if hostConfig == nil || hostConfig.Links == nil { return nil } diff --git a/components/engine/daemon/daemon_unix_test.go b/components/engine/daemon/daemon_unix_test.go index 5d92782d99..083b2bd45b 100644 --- a/components/engine/daemon/daemon_unix_test.go +++ b/components/engine/daemon/daemon_unix_test.go @@ -7,7 +7,7 @@ import ( "os" "testing" - "github.com/docker/docker/runconfig" + "github.com/docker/docker/api/types/container" ) func TestAdjustCPUShares(t *testing.T) { @@ -21,8 +21,8 @@ func TestAdjustCPUShares(t *testing.T) { root: tmp, } - hostConfig := &runconfig.HostConfig{ - Resources: runconfig.Resources{CPUShares: linuxMinCPUShares - 1}, + hostConfig := &container.HostConfig{ + Resources: container.Resources{CPUShares: linuxMinCPUShares - 1}, } daemon.adaptContainerSettings(hostConfig, true) if hostConfig.CPUShares != linuxMinCPUShares { @@ -59,8 +59,8 @@ func TestAdjustCPUSharesNoAdjustment(t *testing.T) { root: tmp, } - hostConfig := &runconfig.HostConfig{ - Resources: runconfig.Resources{CPUShares: linuxMinCPUShares - 1}, + hostConfig := &container.HostConfig{ + Resources: container.Resources{CPUShares: linuxMinCPUShares - 1}, } daemon.adaptContainerSettings(hostConfig, false) if hostConfig.CPUShares != linuxMinCPUShares-1 { diff --git a/components/engine/daemon/daemon_windows.go b/components/engine/daemon/daemon_windows.go index 2735702f7e..477509c3ba 100644 --- a/components/engine/daemon/daemon_windows.go +++ b/components/engine/daemon/daemon_windows.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/Sirupsen/logrus" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/dockerversion" @@ -18,7 +19,6 @@ import ( // register the windows graph driver "github.com/docker/docker/daemon/graphdriver/windows" "github.com/docker/docker/pkg/system" - "github.com/docker/docker/runconfig" "github.com/docker/libnetwork" blkiodev "github.com/opencontainers/runc/libcontainer/configs" ) @@ -30,27 +30,27 @@ const ( windowsMaxCPUShares = 10000 ) -func getBlkioWeightDevices(config *runconfig.HostConfig) ([]*blkiodev.WeightDevice, error) { +func getBlkioWeightDevices(config *containertypes.HostConfig) ([]*blkiodev.WeightDevice, error) { return nil, nil } -func parseSecurityOpt(container *container.Container, config *runconfig.HostConfig) error { +func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error { return nil } -func getBlkioReadIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioReadIOpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { return nil, nil } -func getBlkioWriteIOpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioWriteIOpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { return nil, nil } -func getBlkioReadBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioReadBpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { return nil, nil } -func getBlkioWriteBpsDevices(config *runconfig.HostConfig) ([]*blkiodev.ThrottleDevice, error) { +func getBlkioWriteBpsDevices(config *containertypes.HostConfig) ([]*blkiodev.ThrottleDevice, error) { return nil, nil } @@ -64,7 +64,7 @@ func checkKernel() error { // adaptContainerSettings is called during container creation to modify any // settings necessary in the HostConfig structure. -func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) error { +func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error { if hostConfig == nil { return nil } @@ -82,7 +82,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, a // verifyPlatformContainerSettings performs platform-specific validation of the // hostconfig and config structures. -func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { +func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config) ([]string, error) { return nil, nil } @@ -131,7 +131,7 @@ func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkC // registerLinks sets up links between containers and writes the // configuration out for persistence. As of Windows TP4, links are not supported. -func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *runconfig.HostConfig) error { +func (daemon *Daemon) registerLinks(container *container.Container, hostConfig *containertypes.HostConfig) error { return nil } diff --git a/components/engine/daemon/daemonbuilder/builder.go b/components/engine/daemon/daemonbuilder/builder.go index ab4122994b..fec37a6a84 100644 --- a/components/engine/daemon/daemonbuilder/builder.go +++ b/components/engine/daemon/daemonbuilder/builder.go @@ -11,6 +11,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/builder" "github.com/docker/docker/daemon" "github.com/docker/docker/image" @@ -21,7 +22,6 @@ import ( "github.com/docker/docker/pkg/urlutil" "github.com/docker/docker/reference" "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" ) // Docker implements builder.Backend for the docker Daemon object. @@ -182,7 +182,7 @@ func (d Docker) BuilderCopy(cID string, destPath string, src builder.FileInfo, d // GetCachedImage returns a reference to a cached image whose parent equals `parent` // and runconfig equals `cfg`. A cache miss is expected to return an empty ID and a nil error. -func (d Docker) GetCachedImage(imgID string, cfg *runconfig.Config) (string, error) { +func (d Docker) GetCachedImage(imgID string, cfg *container.Config) (string, error) { cache, err := d.Daemon.ImageGetCached(image.ID(imgID), cfg) if cache == nil || err != nil { return "", err diff --git a/components/engine/daemon/daemonbuilder/image.go b/components/engine/daemon/daemonbuilder/image.go index ab5ab9a322..34dbe3007c 100644 --- a/components/engine/daemon/daemonbuilder/image.go +++ b/components/engine/daemon/daemonbuilder/image.go @@ -1,8 +1,8 @@ package daemonbuilder import ( + "github.com/docker/docker/api/types/container" "github.com/docker/docker/image" - "github.com/docker/docker/runconfig" ) type imgWrap struct { @@ -13,6 +13,6 @@ func (img imgWrap) ID() string { return string(img.inner.ID()) } -func (img imgWrap) Config() *runconfig.Config { +func (img imgWrap) Config() *container.Config { return img.inner.Config } diff --git a/components/engine/daemon/delete_test.go b/components/engine/daemon/delete_test.go index 1ccba815e8..487bb5d4e3 100644 --- a/components/engine/daemon/delete_test.go +++ b/components/engine/daemon/delete_test.go @@ -6,8 +6,8 @@ import ( "testing" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" - "github.com/docker/docker/runconfig" ) func TestContainerDoubleDelete(t *testing.T) { @@ -26,7 +26,7 @@ func TestContainerDoubleDelete(t *testing.T) { CommonContainer: container.CommonContainer{ ID: "test", State: container.NewState(), - Config: &runconfig.Config{}, + Config: &containertypes.Config{}, }, } daemon.containers.Add(container.ID, container) diff --git a/components/engine/daemon/exec.go b/components/engine/daemon/exec.go index 50b1edc3b3..f400bc72f5 100644 --- a/components/engine/daemon/exec.go +++ b/components/engine/daemon/exec.go @@ -6,14 +6,14 @@ import ( "time" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/strslice" "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/pkg/pools" "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/runconfig" ) func (d *Daemon) registerExecCommand(container *container.Container, config *exec.Config) { @@ -79,14 +79,14 @@ func (d *Daemon) getActiveContainer(name string) (*container.Container, error) { } // ContainerExecCreate sets up an exec in a running container. -func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) { +func (d *Daemon) ContainerExecCreate(config *types.ExecConfig) (string, error) { container, err := d.getActiveContainer(config.Container) if err != nil { return "", err } - cmd := stringutils.NewStrSlice(config.Cmd...) - entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd) + cmd := strslice.New(config.Cmd...) + entrypoint, args := d.getEntrypointAndArgs(strslice.New(), cmd) processConfig := &execdriver.ProcessConfig{ CommonProcessConfig: execdriver.CommonProcessConfig{ diff --git a/components/engine/daemon/exec_unix.go b/components/engine/daemon/exec_unix.go index 4ac49927e9..40bd2c8ab8 100644 --- a/components/engine/daemon/exec_unix.go +++ b/components/engine/daemon/exec_unix.go @@ -3,14 +3,14 @@ package daemon import ( + "github.com/docker/docker/api/types" "github.com/docker/docker/container" "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/runconfig" ) // setPlatformSpecificExecProcessConfig sets platform-specific fields in the // ProcessConfig structure. -func setPlatformSpecificExecProcessConfig(config *runconfig.ExecConfig, container *container.Container, pc *execdriver.ProcessConfig) { +func setPlatformSpecificExecProcessConfig(config *types.ExecConfig, container *container.Container, pc *execdriver.ProcessConfig) { user := config.User if len(user) == 0 { user = container.Config.User diff --git a/components/engine/daemon/exec_windows.go b/components/engine/daemon/exec_windows.go index d6e887acad..f1b93bf02a 100644 --- a/components/engine/daemon/exec_windows.go +++ b/components/engine/daemon/exec_windows.go @@ -1,12 +1,12 @@ package daemon import ( + "github.com/docker/docker/api/types" "github.com/docker/docker/container" "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/runconfig" ) // setPlatformSpecificExecProcessConfig sets platform-specific fields in the // ProcessConfig structure. This is a no-op on Windows -func setPlatformSpecificExecProcessConfig(config *runconfig.ExecConfig, container *container.Container, pc *execdriver.ProcessConfig) { +func setPlatformSpecificExecProcessConfig(config *types.ExecConfig, container *container.Container, pc *execdriver.ProcessConfig) { } diff --git a/components/engine/daemon/execdriver/driver_windows.go b/components/engine/daemon/execdriver/driver_windows.go index dcd9d36df3..ec482cd30f 100644 --- a/components/engine/daemon/execdriver/driver_windows.go +++ b/components/engine/daemon/execdriver/driver_windows.go @@ -1,9 +1,6 @@ package execdriver -import ( - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/runconfig" -) +import "github.com/docker/go-connections/nat" // Mount contains information for a mount operation. type Mount struct { @@ -52,12 +49,13 @@ type Command struct { // Fields below here are platform specific - FirstStart bool `json:"first_start"` // Optimisation for first boot of Windows - Hostname string `json:"hostname"` // Windows sets the hostname in the execdriver - LayerFolder string `json:"layer_folder"` // Layer folder for a command - LayerPaths []string `json:"layer_paths"` // Layer paths for a command - Isolation runconfig.IsolationLevel `json:"isolation"` // Isolation level for the container - ArgsEscaped bool `json:"args_escaped"` // True if args are already escaped + FirstStart bool `json:"first_start"` // Optimisation for first boot of Windows + Hostname string `json:"hostname"` // Windows sets the hostname in the execdriver + LayerFolder string `json:"layer_folder"` // Layer folder for a command + LayerPaths []string `json:"layer_paths"` // Layer paths for a command + Isolation string `json:"isolation"` // Isolation level for the container + ArgsEscaped bool `json:"args_escaped"` // True if args are already escaped + HvPartition bool `json:"hv_partition"` // True if it's an hypervisor partition } // ExitStatus provides exit reasons for a container. diff --git a/components/engine/daemon/execdriver/windows/info.go b/components/engine/daemon/execdriver/windows/info.go index c85cd8a299..5a92f5d6dc 100644 --- a/components/engine/daemon/execdriver/windows/info.go +++ b/components/engine/daemon/execdriver/windows/info.go @@ -3,14 +3,14 @@ package windows import ( + "github.com/docker/docker/api/types/container" "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/runconfig" ) type info struct { ID string driver *Driver - isolation runconfig.IsolationLevel + isolation container.IsolationLevel } // Info implements the exec driver Driver interface. @@ -18,7 +18,7 @@ func (d *Driver) Info(id string) execdriver.Info { return &info{ ID: id, driver: d, - isolation: defaultIsolation, + isolation: DefaultIsolation, } } diff --git a/components/engine/daemon/execdriver/windows/run.go b/components/engine/daemon/execdriver/windows/run.go index b2f0966857..95d91dbc28 100644 --- a/components/engine/daemon/execdriver/windows/run.go +++ b/components/engine/daemon/execdriver/windows/run.go @@ -104,14 +104,7 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd HostName: c.Hostname, } - // Work out the isolation (whether it is a hypervisor partition) - if c.Isolation.IsDefault() { - // Not specified by caller. Take daemon default - cu.HvPartition = defaultIsolation.IsHyperV() - } else { - // Take value specified by caller - cu.HvPartition = c.Isolation.IsHyperV() - } + cu.HvPartition = c.HvPartition if cu.HvPartition { cu.SandboxPath = filepath.Dir(c.LayerFolder) diff --git a/components/engine/daemon/execdriver/windows/windows.go b/components/engine/daemon/execdriver/windows/windows.go index 3edb57ee51..810f452ed5 100644 --- a/components/engine/daemon/execdriver/windows/windows.go +++ b/components/engine/daemon/execdriver/windows/windows.go @@ -8,10 +8,10 @@ import ( "sync" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/dockerversion" "github.com/docker/docker/pkg/parsers" - "github.com/docker/docker/runconfig" ) // This is a daemon development variable only and should not be @@ -22,11 +22,11 @@ var dummyMode bool // This allows the daemon to force kill (HCS terminate) rather than shutdown var forceKill bool -// defaultIsolation allows users to specify a default isolation mode for +// DefaultIsolation allows users to specify a default isolation mode for // when running a container on Windows. For example docker daemon -D // --exec-opt isolation=hyperv will cause Windows to always run containers // as Hyper-V containers unless otherwise specified. -var defaultIsolation runconfig.IsolationLevel = "process" +var DefaultIsolation container.IsolationLevel = "process" // Define name and version for windows var ( @@ -48,7 +48,7 @@ type Driver struct { // Name implements the exec driver Driver interface. func (d *Driver) Name() string { - return fmt.Sprintf("\n Name: %s\n Build: %s \n Default Isolation: %s", DriverName, Version, defaultIsolation) + return fmt.Sprintf("\n Name: %s\n Build: %s \n Default Isolation: %s", DriverName, Version, DefaultIsolation) } // NewDriver returns a new windows driver, called from NewDriver of execdriver. @@ -77,11 +77,11 @@ func NewDriver(root string, options []string) (*Driver, error) { } case "isolation": - if !runconfig.IsolationLevel(val).IsValid() { + if !container.IsolationLevel(val).IsValid() { return nil, fmt.Errorf("Unrecognised exec driver option 'isolation':'%s'", val) } - if runconfig.IsolationLevel(val).IsHyperV() { - defaultIsolation = "hyperv" + if container.IsolationLevel(val).IsHyperV() { + DefaultIsolation = "hyperv" } logrus.Infof("Windows default isolation level: '%s'", val) default: diff --git a/components/engine/daemon/import.go b/components/engine/daemon/import.go index f09ab672aa..26f8ce66fe 100644 --- a/components/engine/daemon/import.go +++ b/components/engine/daemon/import.go @@ -8,6 +8,7 @@ import ( "runtime" "time" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/dockerversion" "github.com/docker/docker/image" "github.com/docker/docker/layer" @@ -15,14 +16,13 @@ import ( "github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/reference" - "github.com/docker/docker/runconfig" ) // ImportImage imports an image, getting the archived layer data either from // inConfig (if src is "-"), or from a URI specified in src. Progress output is // written to outStream. Repository and tag names can optionally be given in // the repo and tag arguments, respectively. -func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, config *runconfig.Config) error { +func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, config *container.Config) error { var ( sf = streamformatter.NewJSONStreamFormatter() archive io.ReadCloser diff --git a/components/engine/daemon/links/links.go b/components/engine/daemon/links/links.go index e513fe06e7..af15de046d 100644 --- a/components/engine/daemon/links/links.go +++ b/components/engine/daemon/links/links.go @@ -5,7 +5,7 @@ import ( "path" "strings" - "github.com/docker/docker/pkg/nat" + "github.com/docker/go-connections/nat" ) // Link struct holds informations about parent/child linked container diff --git a/components/engine/daemon/links/links_test.go b/components/engine/daemon/links/links_test.go index 3d0fb6d7c6..0273f13cf0 100644 --- a/components/engine/daemon/links/links_test.go +++ b/components/engine/daemon/links/links_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/docker/docker/pkg/nat" + "github.com/docker/go-connections/nat" ) // Just to make life easier diff --git a/components/engine/daemon/list.go b/components/engine/daemon/list.go index 26632c3ce8..68944d6598 100644 --- a/components/engine/daemon/list.go +++ b/components/engine/daemon/list.go @@ -12,7 +12,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/image" "github.com/docker/docker/pkg/graphdb" - "github.com/docker/docker/pkg/nat" + "github.com/docker/go-connections/nat" ) // iterationAction represents possible outcomes happening during the container iteration. diff --git a/components/engine/daemon/network/settings.go b/components/engine/daemon/network/settings.go index 293ffc7056..1bf4b5a672 100644 --- a/components/engine/daemon/network/settings.go +++ b/components/engine/daemon/network/settings.go @@ -2,7 +2,7 @@ package network import ( networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/pkg/nat" + "github.com/docker/go-connections/nat" ) // Settings stores configuration details about the daemon network config diff --git a/components/engine/daemon/start.go b/components/engine/daemon/start.go index 639e6aec01..27279d6b37 100644 --- a/components/engine/daemon/start.go +++ b/components/engine/daemon/start.go @@ -4,13 +4,14 @@ import ( "runtime" "github.com/Sirupsen/logrus" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" derr "github.com/docker/docker/errors" "github.com/docker/docker/runconfig" ) // ContainerStart starts a container. -func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConfig) error { +func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig) error { container, err := daemon.GetContainer(name) if err != nil { return err diff --git a/components/engine/daemon/volumes.go b/components/engine/daemon/volumes.go index 33e8a20aad..4b5522d66a 100644 --- a/components/engine/daemon/volumes.go +++ b/components/engine/daemon/volumes.go @@ -7,10 +7,10 @@ import ( "strings" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" "github.com/docker/docker/daemon/execdriver" derr "github.com/docker/docker/errors" - "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" "github.com/opencontainers/runc/libcontainer/label" ) @@ -71,7 +71,7 @@ func (m mounts) parts(i int) int { // 2. Select the volumes mounted from another containers. Overrides previously configured mount point destination. // 3. Select the bind mounts set by the client. Overrides previously configured mount point destinations. // 4. Cleanup old volumes that are about to be reassigned. -func (daemon *Daemon) registerMountPoints(container *container.Container, hostConfig *runconfig.HostConfig) error { +func (daemon *Daemon) registerMountPoints(container *container.Container, hostConfig *containertypes.HostConfig) error { binds := map[string]bool{} mountPoints := map[string]*volume.MountPoint{} diff --git a/components/engine/hack/vendor.sh b/components/engine/hack/vendor.sh index f6832193d2..9535aa5657 100755 --- a/components/engine/hack/vendor.sh +++ b/components/engine/hack/vendor.sh @@ -21,6 +21,7 @@ clone git github.com/tchap/go-patricia v2.1.0 clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://github.com/golang/net.git clone git github.com/docker/go-units v0.2.0 +clone git github.com/docker/go-connections 96cdf8190a45946d0f19576732e2a410c6f84a31 #get libnetwork packages clone git github.com/docker/libnetwork bbd6e6d8ca1e7c9b42f6f53277b0bde72847ff90 diff --git a/components/engine/image/image.go b/components/engine/image/image.go index ee4a2884f9..c0508c1b98 100644 --- a/components/engine/image/image.go +++ b/components/engine/image/image.go @@ -7,7 +7,7 @@ import ( "time" "github.com/docker/distribution/digest" - "github.com/docker/docker/runconfig" + "github.com/docker/docker/api/types/container" ) // ID is the content-addressable ID of an image. @@ -30,13 +30,13 @@ type V1Image struct { // Container is the id of the container used to commit Container string `json:"container,omitempty"` // ContainerConfig is the configuration of the container that is committed into the image - ContainerConfig runconfig.Config `json:"container_config,omitempty"` + ContainerConfig container.Config `json:"container_config,omitempty"` // DockerVersion specifies version on which image is built DockerVersion string `json:"docker_version,omitempty"` // Author of the image Author string `json:"author,omitempty"` // Config is the configuration of the container received from the client - Config *runconfig.Config `json:"config,omitempty"` + Config *container.Config `json:"config,omitempty"` // Architecture is the hardware that the image is build and runs on Architecture string `json:"architecture,omitempty"` // OS is the operating system used to build and run the image diff --git a/components/engine/integration-cli/docker_api_containers_test.go b/components/engine/integration-cli/docker_api_containers_test.go index 4e6322643a..5c33520170 100644 --- a/components/engine/integration-cli/docker_api_containers_test.go +++ b/components/engine/integration-cli/docker_api_containers_test.go @@ -16,10 +16,10 @@ import ( "time" "github.com/docker/docker/api/types" + containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/integration" "github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" "github.com/go-check/check" ) @@ -678,7 +678,7 @@ func UtilCreateNetworkMode(c *check.C, networkMode string) { var containerJSON types.ContainerJSON c.Assert(json.Unmarshal(body, &containerJSON), checker.IsNil) - c.Assert(containerJSON.HostConfig.NetworkMode, checker.Equals, runconfig.NetworkMode(networkMode), check.Commentf("Mismatched NetworkMode")) + c.Assert(containerJSON.HostConfig.NetworkMode, checker.Equals, containertypes.NetworkMode(networkMode), check.Commentf("Mismatched NetworkMode")) } func (s *DockerSuite) TestContainerApiCreateWithCpuSharesCpuset(c *check.C) { diff --git a/components/engine/integration-cli/docker_cli_create_test.go b/components/engine/integration-cli/docker_cli_create_test.go index a2d47cf595..bbd1eb6df1 100644 --- a/components/engine/integration-cli/docker_cli_create_test.go +++ b/components/engine/integration-cli/docker_cli_create_test.go @@ -13,8 +13,8 @@ import ( "io/ioutil" "github.com/docker/docker/pkg/integration/checker" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/stringid" + "github.com/docker/go-connections/nat" "github.com/go-check/check" ) diff --git a/components/engine/integration-cli/docker_cli_inspect_test.go b/components/engine/integration-cli/docker_cli_inspect_test.go index 2da0b3ca3d..d471936be4 100644 --- a/components/engine/integration-cli/docker_cli_inspect_test.go +++ b/components/engine/integration-cli/docker_cli_inspect_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/integration/checker" - "github.com/docker/docker/runconfig" "github.com/go-check/check" ) @@ -281,7 +281,7 @@ func (s *DockerSuite) TestInspectTimesAsRFC3339Nano(c *check.C) { func (s *DockerSuite) TestInspectLogConfigNoType(c *check.C) { testRequires(c, DaemonIsLinux) dockerCmd(c, "create", "--name=test", "--log-opt", "max-file=42", "busybox") - var logConfig runconfig.LogConfig + var logConfig container.LogConfig out, err := inspectFieldJSON("test", "HostConfig.LogConfig") c.Assert(err, checker.IsNil, check.Commentf("%v", out)) diff --git a/components/engine/integration-cli/docker_cli_run_test.go b/components/engine/integration-cli/docker_cli_run_test.go index 399dce27cb..e696078950 100644 --- a/components/engine/integration-cli/docker_cli_run_test.go +++ b/components/engine/integration-cli/docker_cli_run_test.go @@ -20,8 +20,8 @@ import ( "github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/runconfig" + "github.com/docker/go-connections/nat" "github.com/docker/libnetwork/resolvconf" "github.com/go-check/check" ) diff --git a/components/engine/opts/opts.go b/components/engine/opts/opts.go index 1a77e20c7a..98a0319750 100644 --- a/components/engine/opts/opts.go +++ b/components/engine/opts/opts.go @@ -8,7 +8,7 @@ import ( "strconv" "strings" - "github.com/docker/docker/pkg/blkiodev" + "github.com/docker/docker/api/types/blkiodev" "github.com/docker/go-units" ) diff --git a/components/engine/opts/throttledevice.go b/components/engine/opts/throttledevice.go index fb11802326..6d3e31bc04 100644 --- a/components/engine/opts/throttledevice.go +++ b/components/engine/opts/throttledevice.go @@ -3,7 +3,7 @@ package opts import ( "fmt" - "github.com/docker/docker/pkg/blkiodev" + "github.com/docker/docker/api/types/blkiodev" ) // ThrottledeviceOpt defines a map of ThrottleDevices diff --git a/components/engine/opts/weightdevice.go b/components/engine/opts/weightdevice.go index 4c6288f6af..2c94af3bf0 100644 --- a/components/engine/opts/weightdevice.go +++ b/components/engine/opts/weightdevice.go @@ -3,7 +3,7 @@ package opts import ( "fmt" - "github.com/docker/docker/pkg/blkiodev" + "github.com/docker/docker/api/types/blkiodev" ) // WeightdeviceOpt defines a map of WeightDevices diff --git a/components/engine/runconfig/compare.go b/components/engine/runconfig/compare.go index ebb8ead6c1..81f16b0a35 100644 --- a/components/engine/runconfig/compare.go +++ b/components/engine/runconfig/compare.go @@ -1,8 +1,10 @@ package runconfig +import "github.com/docker/docker/api/types/container" + // Compare two Config struct. Do not compare the "Image" nor "Hostname" fields // If OpenStdin is set, then it differs -func Compare(a, b *Config) bool { +func Compare(a, b *container.Config) bool { if a == nil || b == nil || a.OpenStdin || b.OpenStdin { return false diff --git a/components/engine/runconfig/compare_test.go b/components/engine/runconfig/compare_test.go index 1a5c6c6ca0..ed7528d67b 100644 --- a/components/engine/runconfig/compare_test.go +++ b/components/engine/runconfig/compare_test.go @@ -3,8 +3,9 @@ package runconfig import ( "testing" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/stringutils" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/go-connections/nat" ) // Just to make life easier @@ -33,21 +34,21 @@ func TestCompare(t *testing.T) { volumes3["/test3"] = struct{}{} envs1 := []string{"ENV1=value1", "ENV2=value2"} envs2 := []string{"ENV1=value1", "ENV3=value3"} - entrypoint1 := stringutils.NewStrSlice("/bin/sh", "-c") - entrypoint2 := stringutils.NewStrSlice("/bin/sh", "-d") - entrypoint3 := stringutils.NewStrSlice("/bin/sh", "-c", "echo") - cmd1 := stringutils.NewStrSlice("/bin/sh", "-c") - cmd2 := stringutils.NewStrSlice("/bin/sh", "-d") - cmd3 := stringutils.NewStrSlice("/bin/sh", "-c", "echo") + entrypoint1 := strslice.New("/bin/sh", "-c") + entrypoint2 := strslice.New("/bin/sh", "-d") + entrypoint3 := strslice.New("/bin/sh", "-c", "echo") + cmd1 := strslice.New("/bin/sh", "-c") + cmd2 := strslice.New("/bin/sh", "-d") + cmd3 := strslice.New("/bin/sh", "-c", "echo") labels1 := map[string]string{"LABEL1": "value1", "LABEL2": "value2"} labels2 := map[string]string{"LABEL1": "value1", "LABEL2": "value3"} labels3 := map[string]string{"LABEL1": "value1", "LABEL2": "value2", "LABEL3": "value3"} - sameConfigs := map[*Config]*Config{ + sameConfigs := map[*container.Config]*container.Config{ // Empty config - &Config{}: {}, + &container.Config{}: {}, // Does not compare hostname, domainname & image - &Config{ + &container.Config{ Hostname: "host1", Domainname: "domain1", Image: "image1", @@ -59,23 +60,23 @@ func TestCompare(t *testing.T) { User: "user", }, // only OpenStdin - &Config{OpenStdin: false}: {OpenStdin: false}, + &container.Config{OpenStdin: false}: {OpenStdin: false}, // only env - &Config{Env: envs1}: {Env: envs1}, + &container.Config{Env: envs1}: {Env: envs1}, // only cmd - &Config{Cmd: cmd1}: {Cmd: cmd1}, + &container.Config{Cmd: cmd1}: {Cmd: cmd1}, // only labels - &Config{Labels: labels1}: {Labels: labels1}, + &container.Config{Labels: labels1}: {Labels: labels1}, // only exposedPorts - &Config{ExposedPorts: ports1}: {ExposedPorts: ports1}, + &container.Config{ExposedPorts: ports1}: {ExposedPorts: ports1}, // only entrypoints - &Config{Entrypoint: entrypoint1}: {Entrypoint: entrypoint1}, + &container.Config{Entrypoint: entrypoint1}: {Entrypoint: entrypoint1}, // only volumes - &Config{Volumes: volumes1}: {Volumes: volumes1}, + &container.Config{Volumes: volumes1}: {Volumes: volumes1}, } - differentConfigs := map[*Config]*Config{ + differentConfigs := map[*container.Config]*container.Config{ nil: nil, - &Config{ + &container.Config{ Hostname: "host1", Domainname: "domain1", Image: "image1", @@ -87,30 +88,30 @@ func TestCompare(t *testing.T) { User: "user2", }, // only OpenStdin - &Config{OpenStdin: false}: {OpenStdin: true}, - &Config{OpenStdin: true}: {OpenStdin: false}, + &container.Config{OpenStdin: false}: {OpenStdin: true}, + &container.Config{OpenStdin: true}: {OpenStdin: false}, // only env - &Config{Env: envs1}: {Env: envs2}, + &container.Config{Env: envs1}: {Env: envs2}, // only cmd - &Config{Cmd: cmd1}: {Cmd: cmd2}, + &container.Config{Cmd: cmd1}: {Cmd: cmd2}, // not the same number of parts - &Config{Cmd: cmd1}: {Cmd: cmd3}, + &container.Config{Cmd: cmd1}: {Cmd: cmd3}, // only labels - &Config{Labels: labels1}: {Labels: labels2}, + &container.Config{Labels: labels1}: {Labels: labels2}, // not the same number of labels - &Config{Labels: labels1}: {Labels: labels3}, + &container.Config{Labels: labels1}: {Labels: labels3}, // only exposedPorts - &Config{ExposedPorts: ports1}: {ExposedPorts: ports2}, + &container.Config{ExposedPorts: ports1}: {ExposedPorts: ports2}, // not the same number of ports - &Config{ExposedPorts: ports1}: {ExposedPorts: ports3}, + &container.Config{ExposedPorts: ports1}: {ExposedPorts: ports3}, // only entrypoints - &Config{Entrypoint: entrypoint1}: {Entrypoint: entrypoint2}, + &container.Config{Entrypoint: entrypoint1}: {Entrypoint: entrypoint2}, // not the same number of parts - &Config{Entrypoint: entrypoint1}: {Entrypoint: entrypoint3}, + &container.Config{Entrypoint: entrypoint1}: {Entrypoint: entrypoint3}, // only volumes - &Config{Volumes: volumes1}: {Volumes: volumes2}, + &container.Config{Volumes: volumes1}: {Volumes: volumes2}, // not the same number of labels - &Config{Volumes: volumes1}: {Volumes: volumes3}, + &container.Config{Volumes: volumes1}: {Volumes: volumes3}, } for config1, config2 := range sameConfigs { if !Compare(config1, config2) { diff --git a/components/engine/runconfig/config.go b/components/engine/runconfig/config.go index f4af1017e2..d12457393c 100644 --- a/components/engine/runconfig/config.go +++ b/components/engine/runconfig/config.go @@ -5,48 +5,15 @@ import ( "fmt" "io" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/stringutils" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/volume" ) -// Config contains the configuration data about a container. -// It should hold only portable information about the container. -// Here, "portable" means "independent from the host we are running on". -// Non-portable information *should* appear in HostConfig. -// All fields added to this struct must be marked `omitempty` to keep getting -// predictable hashes from the old `v1Compatibility` configuration. -type Config struct { - Hostname string // Hostname - Domainname string // Domainname - User string // User that will run the command(s) inside the container - AttachStdin bool // Attach the standard input, makes possible user interaction - AttachStdout bool // Attach the standard output - AttachStderr bool // Attach the standard error - ExposedPorts map[nat.Port]struct{} `json:",omitempty"` // List of exposed ports - PublishService string `json:",omitempty"` // Name of the network service exposed by the container - Tty bool // Attach standard streams to a tty, including stdin if it is not closed. - OpenStdin bool // Open stdin - StdinOnce bool // If true, close stdin after the 1 attached client disconnects. - Env []string // List of environment variable to set in the container - Cmd *stringutils.StrSlice // Command to run when starting the container - ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific) - Image string // Name of the image as it was passed by the operator (eg. could be symbolic) - Volumes map[string]struct{} // List of volumes (mounts) used for the container - WorkingDir string // Current directory (PWD) in the command will be launched - Entrypoint *stringutils.StrSlice // Entrypoint to run when starting the container - NetworkDisabled bool `json:",omitempty"` // Is network disabled - MacAddress string `json:",omitempty"` // Mac Address of the container - OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile - Labels map[string]string // List of labels set to this container - StopSignal string `json:",omitempty"` // Signal to stop a container -} - // DecodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper // struct and returns both a Config and an HostConfig struct // Be aware this function is not checking whether the resulted structs are nil, // it's your business to do so -func DecodeContainerConfig(src io.Reader) (*Config, *HostConfig, error) { +func DecodeContainerConfig(src io.Reader) (*container.Config, *container.HostConfig, error) { var w ContainerConfigWrapper decoder := json.NewDecoder(src) @@ -85,7 +52,7 @@ func DecodeContainerConfig(src io.Reader) (*Config, *HostConfig, error) { // validateVolumesAndBindSettings validates each of the volumes and bind settings // passed by the caller to ensure they are valid. -func validateVolumesAndBindSettings(c *Config, hc *HostConfig) error { +func validateVolumesAndBindSettings(c *container.Config, hc *container.HostConfig) error { // Ensure all volumes and binds are valid. for spec := range c.Volumes { diff --git a/components/engine/runconfig/config_test.go b/components/engine/runconfig/config_test.go index b721cf1086..7a1c785c2f 100644 --- a/components/engine/runconfig/config_test.go +++ b/components/engine/runconfig/config_test.go @@ -9,12 +9,13 @@ import ( "strings" "testing" - "github.com/docker/docker/pkg/stringutils" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/strslice" ) type f struct { file string - entrypoint *stringutils.StrSlice + entrypoint *strslice.StrSlice } func TestDecodeContainerConfig(t *testing.T) { @@ -27,14 +28,14 @@ func TestDecodeContainerConfig(t *testing.T) { if runtime.GOOS != "windows" { image = "ubuntu" fixtures = []f{ - {"fixtures/unix/container_config_1_14.json", stringutils.NewStrSlice()}, - {"fixtures/unix/container_config_1_17.json", stringutils.NewStrSlice("bash")}, - {"fixtures/unix/container_config_1_19.json", stringutils.NewStrSlice("bash")}, + {"fixtures/unix/container_config_1_14.json", strslice.New()}, + {"fixtures/unix/container_config_1_17.json", strslice.New("bash")}, + {"fixtures/unix/container_config_1_19.json", strslice.New("bash")}, } } else { image = "windows" fixtures = []f{ - {"fixtures/windows/container_config_1_19.json", stringutils.NewStrSlice("cmd")}, + {"fixtures/windows/container_config_1_19.json", strslice.New("cmd")}, } } @@ -101,16 +102,16 @@ func TestDecodeContainerConfigIsolation(t *testing.T) { // callDecodeContainerConfigIsolation is a utility function to call // DecodeContainerConfig for validating isolation levels -func callDecodeContainerConfigIsolation(isolation string) (*Config, *HostConfig, error) { +func callDecodeContainerConfigIsolation(isolation string) (*container.Config, *container.HostConfig, error) { var ( b []byte err error ) w := ContainerConfigWrapper{ - Config: &Config{}, - HostConfig: &HostConfig{ + Config: &container.Config{}, + HostConfig: &container.HostConfig{ NetworkMode: "none", - Isolation: IsolationLevel(isolation)}, + Isolation: container.IsolationLevel(isolation)}, } if b, err = json.Marshal(w); err != nil { return nil, nil, fmt.Errorf("Error on marshal %s", err.Error()) diff --git a/components/engine/runconfig/config_unix.go b/components/engine/runconfig/config_unix.go index 18b2fee7c8..05af155f5d 100644 --- a/components/engine/runconfig/config_unix.go +++ b/components/engine/runconfig/config_unix.go @@ -2,18 +2,20 @@ package runconfig +import "github.com/docker/docker/api/types/container" + // ContainerConfigWrapper is a Config wrapper that hold the container Config (portable) // and the corresponding HostConfig (non-portable). type ContainerConfigWrapper struct { - *Config - InnerHostConfig *HostConfig `json:"HostConfig,omitempty"` - Cpuset string `json:",omitempty"` // Deprecated. Exported for backwards compatibility. - *HostConfig // Deprecated. Exported to read attributes from json that are not in the inner host config structure. + *container.Config + InnerHostConfig *container.HostConfig `json:"HostConfig,omitempty"` + Cpuset string `json:",omitempty"` // Deprecated. Exported for backwards compatibility. + *container.HostConfig // Deprecated. Exported to read attributes from json that are not in the inner host config structure. } // getHostConfig gets the HostConfig of the Config. // It's mostly there to handle Deprecated fields of the ContainerConfigWrapper -func (w *ContainerConfigWrapper) getHostConfig() *HostConfig { +func (w *ContainerConfigWrapper) getHostConfig() *container.HostConfig { hc := w.HostConfig if hc == nil && w.InnerHostConfig != nil { diff --git a/components/engine/runconfig/config_windows.go b/components/engine/runconfig/config_windows.go index 2ab8e19a27..6ff7afcdaf 100644 --- a/components/engine/runconfig/config_windows.go +++ b/components/engine/runconfig/config_windows.go @@ -1,13 +1,15 @@ package runconfig +import "github.com/docker/docker/api/types/container" + // ContainerConfigWrapper is a Config wrapper that hold the container Config (portable) // and the corresponding HostConfig (non-portable). type ContainerConfigWrapper struct { - *Config - HostConfig *HostConfig `json:"HostConfig,omitempty"` + *container.Config + HostConfig *container.HostConfig `json:"HostConfig,omitempty"` } // getHostConfig gets the HostConfig of the Config. -func (w *ContainerConfigWrapper) getHostConfig() *HostConfig { +func (w *ContainerConfigWrapper) getHostConfig() *container.HostConfig { return w.HostConfig } diff --git a/components/engine/runconfig/exec.go b/components/engine/runconfig/exec.go index 6fe28ea338..0ef8926602 100644 --- a/components/engine/runconfig/exec.go +++ b/components/engine/runconfig/exec.go @@ -1,28 +1,15 @@ package runconfig import ( + "github.com/docker/docker/api/types" flag "github.com/docker/docker/pkg/mflag" ) -// ExecConfig is a small subset of the Config struct that hold the configuration -// for the exec feature of docker. -type ExecConfig struct { - User string // User that will run the command - Privileged bool // Is the container in privileged mode - Tty bool // Attach standard streams to a tty. - Container string // Name of the container (to execute in) - AttachStdin bool // Attach the standard input, makes possible user interaction - AttachStderr bool // Attach the standard output - AttachStdout bool // Attach the standard error - Detach bool // Execute in detach mode - Cmd []string // Execution commands and args -} - // ParseExec parses the specified args for the specified command and generates // an ExecConfig from it. // If the minimal number of specified args is not right or if specified args are // not valid, it will return an error. -func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) { +func ParseExec(cmd *flag.FlagSet, args []string) (*types.ExecConfig, error) { var ( flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached") flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY") @@ -40,7 +27,7 @@ func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) { parsedArgs := cmd.Args() execCmd = parsedArgs[1:] - execConfig := &ExecConfig{ + execConfig := &types.ExecConfig{ User: *flUser, Privileged: *flPrivileged, Tty: *flTty, diff --git a/components/engine/runconfig/exec_test.go b/components/engine/runconfig/exec_test.go index a4b7ea9bac..1acae6eff6 100644 --- a/components/engine/runconfig/exec_test.go +++ b/components/engine/runconfig/exec_test.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "testing" + "github.com/docker/docker/api/types" flag "github.com/docker/docker/pkg/mflag" ) @@ -18,7 +19,7 @@ func TestParseExec(t *testing.T) { &arguments{[]string{"-u"}}: fmt.Errorf("flag needs an argument: -u"), &arguments{[]string{"--user"}}: fmt.Errorf("flag needs an argument: --user"), } - valids := map[*arguments]*ExecConfig{ + valids := map[*arguments]*types.ExecConfig{ &arguments{ []string{"container", "command"}, }: { @@ -92,7 +93,7 @@ func TestParseExec(t *testing.T) { } } -func compareExecConfig(config1 *ExecConfig, config2 *ExecConfig) bool { +func compareExecConfig(config1 *types.ExecConfig, config2 *types.ExecConfig) bool { if config1.AttachStderr != config2.AttachStderr { return false } diff --git a/components/engine/runconfig/hostconfig.go b/components/engine/runconfig/hostconfig.go index 98d044cf66..2b81d02c20 100644 --- a/components/engine/runconfig/hostconfig.go +++ b/components/engine/runconfig/hostconfig.go @@ -3,240 +3,13 @@ package runconfig import ( "encoding/json" "io" - "strings" - "github.com/docker/docker/pkg/blkiodev" - "github.com/docker/docker/pkg/nat" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/docker/pkg/ulimit" + "github.com/docker/docker/api/types/container" ) -// KeyValuePair is a structure that hold a value for a key. -type KeyValuePair struct { - Key string - Value string -} - -// NetworkMode represents the container network stack. -type NetworkMode string - -// IsolationLevel represents the isolation level of a container. The supported -// values are platform specific -type IsolationLevel string - -// IsDefault indicates the default isolation level of a container. On Linux this -// is the native driver. On Windows, this is a Windows Server Container. -func (i IsolationLevel) IsDefault() bool { - return strings.ToLower(string(i)) == "default" || string(i) == "" -} - -// IpcMode represents the container ipc stack. -type IpcMode string - -// IsPrivate indicates whether the container uses it's private ipc stack. -func (n IpcMode) IsPrivate() bool { - return !(n.IsHost() || n.IsContainer()) -} - -// IsHost indicates whether the container uses the host's ipc stack. -func (n IpcMode) IsHost() bool { - return n == "host" -} - -// IsContainer indicates whether the container uses a container's ipc stack. -func (n IpcMode) IsContainer() bool { - parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// Valid indicates whether the ipc stack is valid. -func (n IpcMode) Valid() bool { - parts := strings.Split(string(n), ":") - switch mode := parts[0]; mode { - case "", "host": - case "container": - if len(parts) != 2 || parts[1] == "" { - return false - } - default: - return false - } - return true -} - -// Container returns the name of the container ipc stack is going to be used. -func (n IpcMode) Container() string { - parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - -// UTSMode represents the UTS namespace of the container. -type UTSMode string - -// IsPrivate indicates whether the container uses it's private UTS namespace. -func (n UTSMode) IsPrivate() bool { - return !(n.IsHost()) -} - -// IsHost indicates whether the container uses the host's UTS namespace. -func (n UTSMode) IsHost() bool { - return n == "host" -} - -// Valid indicates whether the UTS namespace is valid. -func (n UTSMode) Valid() bool { - parts := strings.Split(string(n), ":") - switch mode := parts[0]; mode { - case "", "host": - default: - return false - } - return true -} - -// PidMode represents the pid stack of the container. -type PidMode string - -// IsPrivate indicates whether the container uses it's private pid stack. -func (n PidMode) IsPrivate() bool { - return !(n.IsHost()) -} - -// IsHost indicates whether the container uses the host's pid stack. -func (n PidMode) IsHost() bool { - return n == "host" -} - -// Valid indicates whether the pid stack is valid. -func (n PidMode) Valid() bool { - parts := strings.Split(string(n), ":") - switch mode := parts[0]; mode { - case "", "host": - default: - return false - } - return true -} - -// DeviceMapping represents the device mapping between the host and the container. -type DeviceMapping struct { - PathOnHost string - PathInContainer string - CgroupPermissions string -} - -// RestartPolicy represents the restart policies of the container. -type RestartPolicy struct { - Name string - MaximumRetryCount int -} - -// IsNone indicates whether the container has the "no" restart policy. -// This means the container will not automatically restart when exiting. -func (rp *RestartPolicy) IsNone() bool { - return rp.Name == "no" -} - -// IsAlways indicates whether the container has the "always" restart policy. -// This means the container will automatically restart regardless of the exit status. -func (rp *RestartPolicy) IsAlways() bool { - return rp.Name == "always" -} - -// IsOnFailure indicates whether the container has the "on-failure" restart policy. -// This means the contain will automatically restart of exiting with a non-zero exit status. -func (rp *RestartPolicy) IsOnFailure() bool { - return rp.Name == "on-failure" -} - -// IsUnlessStopped indicates whether the container has the -// "unless-stopped" restart policy. This means the container will -// automatically restart unless user has put it to stopped state. -func (rp *RestartPolicy) IsUnlessStopped() bool { - return rp.Name == "unless-stopped" -} - -// LogConfig represents the logging configuration of the container. -type LogConfig struct { - Type string - Config map[string]string -} - -// Resources contains container's resources (cgroups config, ulimits...) -type Resources struct { - // Applicable to all platforms - CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers) - - // Applicable to UNIX platforms - CgroupParent string // Parent cgroup. - BlkioWeight uint16 // Block IO weight (relative weight vs. other containers) - BlkioWeightDevice []*blkiodev.WeightDevice - BlkioDeviceReadBps []*blkiodev.ThrottleDevice - BlkioDeviceWriteBps []*blkiodev.ThrottleDevice - BlkioDeviceReadIOps []*blkiodev.ThrottleDevice - BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice - CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period - CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota - CpusetCpus string // CpusetCpus 0-2, 0,1 - CpusetMems string // CpusetMems 0-2, 0,1 - Devices []DeviceMapping // List of devices to map inside the container - KernelMemory int64 // Kernel memory limit (in bytes) - Memory int64 // Memory limit (in bytes) - MemoryReservation int64 // Memory soft limit (in bytes) - MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap - MemorySwappiness *int64 // Tuning container memory swappiness behaviour - OomKillDisable bool // Whether to disable OOM Killer or not - Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container -} - -// HostConfig the non-portable Config structure of a container. -// Here, "non-portable" means "dependent of the host we are running on". -// Portable information *should* appear in Config. -type HostConfig struct { - // Applicable to all platforms - Binds []string // List of volume bindings for this container - ContainerIDFile string // File (path) where the containerId is written - LogConfig LogConfig // Configuration of the logs for this container - NetworkMode NetworkMode // Network mode to use for the container - PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host - RestartPolicy RestartPolicy // Restart policy to be used for the container - VolumeDriver string // Name of the volume driver used to mount volumes - VolumesFrom []string // List of volumes to take from other container - - // Applicable to UNIX platforms - CapAdd *stringutils.StrSlice // List of kernel capabilities to add to the container - CapDrop *stringutils.StrSlice // List of kernel capabilities to remove from the container - DNS []string `json:"Dns"` // List of DNS server to lookup - DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for - DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for - ExtraHosts []string // List of extra hosts - GroupAdd []string // List of additional groups that the container process will run as - IpcMode IpcMode // IPC namespace to use for the container - Links []string // List of links (in the name:alias form) - OomScoreAdj int // Container preference for OOM-killing - PidMode PidMode // PID namespace to use for the container - Privileged bool // Is the container in privileged mode - PublishAllPorts bool // Should docker publish all exposed port for the container - ReadonlyRootfs bool // Is the container root filesystem in read-only - SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. - Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container - UTSMode UTSMode // UTS namespace to use for the container - ShmSize *int64 // Total shm memory usage - - // Applicable to Windows - ConsoleSize [2]int // Initial console size - Isolation IsolationLevel // Isolation level of the container (eg default, hyperv) - - // Contains container's resources (cgroups, ulimits) - Resources -} - // DecodeHostConfig creates a HostConfig based on the specified Reader. // It assumes the content of the reader will be JSON, and decodes it. -func DecodeHostConfig(src io.Reader) (*HostConfig, error) { +func DecodeHostConfig(src io.Reader) (*container.HostConfig, error) { decoder := json.NewDecoder(src) var w ContainerConfigWrapper @@ -252,10 +25,10 @@ func DecodeHostConfig(src io.Reader) (*HostConfig, error) { // to default if it is not populated. This ensures backwards compatibility after // the validation of the network mode was moved from the docker CLI to the // docker daemon. -func SetDefaultNetModeIfBlank(hc *HostConfig) *HostConfig { +func SetDefaultNetModeIfBlank(hc *container.HostConfig) *container.HostConfig { if hc != nil { - if hc.NetworkMode == NetworkMode("") { - hc.NetworkMode = NetworkMode("default") + if hc.NetworkMode == container.NetworkMode("") { + hc.NetworkMode = container.NetworkMode("default") } } return hc diff --git a/components/engine/runconfig/hostconfig_test.go b/components/engine/runconfig/hostconfig_test.go index 9fe3fa782d..941c16d6e8 100644 --- a/components/engine/runconfig/hostconfig_test.go +++ b/components/engine/runconfig/hostconfig_test.go @@ -7,11 +7,13 @@ import ( "fmt" "io/ioutil" "testing" + + "github.com/docker/docker/api/types/container" ) // TODO Windows: This will need addressing for a Windows daemon. func TestNetworkModeTest(t *testing.T) { - networkModes := map[NetworkMode][]bool{ + networkModes := map[container.NetworkMode][]bool{ // private, bridge, host, container, none, default "": {true, false, false, false, false, false}, "something:weird": {true, false, false, false, false, false}, @@ -22,7 +24,7 @@ func TestNetworkModeTest(t *testing.T) { "none": {true, false, false, false, true, false}, "default": {true, false, false, false, false, true}, } - networkModeNames := map[NetworkMode]string{ + networkModeNames := map[container.NetworkMode]string{ "": "", "something:weird": "something:weird", "bridge": "bridge", @@ -58,7 +60,7 @@ func TestNetworkModeTest(t *testing.T) { } func TestIpcModeTest(t *testing.T) { - ipcModes := map[IpcMode][]bool{ + ipcModes := map[container.IpcMode][]bool{ // private, host, container, valid "": {true, false, false, true}, "something:weird": {true, false, false, false}, @@ -82,7 +84,7 @@ func TestIpcModeTest(t *testing.T) { t.Fatalf("IpcMode.Valid for %v should have been %v but was %v", ipcMode, state[3], ipcMode.Valid()) } } - containerIpcModes := map[IpcMode]string{ + containerIpcModes := map[container.IpcMode]string{ "": "", "something": "", "something:weird": "weird", @@ -99,7 +101,7 @@ func TestIpcModeTest(t *testing.T) { } func TestUTSModeTest(t *testing.T) { - utsModes := map[UTSMode][]bool{ + utsModes := map[container.UTSMode][]bool{ // private, host, valid "": {true, false, true}, "something:weird": {true, false, false}, @@ -120,7 +122,7 @@ func TestUTSModeTest(t *testing.T) { } func TestPidModeTest(t *testing.T) { - pidModes := map[PidMode][]bool{ + pidModes := map[container.PidMode][]bool{ // private, host, valid "": {true, false, true}, "something:weird": {true, false, false}, @@ -141,13 +143,13 @@ func TestPidModeTest(t *testing.T) { } func TestRestartPolicy(t *testing.T) { - restartPolicies := map[RestartPolicy][]bool{ + restartPolicies := map[container.RestartPolicy][]bool{ // none, always, failure - RestartPolicy{}: {false, false, false}, - RestartPolicy{"something", 0}: {false, false, false}, - RestartPolicy{"no", 0}: {true, false, false}, - RestartPolicy{"always", 0}: {false, true, false}, - RestartPolicy{"on-failure", 0}: {false, false, true}, + container.RestartPolicy{}: {false, false, false}, + container.RestartPolicy{"something", 0}: {false, false, false}, + container.RestartPolicy{"no", 0}: {true, false, false}, + container.RestartPolicy{"always", 0}: {false, true, false}, + container.RestartPolicy{"on-failure", 0}: {false, false, true}, } for restartPolicy, state := range restartPolicies { if restartPolicy.IsNone() != state[0] { @@ -161,28 +163,6 @@ func TestRestartPolicy(t *testing.T) { } } } - -func TestMergeConfigs(t *testing.T) { - expectedHostname := "hostname" - expectedContainerIDFile := "containerIdFile" - config := &Config{ - Hostname: expectedHostname, - } - hostConfig := &HostConfig{ - ContainerIDFile: expectedContainerIDFile, - } - containerConfigWrapper := MergeConfigs(config, hostConfig) - if containerConfigWrapper.Config.Hostname != expectedHostname { - t.Fatalf("containerConfigWrapper config hostname expected %v got %v", expectedHostname, containerConfigWrapper.Config.Hostname) - } - if containerConfigWrapper.InnerHostConfig.ContainerIDFile != expectedContainerIDFile { - t.Fatalf("containerConfigWrapper hostconfig containerIdfile expected %v got %v", expectedContainerIDFile, containerConfigWrapper.InnerHostConfig.ContainerIDFile) - } - if containerConfigWrapper.Cpuset != "" { - t.Fatalf("Expected empty Cpuset, got %v", containerConfigWrapper.Cpuset) - } -} - func TestDecodeHostConfig(t *testing.T) { fixtures := []struct { file string diff --git a/components/engine/runconfig/hostconfig_unix.go b/components/engine/runconfig/hostconfig_unix.go index 7aad5a33f0..4c28799395 100644 --- a/components/engine/runconfig/hostconfig_unix.go +++ b/components/engine/runconfig/hostconfig_unix.go @@ -6,109 +6,25 @@ import ( "fmt" "runtime" "strings" + + "github.com/docker/docker/api/types/container" ) -// IsValid indicates is an isolation level is valid -func (i IsolationLevel) IsValid() bool { - return i.IsDefault() -} - -// IsPrivate indicates whether container uses it's private network stack. -func (n NetworkMode) IsPrivate() bool { - return !(n.IsHost() || n.IsContainer()) -} - -// IsDefault indicates whether container uses the default network stack. -func (n NetworkMode) IsDefault() bool { - return n == "default" -} - // DefaultDaemonNetworkMode returns the default network stack the daemon should // use. -func DefaultDaemonNetworkMode() NetworkMode { - return NetworkMode("bridge") -} - -// NetworkName returns the name of the network stack. -func (n NetworkMode) NetworkName() string { - if n.IsBridge() { - return "bridge" - } else if n.IsHost() { - return "host" - } else if n.IsContainer() { - return "container" - } else if n.IsNone() { - return "none" - } else if n.IsDefault() { - return "default" - } else if n.IsUserDefined() { - return n.UserDefined() - } - return "" -} - -// IsBridge indicates whether container uses the bridge network stack -func (n NetworkMode) IsBridge() bool { - return n == "bridge" -} - -// IsHost indicates whether container uses the host network stack. -func (n NetworkMode) IsHost() bool { - return n == "host" -} - -// IsContainer indicates whether container uses a container network stack. -func (n NetworkMode) IsContainer() bool { - parts := strings.SplitN(string(n), ":", 2) - return len(parts) > 1 && parts[0] == "container" -} - -// IsNone indicates whether container isn't using a network stack. -func (n NetworkMode) IsNone() bool { - return n == "none" -} - -// ConnectedContainer is the id of the container which network this container is connected to. -func (n NetworkMode) ConnectedContainer() string { - parts := strings.SplitN(string(n), ":", 2) - if len(parts) > 1 { - return parts[1] - } - return "" -} - -// IsUserDefined indicates user-created network -func (n NetworkMode) IsUserDefined() bool { - return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() +func DefaultDaemonNetworkMode() container.NetworkMode { + return container.NetworkMode("bridge") } // IsPreDefinedNetwork indicates if a network is predefined by the daemon func IsPreDefinedNetwork(network string) bool { - n := NetworkMode(network) + n := container.NetworkMode(network) return n.IsBridge() || n.IsHost() || n.IsNone() } -//UserDefined indicates user-created network -func (n NetworkMode) UserDefined() string { - if n.IsUserDefined() { - return string(n) - } - return "" -} - -// MergeConfigs merges the specified container Config and HostConfig. -// It creates a ContainerConfigWrapper. -func MergeConfigs(config *Config, hostConfig *HostConfig) *ContainerConfigWrapper { - return &ContainerConfigWrapper{ - config, - hostConfig, - "", nil, - } -} - // ValidateNetMode ensures that the various combinations of requested // network settings are valid. -func ValidateNetMode(c *Config, hc *HostConfig) error { +func ValidateNetMode(c *container.Config, hc *container.HostConfig) error { // We may not be passed a host config, such as in the case of docker commit if hc == nil { return nil @@ -161,7 +77,7 @@ func ValidateNetMode(c *Config, hc *HostConfig) error { // ValidateIsolationLevel performs platform specific validation of the // isolation level in the hostconfig structure. Linux only supports "default" // which is LXC container isolation -func ValidateIsolationLevel(hc *HostConfig) error { +func ValidateIsolationLevel(hc *container.HostConfig) error { // We may not be passed a host config, such as in the case of docker commit if hc == nil { return nil diff --git a/components/engine/runconfig/hostconfig_windows.go b/components/engine/runconfig/hostconfig_windows.go index 211c93b281..3cade744ad 100644 --- a/components/engine/runconfig/hostconfig_windows.go +++ b/components/engine/runconfig/hostconfig_windows.go @@ -3,49 +3,14 @@ package runconfig import ( "fmt" "strings" + + "github.com/docker/docker/api/types/container" ) -// IsDefault indicates whether container uses the default network stack. -func (n NetworkMode) IsDefault() bool { - return n == "default" -} - -// IsHyperV indicates the use of a Hyper-V partition for isolation -func (i IsolationLevel) IsHyperV() bool { - return strings.ToLower(string(i)) == "hyperv" -} - -// IsProcess indicates the use of process isolation -func (i IsolationLevel) IsProcess() bool { - return strings.ToLower(string(i)) == "process" -} - -// IsValid indicates is an isolation level is valid -func (i IsolationLevel) IsValid() bool { - return i.IsDefault() || i.IsHyperV() || i.IsProcess() -} - // DefaultDaemonNetworkMode returns the default network stack the daemon should // use. -func DefaultDaemonNetworkMode() NetworkMode { - return NetworkMode("default") -} - -// NetworkName returns the name of the network stack. -func (n NetworkMode) NetworkName() string { - if n.IsDefault() { - return "default" - } - return "" -} - -// MergeConfigs merges the specified container Config and HostConfig. -// It creates a ContainerConfigWrapper. -func MergeConfigs(config *Config, hostConfig *HostConfig) *ContainerConfigWrapper { - return &ContainerConfigWrapper{ - config, - hostConfig, - } +func DefaultDaemonNetworkMode() container.NetworkMode { + return container.NetworkMode("default") } // IsPreDefinedNetwork indicates if a network is predefined by the daemon @@ -55,7 +20,7 @@ func IsPreDefinedNetwork(network string) bool { // ValidateNetMode ensures that the various combinations of requested // network settings are valid. -func ValidateNetMode(c *Config, hc *HostConfig) error { +func ValidateNetMode(c *container.Config, hc *container.HostConfig) error { // We may not be passed a host config, such as in the case of docker commit if hc == nil { return nil @@ -72,7 +37,7 @@ func ValidateNetMode(c *Config, hc *HostConfig) error { // ValidateIsolationLevel performs platform specific validation of the // isolation level in the hostconfig structure. Windows supports 'default' (or // blank), 'process', or 'hyperv'. -func ValidateIsolationLevel(hc *HostConfig) error { +func ValidateIsolationLevel(hc *container.HostConfig) error { // We may not be passed a host config, such as in the case of docker commit if hc == nil { return nil diff --git a/components/engine/runconfig/merge.go b/components/engine/runconfig/merge.go index 0106c7ea11..d2e953df27 100644 --- a/components/engine/runconfig/merge.go +++ b/components/engine/runconfig/merge.go @@ -3,7 +3,8 @@ package runconfig import ( "strings" - "github.com/docker/docker/pkg/nat" + "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" ) // Merge merges two Config, the image container configuration (defaults values), @@ -11,7 +12,7 @@ import ( // by the cli. // It will mutate the specified user configuration (userConf) with the image // configuration where the user configuration is incomplete. -func Merge(userConf, imageConf *Config) error { +func Merge(userConf, imageConf *container.Config) error { if userConf.User == "" { userConf.User = imageConf.User } diff --git a/components/engine/runconfig/merge_test.go b/components/engine/runconfig/merge_test.go index 6237ee9df0..2499dbb252 100644 --- a/components/engine/runconfig/merge_test.go +++ b/components/engine/runconfig/merge_test.go @@ -3,7 +3,8 @@ package runconfig import ( "testing" - "github.com/docker/docker/pkg/nat" + "github.com/docker/docker/api/types/container" + "github.com/docker/go-connections/nat" ) func TestMerge(t *testing.T) { @@ -13,7 +14,7 @@ func TestMerge(t *testing.T) { portsImage := make(nat.PortSet) portsImage[newPortNoError("tcp", "1111")] = struct{}{} portsImage[newPortNoError("tcp", "2222")] = struct{}{} - configImage := &Config{ + configImage := &container.Config{ ExposedPorts: portsImage, Env: []string{"VAR1=1", "VAR2=2"}, Volumes: volumesImage, @@ -24,7 +25,7 @@ func TestMerge(t *testing.T) { portsUser[newPortNoError("tcp", "3333")] = struct{}{} volumesUser := make(map[string]struct{}) volumesUser["/test3"] = struct{}{} - configUser := &Config{ + configUser := &container.Config{ ExposedPorts: portsUser, Env: []string{"VAR2=3", "VAR3=3"}, Volumes: volumesUser, @@ -64,7 +65,7 @@ func TestMerge(t *testing.T) { if err != nil { t.Error(err) } - configImage2 := &Config{ + configImage2 := &container.Config{ ExposedPorts: ports, } diff --git a/components/engine/runconfig/parse.go b/components/engine/runconfig/parse.go index 7765d1bcc7..6c7060d543 100644 --- a/components/engine/runconfig/parse.go +++ b/components/engine/runconfig/parse.go @@ -6,14 +6,15 @@ import ( "strconv" "strings" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/opts" flag "github.com/docker/docker/pkg/mflag" "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/nat" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/stringutils" "github.com/docker/docker/volume" + "github.com/docker/go-connections/nat" "github.com/docker/go-units" ) @@ -47,7 +48,7 @@ var ( // Parse parses the specified args for the specified command and generates a Config, // a HostConfig and returns them with the specified command. // If the specified args are not valid, it will return an error. -func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) { +func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.HostConfig, *flag.FlagSet, error) { var ( // FIXME: use utils.ListOpts for attach and volumes? flAttach = opts.NewListOpts(opts.ValidateAttach) @@ -249,15 +250,15 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe var ( parsedArgs = cmd.Args() - runCmd *stringutils.StrSlice - entrypoint *stringutils.StrSlice + runCmd *strslice.StrSlice + entrypoint *strslice.StrSlice image = cmd.Arg(0) ) if len(parsedArgs) > 1 { - runCmd = stringutils.NewStrSlice(parsedArgs[1:]...) + runCmd = strslice.New(parsedArgs[1:]...) } if *flEntrypoint != "" { - entrypoint = stringutils.NewStrSlice(*flEntrypoint) + entrypoint = strslice.New(*flEntrypoint) } var ( @@ -300,7 +301,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe } // parse device mappings - deviceMappings := []DeviceMapping{} + deviceMappings := []container.DeviceMapping{} for _, device := range flDevices.GetAll() { deviceMapping, err := ParseDevice(device) if err != nil { @@ -321,17 +322,17 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe return nil, nil, cmd, err } - ipcMode := IpcMode(*flIpcMode) + ipcMode := container.IpcMode(*flIpcMode) if !ipcMode.Valid() { return nil, nil, cmd, fmt.Errorf("--ipc: invalid IPC mode") } - pidMode := PidMode(*flPidMode) + pidMode := container.PidMode(*flPidMode) if !pidMode.Valid() { return nil, nil, cmd, fmt.Errorf("--pid: invalid PID mode") } - utsMode := UTSMode(*flUTSMode) + utsMode := container.UTSMode(*flUTSMode) if !utsMode.Valid() { return nil, nil, cmd, fmt.Errorf("--uts: invalid UTS mode") } @@ -346,7 +347,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe return nil, nil, cmd, err } - resources := Resources{ + resources := container.Resources{ CgroupParent: *flCgroupParent, Memory: flMemory, MemoryReservation: MemoryReservation, @@ -369,7 +370,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe Devices: deviceMappings, } - config := &Config{ + config := &container.Config{ Hostname: hostname, Domainname: domainname, ExposedPorts: ports, @@ -394,7 +395,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe StopSignal: *flStopSignal, } - hostConfig := &HostConfig{ + hostConfig := &container.HostConfig{ Binds: binds, ContainerIDFile: *flContainerIDFile, OomScoreAdj: *flOomScoreAdj, @@ -412,19 +413,19 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe DNSOptions: flDNSOptions.GetAllOrEmpty(), ExtraHosts: flExtraHosts.GetAll(), VolumesFrom: flVolumesFrom.GetAll(), - NetworkMode: NetworkMode(*flNetMode), + NetworkMode: container.NetworkMode(*flNetMode), IpcMode: ipcMode, PidMode: pidMode, UTSMode: utsMode, - CapAdd: stringutils.NewStrSlice(flCapAdd.GetAll()...), - CapDrop: stringutils.NewStrSlice(flCapDrop.GetAll()...), + CapAdd: strslice.New(flCapAdd.GetAll()...), + CapDrop: strslice.New(flCapDrop.GetAll()...), GroupAdd: flGroupAdd.GetAll(), RestartPolicy: restartPolicy, SecurityOpt: flSecurityOpt.GetAll(), ReadonlyRootfs: *flReadonlyRootfs, - LogConfig: LogConfig{Type: *flLoggingDriver, Config: loggingOpts}, + LogConfig: container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts}, VolumeDriver: *flVolumeDriver, - Isolation: IsolationLevel(*flIsolation), + Isolation: container.IsolationLevel(*flIsolation), ShmSize: parsedShm, Resources: resources, Tmpfs: tmpfs, @@ -477,8 +478,8 @@ func parseLoggingOpts(loggingDriver string, loggingOpts []string) (map[string]st } // ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect -func ParseRestartPolicy(policy string) (RestartPolicy, error) { - p := RestartPolicy{} +func ParseRestartPolicy(policy string) (container.RestartPolicy, error) { + p := container.RestartPolicy{} if policy == "" { return p, nil @@ -516,20 +517,8 @@ func ParseRestartPolicy(policy string) (RestartPolicy, error) { return p, nil } -func parseKeyValueOpts(opts opts.ListOpts) ([]KeyValuePair, error) { - out := make([]KeyValuePair, opts.Len()) - for i, o := range opts.GetAll() { - k, v, err := parsers.ParseKeyValueOpt(o) - if err != nil { - return nil, err - } - out[i] = KeyValuePair{Key: k, Value: v} - } - return out, nil -} - -// ParseDevice parses a device mapping string to a DeviceMapping struct -func ParseDevice(device string) (DeviceMapping, error) { +// ParseDevice parses a device mapping string to a container.DeviceMapping struct +func ParseDevice(device string) (container.DeviceMapping, error) { src := "" dst := "" permissions := "rwm" @@ -548,14 +537,14 @@ func ParseDevice(device string) (DeviceMapping, error) { case 1: src = arr[0] default: - return DeviceMapping{}, fmt.Errorf("Invalid device specification: %s", device) + return container.DeviceMapping{}, fmt.Errorf("Invalid device specification: %s", device) } if dst == "" { dst = src } - deviceMapping := DeviceMapping{ + deviceMapping := container.DeviceMapping{ PathOnHost: src, PathInContainer: dst, CgroupPermissions: permissions, diff --git a/components/engine/runconfig/parse_test.go b/components/engine/runconfig/parse_test.go index 9abbe86460..7c48abe603 100644 --- a/components/engine/runconfig/parse_test.go +++ b/components/engine/runconfig/parse_test.go @@ -10,23 +10,24 @@ import ( "strings" "testing" + "github.com/docker/docker/api/types/container" flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/nat" + "github.com/docker/go-connections/nat" ) -func parseRun(args []string) (*Config, *HostConfig, *flag.FlagSet, error) { +func parseRun(args []string) (*container.Config, *container.HostConfig, *flag.FlagSet, error) { cmd := flag.NewFlagSet("run", flag.ContinueOnError) cmd.SetOutput(ioutil.Discard) cmd.Usage = nil return Parse(cmd, args) } -func parse(t *testing.T, args string) (*Config, *HostConfig, error) { +func parse(t *testing.T, args string) (*container.Config, *container.HostConfig, error) { config, hostConfig, _, err := parseRun(strings.Split(args+" ubuntu bash", " ")) return config, hostConfig, err } -func mustParse(t *testing.T, args string) (*Config, *HostConfig) { +func mustParse(t *testing.T, args string) (*container.Config, *container.HostConfig) { config, hostConfig, err := parse(t, args) if err != nil { t.Fatal(err) @@ -280,18 +281,18 @@ func TestDecodeContainerConfigVolumes(t *testing.T) { // passed into it. It returns a config and a hostconfig which can be // validated to ensure DecodeContainerConfig has manipulated the structures // correctly. -func callDecodeContainerConfig(volumes []string, binds []string) (*Config, *HostConfig, error) { +func callDecodeContainerConfig(volumes []string, binds []string) (*container.Config, *container.HostConfig, error) { var ( b []byte err error - c *Config - h *HostConfig + c *container.Config + h *container.HostConfig ) w := ContainerConfigWrapper{ - Config: &Config{ + Config: &container.Config{ Volumes: map[string]struct{}{}, }, - HostConfig: &HostConfig{ + HostConfig: &container.HostConfig{ NetworkMode: "none", Binds: binds, }, @@ -450,7 +451,7 @@ func TestParseWithExpose(t *testing.T) { } func TestParseDevice(t *testing.T) { - valids := map[string]DeviceMapping{ + valids := map[string]container.DeviceMapping{ "/dev/snd": { PathOnHost: "/dev/snd", PathInContainer: "/dev/snd", @@ -546,7 +547,7 @@ func TestParseRestartPolicy(t *testing.T) { "on-failure:invalid": `strconv.ParseInt: parsing "invalid": invalid syntax`, "on-failure:2:5": "restart count format is not valid, usage: 'on-failure:N' or 'on-failure'", } - valids := map[string]RestartPolicy{ + valids := map[string]container.RestartPolicy{ "": {}, "always": { Name: "always", diff --git a/components/engine/vendor/src/github.com/docker/go-connections/CONTRIBUTING.md b/components/engine/vendor/src/github.com/docker/go-connections/CONTRIBUTING.md new file mode 100644 index 0000000000..926dcc931d --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/CONTRIBUTING.md @@ -0,0 +1,55 @@ +# Contributing to Docker + +### Sign your work + +The sign-off is a simple line at the end of the explanation for the patch. Your +signature certifies that you wrote the patch or otherwise have the right to pass +it on as an open-source patch. The rules are pretty simple: if you can certify +the below (from [developercertificate.org](http://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +660 York Street, Suite 102, +San Francisco, CA 94110 USA + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +Then you just add a line to every git commit message: + + Signed-off-by: Joe Smith + +Use your real name (sorry, no pseudonyms or anonymous contributions.) + +If you set your `user.name` and `user.email` git configs, you can sign your +commit automatically with `git commit -s`. diff --git a/components/engine/vendor/src/github.com/docker/go-connections/LICENSE b/components/engine/vendor/src/github.com/docker/go-connections/LICENSE new file mode 100644 index 0000000000..b55b37bc31 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/components/engine/vendor/src/github.com/docker/go-connections/MAINTAINERS b/components/engine/vendor/src/github.com/docker/go-connections/MAINTAINERS new file mode 100644 index 0000000000..477be8b214 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/MAINTAINERS @@ -0,0 +1,27 @@ +# go-connections maintainers file +# +# This file describes who runs the docker/go-connections project and how. +# This is a living document - if you see something out of date or missing, speak up! +# +# It is structured to be consumable by both humans and programs. +# To extract its contents programmatically, use any TOML-compliant parser. +# +# This file is compiled into the MAINTAINERS file in docker/opensource. +# +[Org] + [Org."Core maintainers"] + people = [ + "calavera", + ] + +[people] + +# A reference list of all people associated with the project. +# All other sections should refer to people by their canonical key +# in the people section. + + # ADD YOURSELF HERE IN ALPHABETICAL ORDER + [people.calavera] + Name = "David Calavera" + Email = "david.calavera@gmail.com" + GitHub = "calavera" diff --git a/components/engine/vendor/src/github.com/docker/go-connections/README.md b/components/engine/vendor/src/github.com/docker/go-connections/README.md new file mode 100644 index 0000000000..d257e44fdc --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/README.md @@ -0,0 +1,13 @@ +[![GoDoc](https://godoc.org/github.com/docker/go-connections?status.svg)](https://godoc.org/github.com/docker/go-connections) + +# Introduction + +go-connections provides common package to work with network connections. + +## Usage + +See the [docs in godoc](https://godoc.org/github.com/docker/go-connections) for examples and documentation. + +## License + +go-connections is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text. diff --git a/components/engine/vendor/src/github.com/docker/go-connections/circle.yml b/components/engine/vendor/src/github.com/docker/go-connections/circle.yml new file mode 100644 index 0000000000..8a82ee8259 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/circle.yml @@ -0,0 +1,14 @@ +dependencies: + pre: + # setup ipv6 + - sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0 net.ipv6.conf.default.disable_ipv6=0 net.ipv6.conf.all.disable_ipv6=0 + post: + # install golint + - go get github.com/golang/lint/golint + +test: + pre: + # run analysis before tests + - go vet ./... + - test -z "$(golint ./... | tee /dev/stderr)" + - test -z "$(gofmt -s -l . | tee /dev/stderr)" diff --git a/components/engine/vendor/src/github.com/docker/go-connections/doc.go b/components/engine/vendor/src/github.com/docker/go-connections/doc.go new file mode 100644 index 0000000000..43e27247d4 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/doc.go @@ -0,0 +1,3 @@ +// Package connections provides libraries to work with network connections. +// This library is divided in several components for specific usage. +package connections diff --git a/components/engine/pkg/nat/nat.go b/components/engine/vendor/src/github.com/docker/go-connections/nat/nat.go similarity index 98% rename from components/engine/pkg/nat/nat.go rename to components/engine/vendor/src/github.com/docker/go-connections/nat/nat.go index 6595feb055..36b8555122 100644 --- a/components/engine/pkg/nat/nat.go +++ b/components/engine/vendor/src/github.com/docker/go-connections/nat/nat.go @@ -1,8 +1,6 @@ +// Package nat is a convenience package for manipulation of strings describing network ports. package nat -// nat is a convenience package for docker's manipulation of strings describing -// network ports. - import ( "fmt" "net" diff --git a/components/engine/pkg/nat/nat_test.go b/components/engine/vendor/src/github.com/docker/go-connections/nat/nat_test.go similarity index 100% rename from components/engine/pkg/nat/nat_test.go rename to components/engine/vendor/src/github.com/docker/go-connections/nat/nat_test.go diff --git a/components/engine/pkg/nat/sort.go b/components/engine/vendor/src/github.com/docker/go-connections/nat/sort.go similarity index 100% rename from components/engine/pkg/nat/sort.go rename to components/engine/vendor/src/github.com/docker/go-connections/nat/sort.go diff --git a/components/engine/pkg/nat/sort_test.go b/components/engine/vendor/src/github.com/docker/go-connections/nat/sort_test.go similarity index 100% rename from components/engine/pkg/nat/sort_test.go rename to components/engine/vendor/src/github.com/docker/go-connections/nat/sort_test.go diff --git a/components/engine/vendor/src/github.com/docker/go-connections/proxy/network_proxy_test.go b/components/engine/vendor/src/github.com/docker/go-connections/proxy/network_proxy_test.go new file mode 100644 index 0000000000..9e382567c5 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/proxy/network_proxy_test.go @@ -0,0 +1,216 @@ +package proxy + +import ( + "bytes" + "fmt" + "io" + "net" + "strings" + "testing" + "time" +) + +var testBuf = []byte("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo") +var testBufSize = len(testBuf) + +type EchoServer interface { + Run() + Close() + LocalAddr() net.Addr +} + +type TCPEchoServer struct { + listener net.Listener + testCtx *testing.T +} + +type UDPEchoServer struct { + conn net.PacketConn + testCtx *testing.T +} + +func NewEchoServer(t *testing.T, proto, address string) EchoServer { + var server EchoServer + if strings.HasPrefix(proto, "tcp") { + listener, err := net.Listen(proto, address) + if err != nil { + t.Fatal(err) + } + server = &TCPEchoServer{listener: listener, testCtx: t} + } else { + socket, err := net.ListenPacket(proto, address) + if err != nil { + t.Fatal(err) + } + server = &UDPEchoServer{conn: socket, testCtx: t} + } + return server +} + +func (server *TCPEchoServer) Run() { + go func() { + for { + client, err := server.listener.Accept() + if err != nil { + return + } + go func(client net.Conn) { + if _, err := io.Copy(client, client); err != nil { + server.testCtx.Logf("can't echo to the client: %v\n", err.Error()) + } + client.Close() + }(client) + } + }() +} + +func (server *TCPEchoServer) LocalAddr() net.Addr { return server.listener.Addr() } +func (server *TCPEchoServer) Close() { server.listener.Addr() } + +func (server *UDPEchoServer) Run() { + go func() { + readBuf := make([]byte, 1024) + for { + read, from, err := server.conn.ReadFrom(readBuf) + if err != nil { + return + } + for i := 0; i != read; { + written, err := server.conn.WriteTo(readBuf[i:read], from) + if err != nil { + break + } + i += written + } + } + }() +} + +func (server *UDPEchoServer) LocalAddr() net.Addr { return server.conn.LocalAddr() } +func (server *UDPEchoServer) Close() { server.conn.Close() } + +func testProxyAt(t *testing.T, proto string, proxy Proxy, addr string) { + defer proxy.Close() + go proxy.Run() + client, err := net.Dial(proto, addr) + if err != nil { + t.Fatalf("Can't connect to the proxy: %v", err) + } + defer client.Close() + client.SetDeadline(time.Now().Add(10 * time.Second)) + if _, err = client.Write(testBuf); err != nil { + t.Fatal(err) + } + recvBuf := make([]byte, testBufSize) + if _, err = client.Read(recvBuf); err != nil { + t.Fatal(err) + } + if !bytes.Equal(testBuf, recvBuf) { + t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf)) + } +} + +func testProxy(t *testing.T, proto string, proxy Proxy) { + testProxyAt(t, proto, proxy, proxy.FrontendAddr().String()) +} + +func TestTCP4Proxy(t *testing.T) { + backend := NewEchoServer(t, "tcp", "127.0.0.1:0") + defer backend.Close() + backend.Run() + frontendAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0} + proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) + if err != nil { + t.Fatal(err) + } + testProxy(t, "tcp", proxy) +} + +func TestTCP6Proxy(t *testing.T) { + backend := NewEchoServer(t, "tcp", "[::1]:0") + defer backend.Close() + backend.Run() + frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0} + proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) + if err != nil { + t.Fatal(err) + } + testProxy(t, "tcp", proxy) +} + +func TestTCPDualStackProxy(t *testing.T) { + // If I understand `godoc -src net favoriteAddrFamily` (used by the + // net.Listen* functions) correctly this should work, but it doesn't. + t.Skip("No support for dual stack yet") + backend := NewEchoServer(t, "tcp", "[::1]:0") + defer backend.Close() + backend.Run() + frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0} + proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) + if err != nil { + t.Fatal(err) + } + ipv4ProxyAddr := &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: proxy.FrontendAddr().(*net.TCPAddr).Port, + } + testProxyAt(t, "tcp", proxy, ipv4ProxyAddr.String()) +} + +func TestUDP4Proxy(t *testing.T) { + backend := NewEchoServer(t, "udp", "127.0.0.1:0") + defer backend.Close() + backend.Run() + frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0} + proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) + if err != nil { + t.Fatal(err) + } + testProxy(t, "udp", proxy) +} + +func TestUDP6Proxy(t *testing.T) { + backend := NewEchoServer(t, "udp", "[::1]:0") + defer backend.Close() + backend.Run() + frontendAddr := &net.UDPAddr{IP: net.IPv6loopback, Port: 0} + proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) + if err != nil { + t.Fatal(err) + } + testProxy(t, "udp", proxy) +} + +func TestUDPWriteError(t *testing.T) { + frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0} + // Hopefully, this port will be free: */ + backendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 25587} + proxy, err := NewProxy(frontendAddr, backendAddr) + if err != nil { + t.Fatal(err) + } + defer proxy.Close() + go proxy.Run() + client, err := net.Dial("udp", "127.0.0.1:25587") + if err != nil { + t.Fatalf("Can't connect to the proxy: %v", err) + } + defer client.Close() + // Make sure the proxy doesn't stop when there is no actual backend: + client.Write(testBuf) + client.Write(testBuf) + backend := NewEchoServer(t, "udp", "127.0.0.1:25587") + defer backend.Close() + backend.Run() + client.SetDeadline(time.Now().Add(10 * time.Second)) + if _, err = client.Write(testBuf); err != nil { + t.Fatal(err) + } + recvBuf := make([]byte, testBufSize) + if _, err = client.Read(recvBuf); err != nil { + t.Fatal(err) + } + if !bytes.Equal(testBuf, recvBuf) { + t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf)) + } +} diff --git a/components/engine/vendor/src/github.com/docker/go-connections/proxy/proxy.go b/components/engine/vendor/src/github.com/docker/go-connections/proxy/proxy.go new file mode 100644 index 0000000000..537aebb7ca --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/proxy/proxy.go @@ -0,0 +1,36 @@ +// Package proxy provides a network Proxy interface and implementations for TCP and UDP. +package proxy + +import ( + "fmt" + "net" +) + +// Proxy defines the behavior of a proxy. It forwards traffic back and forth +// between two endpoints : the frontend and the backend. +// It can be used to do software port-mapping between two addresses. +// e.g. forward all traffic between the frontend (host) 127.0.0.1:3000 +// to the backend (container) at 172.17.42.108:4000. +type Proxy interface { + // Run starts forwarding traffic back and forth between the front + // and back-end addresses. + Run() + // Close stops forwarding traffic and close both ends of the Proxy. + Close() + // FrontendAddr returns the address on which the proxy is listening. + FrontendAddr() net.Addr + // BackendAddr returns the proxied address. + BackendAddr() net.Addr +} + +// NewProxy creates a Proxy according to the specified frontendAddr and backendAddr. +func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) { + switch frontendAddr.(type) { + case *net.UDPAddr: + return NewUDPProxy(frontendAddr.(*net.UDPAddr), backendAddr.(*net.UDPAddr)) + case *net.TCPAddr: + return NewTCPProxy(frontendAddr.(*net.TCPAddr), backendAddr.(*net.TCPAddr)) + default: + panic(fmt.Errorf("Unsupported protocol")) + } +} diff --git a/components/engine/vendor/src/github.com/docker/go-connections/proxy/stub_proxy.go b/components/engine/vendor/src/github.com/docker/go-connections/proxy/stub_proxy.go new file mode 100644 index 0000000000..571749e467 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/proxy/stub_proxy.go @@ -0,0 +1,31 @@ +package proxy + +import ( + "net" +) + +// StubProxy is a proxy that is a stub (does nothing). +type StubProxy struct { + frontendAddr net.Addr + backendAddr net.Addr +} + +// Run does nothing. +func (p *StubProxy) Run() {} + +// Close does nothing. +func (p *StubProxy) Close() {} + +// FrontendAddr returns the frontend address. +func (p *StubProxy) FrontendAddr() net.Addr { return p.frontendAddr } + +// BackendAddr returns the backend address. +func (p *StubProxy) BackendAddr() net.Addr { return p.backendAddr } + +// NewStubProxy creates a new StubProxy +func NewStubProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) { + return &StubProxy{ + frontendAddr: frontendAddr, + backendAddr: backendAddr, + }, nil +} diff --git a/components/engine/vendor/src/github.com/docker/go-connections/proxy/tcp_proxy.go b/components/engine/vendor/src/github.com/docker/go-connections/proxy/tcp_proxy.go new file mode 100644 index 0000000000..3cd742af76 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/proxy/tcp_proxy.go @@ -0,0 +1,99 @@ +package proxy + +import ( + "io" + "net" + "syscall" + + "github.com/Sirupsen/logrus" +) + +// TCPProxy is a proxy for TCP connections. It implements the Proxy interface to +// handle TCP traffic forwarding between the frontend and backend addresses. +type TCPProxy struct { + listener *net.TCPListener + frontendAddr *net.TCPAddr + backendAddr *net.TCPAddr +} + +// NewTCPProxy creates a new TCPProxy. +func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) { + listener, err := net.ListenTCP("tcp", frontendAddr) + if err != nil { + return nil, err + } + // If the port in frontendAddr was 0 then ListenTCP will have a picked + // a port to listen on, hence the call to Addr to get that actual port: + return &TCPProxy{ + listener: listener, + frontendAddr: listener.Addr().(*net.TCPAddr), + backendAddr: backendAddr, + }, nil +} + +func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) { + backend, err := net.DialTCP("tcp", nil, proxy.backendAddr) + if err != nil { + logrus.Printf("Can't forward traffic to backend tcp/%v: %s\n", proxy.backendAddr, err) + client.Close() + return + } + + event := make(chan int64) + var broker = func(to, from *net.TCPConn) { + written, err := io.Copy(to, from) + if err != nil { + // If the socket we are writing to is shutdown with + // SHUT_WR, forward it to the other end of the pipe: + if err, ok := err.(*net.OpError); ok && err.Err == syscall.EPIPE { + from.CloseWrite() + } + } + to.CloseRead() + event <- written + } + + go broker(client, backend) + go broker(backend, client) + + var transferred int64 + for i := 0; i < 2; i++ { + select { + case written := <-event: + transferred += written + case <-quit: + // Interrupt the two brokers and "join" them. + client.Close() + backend.Close() + for ; i < 2; i++ { + transferred += <-event + } + return + } + } + client.Close() + backend.Close() +} + +// Run starts forwarding the traffic using TCP. +func (proxy *TCPProxy) Run() { + quit := make(chan bool) + defer close(quit) + for { + client, err := proxy.listener.Accept() + if err != nil { + logrus.Printf("Stopping proxy on tcp/%v for tcp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err) + return + } + go proxy.clientLoop(client.(*net.TCPConn), quit) + } +} + +// Close stops forwarding the traffic. +func (proxy *TCPProxy) Close() { proxy.listener.Close() } + +// FrontendAddr returns the TCP address on which the proxy is listening. +func (proxy *TCPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr } + +// BackendAddr returns the TCP proxied address. +func (proxy *TCPProxy) BackendAddr() net.Addr { return proxy.backendAddr } diff --git a/components/engine/vendor/src/github.com/docker/go-connections/proxy/udp_proxy.go b/components/engine/vendor/src/github.com/docker/go-connections/proxy/udp_proxy.go new file mode 100644 index 0000000000..b8375c374f --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/proxy/udp_proxy.go @@ -0,0 +1,169 @@ +package proxy + +import ( + "encoding/binary" + "net" + "strings" + "sync" + "syscall" + "time" + + "github.com/Sirupsen/logrus" +) + +const ( + // UDPConnTrackTimeout is the timeout used for UDP connection tracking + UDPConnTrackTimeout = 90 * time.Second + // UDPBufSize is the buffer size for the UDP proxy + UDPBufSize = 65507 +) + +// A net.Addr where the IP is split into two fields so you can use it as a key +// in a map: +type connTrackKey struct { + IPHigh uint64 + IPLow uint64 + Port int +} + +func newConnTrackKey(addr *net.UDPAddr) *connTrackKey { + if len(addr.IP) == net.IPv4len { + return &connTrackKey{ + IPHigh: 0, + IPLow: uint64(binary.BigEndian.Uint32(addr.IP)), + Port: addr.Port, + } + } + return &connTrackKey{ + IPHigh: binary.BigEndian.Uint64(addr.IP[:8]), + IPLow: binary.BigEndian.Uint64(addr.IP[8:]), + Port: addr.Port, + } +} + +type connTrackMap map[connTrackKey]*net.UDPConn + +// UDPProxy is proxy for which handles UDP datagrams. It implements the Proxy +// interface to handle UDP traffic forwarding between the frontend and backend +// addresses. +type UDPProxy struct { + listener *net.UDPConn + frontendAddr *net.UDPAddr + backendAddr *net.UDPAddr + connTrackTable connTrackMap + connTrackLock sync.Mutex +} + +// NewUDPProxy creates a new UDPProxy. +func NewUDPProxy(frontendAddr, backendAddr *net.UDPAddr) (*UDPProxy, error) { + listener, err := net.ListenUDP("udp", frontendAddr) + if err != nil { + return nil, err + } + return &UDPProxy{ + listener: listener, + frontendAddr: listener.LocalAddr().(*net.UDPAddr), + backendAddr: backendAddr, + connTrackTable: make(connTrackMap), + }, nil +} + +func (proxy *UDPProxy) replyLoop(proxyConn *net.UDPConn, clientAddr *net.UDPAddr, clientKey *connTrackKey) { + defer func() { + proxy.connTrackLock.Lock() + delete(proxy.connTrackTable, *clientKey) + proxy.connTrackLock.Unlock() + proxyConn.Close() + }() + + readBuf := make([]byte, UDPBufSize) + for { + proxyConn.SetReadDeadline(time.Now().Add(UDPConnTrackTimeout)) + again: + read, err := proxyConn.Read(readBuf) + if err != nil { + if err, ok := err.(*net.OpError); ok && err.Err == syscall.ECONNREFUSED { + // This will happen if the last write failed + // (e.g: nothing is actually listening on the + // proxied port on the container), ignore it + // and continue until UDPConnTrackTimeout + // expires: + goto again + } + return + } + for i := 0; i != read; { + written, err := proxy.listener.WriteToUDP(readBuf[i:read], clientAddr) + if err != nil { + return + } + i += written + } + } +} + +// Run starts forwarding the traffic using UDP. +func (proxy *UDPProxy) Run() { + readBuf := make([]byte, UDPBufSize) + for { + read, from, err := proxy.listener.ReadFromUDP(readBuf) + if err != nil { + // NOTE: Apparently ReadFrom doesn't return + // ECONNREFUSED like Read do (see comment in + // UDPProxy.replyLoop) + if !isClosedError(err) { + logrus.Printf("Stopping proxy on udp/%v for udp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err) + } + break + } + + fromKey := newConnTrackKey(from) + proxy.connTrackLock.Lock() + proxyConn, hit := proxy.connTrackTable[*fromKey] + if !hit { + proxyConn, err = net.DialUDP("udp", nil, proxy.backendAddr) + if err != nil { + logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err) + proxy.connTrackLock.Unlock() + continue + } + proxy.connTrackTable[*fromKey] = proxyConn + go proxy.replyLoop(proxyConn, from, fromKey) + } + proxy.connTrackLock.Unlock() + for i := 0; i != read; { + written, err := proxyConn.Write(readBuf[i:read]) + if err != nil { + logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err) + break + } + i += written + } + } +} + +// Close stops forwarding the traffic. +func (proxy *UDPProxy) Close() { + proxy.listener.Close() + proxy.connTrackLock.Lock() + defer proxy.connTrackLock.Unlock() + for _, conn := range proxy.connTrackTable { + conn.Close() + } +} + +// FrontendAddr returns the UDP address on which the proxy is listening. +func (proxy *UDPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr } + +// BackendAddr returns the proxied UDP address. +func (proxy *UDPProxy) BackendAddr() net.Addr { return proxy.backendAddr } + +func isClosedError(err error) bool { + /* This comparison is ugly, but unfortunately, net.go doesn't export errClosing. + * See: + * http://golang.org/src/pkg/net/net.go + * https://code.google.com/p/go/issues/detail?id=4337 + * https://groups.google.com/forum/#!msg/golang-nuts/0_aaCvBmOcM/SptmDyX1XJMJ + */ + return strings.HasSuffix(err.Error(), "use of closed network connection") +} diff --git a/components/engine/vendor/src/github.com/docker/go-connections/sockets/README.md b/components/engine/vendor/src/github.com/docker/go-connections/sockets/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/components/engine/vendor/src/github.com/docker/go-connections/sockets/tcp_socket.go b/components/engine/vendor/src/github.com/docker/go-connections/sockets/tcp_socket.go new file mode 100644 index 0000000000..5d80e4a305 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/sockets/tcp_socket.go @@ -0,0 +1,43 @@ +// Package sockets provides helper functions to create and configure Unix or TCP sockets. +package sockets + +import ( + "crypto/tls" + "net" + "net/http" + "time" +) + +// NewTCPSocket creates a TCP socket listener with the specified address and +// and the specified tls configuration. If TLSConfig is set, will encapsulate the +// TCP listener inside a TLS one. +func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) { + l, err := net.Listen("tcp", addr) + if err != nil { + return nil, err + } + if tlsConfig != nil { + tlsConfig.NextProtos = []string{"http/1.1"} + l = tls.NewListener(l, tlsConfig) + } + return l, nil +} + +// ConfigureTCPTransport configures the specified Transport according to the +// specified proto and addr. +// If the proto is unix (using a unix socket to communicate) the compression +// is disabled. +func ConfigureTCPTransport(tr *http.Transport, proto, addr string) { + // Why 32? See https://github.com/docker/docker/pull/8035. + timeout := 32 * time.Second + if proto == "unix" { + // No need for compression in local communications. + tr.DisableCompression = true + tr.Dial = func(_, _ string) (net.Conn, error) { + return net.DialTimeout(proto, addr, timeout) + } + } else { + tr.Proxy = http.ProxyFromEnvironment + tr.Dial = (&net.Dialer{Timeout: timeout}).Dial + } +} diff --git a/components/engine/vendor/src/github.com/docker/go-connections/sockets/unix_socket.go b/components/engine/vendor/src/github.com/docker/go-connections/sockets/unix_socket.go new file mode 100644 index 0000000000..c10acedca2 --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/sockets/unix_socket.go @@ -0,0 +1,80 @@ +// +build linux freebsd + +package sockets + +import ( + "fmt" + "net" + "os" + "strconv" + "syscall" + + "github.com/Sirupsen/logrus" + "github.com/opencontainers/runc/libcontainer/user" +) + +// NewUnixSocket creates a unix socket with the specified path and group. +func NewUnixSocket(path, group string) (net.Listener, error) { + if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) { + return nil, err + } + mask := syscall.Umask(0777) + defer syscall.Umask(mask) + l, err := net.Listen("unix", path) + if err != nil { + return nil, err + } + if err := setSocketGroup(path, group); err != nil { + l.Close() + return nil, err + } + if err := os.Chmod(path, 0660); err != nil { + l.Close() + return nil, err + } + return l, nil +} + +func setSocketGroup(path, group string) error { + if group == "" { + return nil + } + if err := changeGroup(path, group); err != nil { + if group != "docker" { + return err + } + logrus.Debugf("Warning: could not change group %s to docker: %v", path, err) + } + return nil +} + +func changeGroup(path string, nameOrGid string) error { + gid, err := lookupGidByName(nameOrGid) + if err != nil { + return err + } + logrus.Debugf("%s group found. gid: %d", nameOrGid, gid) + return os.Chown(path, 0, gid) +} + +func lookupGidByName(nameOrGid string) (int, error) { + groupFile, err := user.GetGroupPath() + if err != nil { + return -1, err + } + groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool { + return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid + }) + if err != nil { + return -1, err + } + if groups != nil && len(groups) > 0 { + return groups[0].Gid, nil + } + gid, err := strconv.Atoi(nameOrGid) + if err == nil { + logrus.Warnf("Could not find GID %d", gid) + return gid, nil + } + return -1, fmt.Errorf("Group %s not found", nameOrGid) +} diff --git a/components/engine/vendor/src/github.com/docker/go-connections/tlsconfig/config.go b/components/engine/vendor/src/github.com/docker/go-connections/tlsconfig/config.go new file mode 100644 index 0000000000..e3dfad1f0e --- /dev/null +++ b/components/engine/vendor/src/github.com/docker/go-connections/tlsconfig/config.go @@ -0,0 +1,133 @@ +// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers. +// +// As a reminder from https://golang.org/pkg/crypto/tls/#Config: +// A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified. +// A Config may be reused; the tls package will also not modify it. +package tlsconfig + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "io/ioutil" + "os" + + "github.com/Sirupsen/logrus" +) + +// Options represents the information needed to create client and server TLS configurations. +type Options struct { + CAFile string + + // If either CertFile or KeyFile is empty, Client() will not load them + // preventing the client from authenticating to the server. + // However, Server() requires them and will error out if they are empty. + CertFile string + KeyFile string + + // client-only option + InsecureSkipVerify bool + // server-only option + ClientAuth tls.ClientAuthType +} + +// Extra (server-side) accepted CBC cipher suites - will phase out in the future +var acceptedCBCCiphers = []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + tls.TLS_RSA_WITH_AES_256_CBC_SHA, + tls.TLS_RSA_WITH_AES_128_CBC_SHA, +} + +// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set) +var clientCipherSuites = []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, +} + +// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls +// options struct but wants to use a commonly accepted set of TLS cipher suites, with +// known weak algorithms removed. +var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...) + +// ServerDefault is a secure-enough TLS configuration for the server TLS configuration. +var ServerDefault = tls.Config{ + // Avoid fallback to SSL protocols < TLS1.0 + MinVersion: tls.VersionTLS10, + PreferServerCipherSuites: true, + CipherSuites: DefaultServerAcceptedCiphers, +} + +// ClientDefault is a secure-enough TLS configuration for the client TLS configuration. +var ClientDefault = tls.Config{ + // Prefer TLS1.2 as the client minimum + MinVersion: tls.VersionTLS12, + CipherSuites: clientCipherSuites, +} + +// certPool returns an X.509 certificate pool from `caFile`, the certificate file. +func certPool(caFile string) (*x509.CertPool, error) { + // If we should verify the server, we need to load a trusted ca + certPool := x509.NewCertPool() + pem, err := ioutil.ReadFile(caFile) + if err != nil { + return nil, fmt.Errorf("Could not read CA certificate %q: %v", caFile, err) + } + if !certPool.AppendCertsFromPEM(pem) { + return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile) + } + s := certPool.Subjects() + subjects := make([]string, len(s)) + for i, subject := range s { + subjects[i] = string(subject) + } + logrus.Debugf("Trusting certs with subjects: %v", subjects) + return certPool, nil +} + +// Client returns a TLS configuration meant to be used by a client. +func Client(options Options) (*tls.Config, error) { + tlsConfig := ClientDefault + tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify + if !options.InsecureSkipVerify { + CAs, err := certPool(options.CAFile) + if err != nil { + return nil, err + } + tlsConfig.RootCAs = CAs + } + + if options.CertFile != "" && options.KeyFile != "" { + tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) + if err != nil { + return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err) + } + tlsConfig.Certificates = []tls.Certificate{tlsCert} + } + + return &tlsConfig, nil +} + +// Server returns a TLS configuration meant to be used by a server. +func Server(options Options) (*tls.Config, error) { + tlsConfig := ServerDefault + tlsConfig.ClientAuth = options.ClientAuth + tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) + if err != nil { + if os.IsNotExist(err) { + return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err) + } + return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err) + } + tlsConfig.Certificates = []tls.Certificate{tlsCert} + if options.ClientAuth >= tls.VerifyClientCertIfGiven { + CAs, err := certPool(options.CAFile) + if err != nil { + return nil, err + } + tlsConfig.ClientCAs = CAs + } + return &tlsConfig, nil +}