Move the canonical run configuration objects to a sub-package
* Config is now runconfig.Config * HostConfig is now runconfig.HostConfig * MergeConfig is now runconfig.Merge * CompareConfig is now runconfig.Compare * ParseRun is now runconfig.Parse * ContainerConfigFromJob is now runconfig.ContainerConfigFromJob * ContainerHostConfigFromJob is now runconfig.ContainerHostConfigFromJob This facilitates refactoring commands.go and shrinks the core. Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
This commit is contained in:
parent
9a9690360c
commit
6393c38339
11
buildfile.go
11
buildfile.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/auth"
|
"github.com/dotcloud/docker/auth"
|
||||||
"github.com/dotcloud/docker/registry"
|
"github.com/dotcloud/docker/registry"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -38,7 +39,7 @@ type buildFile struct {
|
||||||
|
|
||||||
image string
|
image string
|
||||||
maintainer string
|
maintainer string
|
||||||
config *Config
|
config *runconfig.Config
|
||||||
|
|
||||||
contextPath string
|
contextPath string
|
||||||
context *utils.TarSum
|
context *utils.TarSum
|
||||||
|
@ -101,7 +102,7 @@ func (b *buildFile) CmdFrom(name string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.image = image.ID
|
b.image = image.ID
|
||||||
b.config = &Config{}
|
b.config = &runconfig.Config{}
|
||||||
if image.Config != nil {
|
if image.Config != nil {
|
||||||
b.config = image.Config
|
b.config = image.Config
|
||||||
}
|
}
|
||||||
|
@ -158,14 +159,14 @@ func (b *buildFile) CmdRun(args string) error {
|
||||||
if b.image == "" {
|
if b.image == "" {
|
||||||
return fmt.Errorf("Please provide a source image with `from` prior to run")
|
return fmt.Errorf("Please provide a source image with `from` prior to run")
|
||||||
}
|
}
|
||||||
config, _, _, err := ParseRun(append([]string{b.image}, b.buildCmdFromJson(args)...), nil)
|
config, _, _, err := runconfig.Parse(append([]string{b.image}, b.buildCmdFromJson(args)...), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := b.config.Cmd
|
cmd := b.config.Cmd
|
||||||
b.config.Cmd = nil
|
b.config.Cmd = nil
|
||||||
MergeConfig(b.config, config)
|
runconfig.Merge(b.config, config)
|
||||||
|
|
||||||
defer func(cmd []string) { b.config.Cmd = cmd }(cmd)
|
defer func(cmd []string) { b.config.Cmd = cmd }(cmd)
|
||||||
|
|
||||||
|
@ -742,7 +743,7 @@ func NewBuildFile(srv *Server, outStream, errStream io.Writer, verbose, utilizeC
|
||||||
return &buildFile{
|
return &buildFile{
|
||||||
runtime: srv.runtime,
|
runtime: srv.runtime,
|
||||||
srv: srv,
|
srv: srv,
|
||||||
config: &Config{},
|
config: &runconfig.Config{},
|
||||||
outStream: outStream,
|
outStream: outStream,
|
||||||
errStream: errStream,
|
errStream: errStream,
|
||||||
tmpContainers: make(map[string]struct{}),
|
tmpContainers: make(map[string]struct{}),
|
||||||
|
|
212
commands.go
212
commands.go
|
@ -15,10 +15,9 @@ import (
|
||||||
"github.com/dotcloud/docker/engine"
|
"github.com/dotcloud/docker/engine"
|
||||||
"github.com/dotcloud/docker/nat"
|
"github.com/dotcloud/docker/nat"
|
||||||
flag "github.com/dotcloud/docker/pkg/mflag"
|
flag "github.com/dotcloud/docker/pkg/mflag"
|
||||||
"github.com/dotcloud/docker/pkg/opts"
|
|
||||||
"github.com/dotcloud/docker/pkg/sysinfo"
|
|
||||||
"github.com/dotcloud/docker/pkg/term"
|
"github.com/dotcloud/docker/pkg/term"
|
||||||
"github.com/dotcloud/docker/registry"
|
"github.com/dotcloud/docker/registry"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -1449,11 +1448,11 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
|
||||||
v.Set("comment", *flComment)
|
v.Set("comment", *flComment)
|
||||||
v.Set("author", *flAuthor)
|
v.Set("author", *flAuthor)
|
||||||
var (
|
var (
|
||||||
config *Config
|
config *runconfig.Config
|
||||||
env engine.Env
|
env engine.Env
|
||||||
)
|
)
|
||||||
if *flConfig != "" {
|
if *flConfig != "" {
|
||||||
config = &Config{}
|
config = &runconfig.Config{}
|
||||||
if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
|
if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1743,210 +1742,9 @@ func (cli *DockerCli) CmdTag(args ...string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME Only used in tests
|
|
||||||
func ParseRun(args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
|
||||||
cmd := flag.NewFlagSet("run", flag.ContinueOnError)
|
|
||||||
cmd.SetOutput(ioutil.Discard)
|
|
||||||
cmd.Usage = nil
|
|
||||||
return parseRun(cmd, args, sysInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
|
||||||
var (
|
|
||||||
// FIXME: use utils.ListOpts for attach and volumes?
|
|
||||||
flAttach = opts.NewListOpts(opts.ValidateAttach)
|
|
||||||
flVolumes = opts.NewListOpts(opts.ValidatePath)
|
|
||||||
flLinks = opts.NewListOpts(opts.ValidateLink)
|
|
||||||
flEnv = opts.NewListOpts(opts.ValidateEnv)
|
|
||||||
|
|
||||||
flPublish opts.ListOpts
|
|
||||||
flExpose opts.ListOpts
|
|
||||||
flDns opts.ListOpts
|
|
||||||
flVolumesFrom opts.ListOpts
|
|
||||||
flLxcOpts opts.ListOpts
|
|
||||||
|
|
||||||
flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
|
|
||||||
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: Run container in the background, print new container id")
|
|
||||||
flNetwork = cmd.Bool([]string{"n", "-networking"}, true, "Enable networking for this container")
|
|
||||||
flPrivileged = cmd.Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
|
|
||||||
flPublishAll = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to the host interfaces")
|
|
||||||
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")
|
|
||||||
flContainerIDFile = cmd.String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
|
|
||||||
flEntrypoint = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default entrypoint of the image")
|
|
||||||
flHostname = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
|
|
||||||
flMemoryString = cmd.String([]string{"m", "-memory"}, "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
|
|
||||||
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID")
|
|
||||||
flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
|
|
||||||
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
|
||||||
|
|
||||||
// For documentation purpose
|
|
||||||
_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
||||||
_ = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to stdin, stdout or stderr.")
|
|
||||||
cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
|
|
||||||
cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container (name:alias)")
|
|
||||||
cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables")
|
|
||||||
|
|
||||||
cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat))
|
|
||||||
cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
|
|
||||||
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
|
||||||
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
|
||||||
cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
|
||||||
|
|
||||||
if err := cmd.Parse(args); err != nil {
|
|
||||||
return nil, nil, cmd, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the kernel supports memory limit cgroup.
|
|
||||||
if sysInfo != nil && *flMemoryString != "" && !sysInfo.MemoryLimit {
|
|
||||||
*flMemoryString = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate input params
|
|
||||||
if *flDetach && flAttach.Len() > 0 {
|
|
||||||
return nil, nil, cmd, ErrConflictAttachDetach
|
|
||||||
}
|
|
||||||
if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
|
|
||||||
return nil, nil, cmd, ErrInvalidWorikingDirectory
|
|
||||||
}
|
|
||||||
if *flDetach && *flAutoRemove {
|
|
||||||
return nil, nil, cmd, ErrConflictDetachAutoRemove
|
|
||||||
}
|
|
||||||
|
|
||||||
// If neither -d or -a are set, attach to everything by default
|
|
||||||
if flAttach.Len() == 0 && !*flDetach {
|
|
||||||
if !*flDetach {
|
|
||||||
flAttach.Set("stdout")
|
|
||||||
flAttach.Set("stderr")
|
|
||||||
if *flStdin {
|
|
||||||
flAttach.Set("stdin")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var flMemory int64
|
|
||||||
if *flMemoryString != "" {
|
|
||||||
parsedMemory, err := utils.RAMInBytes(*flMemoryString)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, cmd, err
|
|
||||||
}
|
|
||||||
flMemory = parsedMemory
|
|
||||||
}
|
|
||||||
|
|
||||||
var binds []string
|
|
||||||
// add any bind targets to the list of container volumes
|
|
||||||
for bind := range flVolumes.GetMap() {
|
|
||||||
if arr := strings.Split(bind, ":"); len(arr) > 1 {
|
|
||||||
if arr[0] == "/" {
|
|
||||||
return nil, nil, cmd, fmt.Errorf("Invalid bind mount: source can't be '/'")
|
|
||||||
}
|
|
||||||
dstDir := arr[1]
|
|
||||||
flVolumes.Set(dstDir)
|
|
||||||
binds = append(binds, bind)
|
|
||||||
flVolumes.Delete(bind)
|
|
||||||
} else if bind == "/" {
|
|
||||||
return nil, nil, cmd, fmt.Errorf("Invalid volume: path can't be '/'")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
parsedArgs = cmd.Args()
|
|
||||||
runCmd []string
|
|
||||||
entrypoint []string
|
|
||||||
image string
|
|
||||||
)
|
|
||||||
if len(parsedArgs) >= 1 {
|
|
||||||
image = cmd.Arg(0)
|
|
||||||
}
|
|
||||||
if len(parsedArgs) > 1 {
|
|
||||||
runCmd = parsedArgs[1:]
|
|
||||||
}
|
|
||||||
if *flEntrypoint != "" {
|
|
||||||
entrypoint = []string{*flEntrypoint}
|
|
||||||
}
|
|
||||||
|
|
||||||
lxcConf, err := parseLxcConfOpts(flLxcOpts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, cmd, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
domainname string
|
|
||||||
hostname = *flHostname
|
|
||||||
parts = strings.SplitN(hostname, ".", 2)
|
|
||||||
)
|
|
||||||
if len(parts) > 1 {
|
|
||||||
hostname = parts[0]
|
|
||||||
domainname = parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
ports, portBindings, err := nat.ParsePortSpecs(flPublish.GetAll())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, cmd, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge in exposed ports to the map of published ports
|
|
||||||
for _, e := range flExpose.GetAll() {
|
|
||||||
if strings.Contains(e, ":") {
|
|
||||||
return nil, nil, cmd, fmt.Errorf("Invalid port format for --expose: %s", e)
|
|
||||||
}
|
|
||||||
p := nat.NewPort(nat.SplitProtoPort(e))
|
|
||||||
if _, exists := ports[p]; !exists {
|
|
||||||
ports[p] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &Config{
|
|
||||||
Hostname: hostname,
|
|
||||||
Domainname: domainname,
|
|
||||||
PortSpecs: nil, // Deprecated
|
|
||||||
ExposedPorts: ports,
|
|
||||||
User: *flUser,
|
|
||||||
Tty: *flTty,
|
|
||||||
NetworkDisabled: !*flNetwork,
|
|
||||||
OpenStdin: *flStdin,
|
|
||||||
Memory: flMemory,
|
|
||||||
CpuShares: *flCpuShares,
|
|
||||||
AttachStdin: flAttach.Get("stdin"),
|
|
||||||
AttachStdout: flAttach.Get("stdout"),
|
|
||||||
AttachStderr: flAttach.Get("stderr"),
|
|
||||||
Env: flEnv.GetAll(),
|
|
||||||
Cmd: runCmd,
|
|
||||||
Dns: flDns.GetAll(),
|
|
||||||
Image: image,
|
|
||||||
Volumes: flVolumes.GetMap(),
|
|
||||||
VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","),
|
|
||||||
Entrypoint: entrypoint,
|
|
||||||
WorkingDir: *flWorkingDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
hostConfig := &HostConfig{
|
|
||||||
Binds: binds,
|
|
||||||
ContainerIDFile: *flContainerIDFile,
|
|
||||||
LxcConf: lxcConf,
|
|
||||||
Privileged: *flPrivileged,
|
|
||||||
PortBindings: portBindings,
|
|
||||||
Links: flLinks.GetAll(),
|
|
||||||
PublishAllPorts: *flPublishAll,
|
|
||||||
}
|
|
||||||
|
|
||||||
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
|
||||||
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
|
||||||
config.MemorySwap = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// When allocating stdin in attached mode, close stdin at client disconnect
|
|
||||||
if config.OpenStdin && config.AttachStdin {
|
|
||||||
config.StdinOnce = true
|
|
||||||
}
|
|
||||||
return config, hostConfig, cmd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cli *DockerCli) CmdRun(args ...string) error {
|
func (cli *DockerCli) CmdRun(args ...string) error {
|
||||||
config, hostConfig, cmd, err := parseRun(cli.Subcmd("run", "[OPTIONS] IMAGE [COMMAND] [ARG...]", "Run a command in a new container"), args, nil)
|
// FIXME: just use runconfig.Parse already
|
||||||
|
config, hostConfig, cmd, err := runconfig.ParseSubcommand(cli.Subcmd("run", "[OPTIONS] IMAGE [COMMAND] [ARG...]", "Run a command in a new container"), args, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parse(t *testing.T, args string) (*Config, *HostConfig, error) {
|
func parse(t *testing.T, args string) (*runconfig.Config, *runconfig.HostConfig, error) {
|
||||||
config, hostConfig, _, err := ParseRun(strings.Split(args+" ubuntu bash", " "), nil)
|
config, hostConfig, _, err := runconfig.Parse(strings.Split(args+" ubuntu bash", " "), nil)
|
||||||
return config, hostConfig, err
|
return config, hostConfig, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustParse(t *testing.T, args string) (*Config, *HostConfig) {
|
func mustParse(t *testing.T, args string) (*runconfig.Config, *runconfig.HostConfig) {
|
||||||
config, hostConfig, err := parse(t, args)
|
config, hostConfig, err := parse(t, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
117
container.go
117
container.go
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/dotcloud/docker/nat"
|
"github.com/dotcloud/docker/nat"
|
||||||
"github.com/dotcloud/docker/pkg/mount"
|
"github.com/dotcloud/docker/pkg/mount"
|
||||||
"github.com/dotcloud/docker/pkg/term"
|
"github.com/dotcloud/docker/pkg/term"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"github.com/kr/pty"
|
"github.com/kr/pty"
|
||||||
"io"
|
"io"
|
||||||
|
@ -42,7 +43,7 @@ type Container struct {
|
||||||
Path string
|
Path string
|
||||||
Args []string
|
Args []string
|
||||||
|
|
||||||
Config *Config
|
Config *runconfig.Config
|
||||||
State State
|
State State
|
||||||
Image string
|
Image string
|
||||||
|
|
||||||
|
@ -68,109 +69,11 @@ type Container struct {
|
||||||
// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
|
// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
|
||||||
// Easier than migrating older container configs :)
|
// Easier than migrating older container configs :)
|
||||||
VolumesRW map[string]bool
|
VolumesRW map[string]bool
|
||||||
hostConfig *HostConfig
|
hostConfig *runconfig.HostConfig
|
||||||
|
|
||||||
activeLinks map[string]*Link
|
activeLinks map[string]*Link
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: the Config structure 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.
|
|
||||||
type Config struct {
|
|
||||||
Hostname string
|
|
||||||
Domainname string
|
|
||||||
User string
|
|
||||||
Memory int64 // Memory limit (in bytes)
|
|
||||||
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
|
|
||||||
CpuShares int64 // CPU shares (relative weight vs. other containers)
|
|
||||||
AttachStdin bool
|
|
||||||
AttachStdout bool
|
|
||||||
AttachStderr bool
|
|
||||||
PortSpecs []string // Deprecated - Can be in the format of 8080/tcp
|
|
||||||
ExposedPorts map[nat.Port]struct{}
|
|
||||||
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
|
|
||||||
Cmd []string
|
|
||||||
Dns []string
|
|
||||||
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
|
||||||
Volumes map[string]struct{}
|
|
||||||
VolumesFrom string
|
|
||||||
WorkingDir string
|
|
||||||
Entrypoint []string
|
|
||||||
NetworkDisabled bool
|
|
||||||
OnBuild []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func ContainerConfigFromJob(job *engine.Job) *Config {
|
|
||||||
config := &Config{
|
|
||||||
Hostname: job.Getenv("Hostname"),
|
|
||||||
Domainname: job.Getenv("Domainname"),
|
|
||||||
User: job.Getenv("User"),
|
|
||||||
Memory: job.GetenvInt64("Memory"),
|
|
||||||
MemorySwap: job.GetenvInt64("MemorySwap"),
|
|
||||||
CpuShares: job.GetenvInt64("CpuShares"),
|
|
||||||
AttachStdin: job.GetenvBool("AttachStdin"),
|
|
||||||
AttachStdout: job.GetenvBool("AttachStdout"),
|
|
||||||
AttachStderr: job.GetenvBool("AttachStderr"),
|
|
||||||
Tty: job.GetenvBool("Tty"),
|
|
||||||
OpenStdin: job.GetenvBool("OpenStdin"),
|
|
||||||
StdinOnce: job.GetenvBool("StdinOnce"),
|
|
||||||
Image: job.Getenv("Image"),
|
|
||||||
VolumesFrom: job.Getenv("VolumesFrom"),
|
|
||||||
WorkingDir: job.Getenv("WorkingDir"),
|
|
||||||
NetworkDisabled: job.GetenvBool("NetworkDisabled"),
|
|
||||||
}
|
|
||||||
job.GetenvJson("ExposedPorts", &config.ExposedPorts)
|
|
||||||
job.GetenvJson("Volumes", &config.Volumes)
|
|
||||||
if PortSpecs := job.GetenvList("PortSpecs"); PortSpecs != nil {
|
|
||||||
config.PortSpecs = PortSpecs
|
|
||||||
}
|
|
||||||
if Env := job.GetenvList("Env"); Env != nil {
|
|
||||||
config.Env = Env
|
|
||||||
}
|
|
||||||
if Cmd := job.GetenvList("Cmd"); Cmd != nil {
|
|
||||||
config.Cmd = Cmd
|
|
||||||
}
|
|
||||||
if Dns := job.GetenvList("Dns"); Dns != nil {
|
|
||||||
config.Dns = Dns
|
|
||||||
}
|
|
||||||
if Entrypoint := job.GetenvList("Entrypoint"); Entrypoint != nil {
|
|
||||||
config.Entrypoint = Entrypoint
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
type HostConfig struct {
|
|
||||||
Binds []string
|
|
||||||
ContainerIDFile string
|
|
||||||
LxcConf []KeyValuePair
|
|
||||||
Privileged bool
|
|
||||||
PortBindings nat.PortMap
|
|
||||||
Links []string
|
|
||||||
PublishAllPorts bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
|
||||||
hostConfig := &HostConfig{
|
|
||||||
ContainerIDFile: job.Getenv("ContainerIDFile"),
|
|
||||||
Privileged: job.GetenvBool("Privileged"),
|
|
||||||
PublishAllPorts: job.GetenvBool("PublishAllPorts"),
|
|
||||||
}
|
|
||||||
job.GetenvJson("LxcConf", &hostConfig.LxcConf)
|
|
||||||
job.GetenvJson("PortBindings", &hostConfig.PortBindings)
|
|
||||||
if Binds := job.GetenvList("Binds"); Binds != nil {
|
|
||||||
hostConfig.Binds = Binds
|
|
||||||
}
|
|
||||||
if Links := job.GetenvList("Links"); Links != nil {
|
|
||||||
hostConfig.Links = Links
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
type BindMap struct {
|
type BindMap struct {
|
||||||
SrcPath string
|
SrcPath string
|
||||||
DstPath string
|
DstPath string
|
||||||
|
@ -178,18 +81,10 @@ type BindMap struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrContainerStart = errors.New("The container failed to start. Unknown error")
|
ErrContainerStart = errors.New("The container failed to start. Unknown error")
|
||||||
ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
|
ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
|
||||||
ErrInvalidWorikingDirectory = errors.New("The working directory is invalid. It needs to be an absolute path.")
|
|
||||||
ErrConflictAttachDetach = errors.New("Conflicting options: -a and -d")
|
|
||||||
ErrConflictDetachAutoRemove = errors.New("Conflicting options: -rm and -d")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyValuePair struct {
|
|
||||||
Key string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: move deprecated port stuff to nat to clean up the core.
|
// FIXME: move deprecated port stuff to nat to clean up the core.
|
||||||
type PortMapping map[string]string // Deprecated
|
type PortMapping map[string]string // Deprecated
|
||||||
|
|
||||||
|
@ -292,7 +187,7 @@ func (container *Container) ToDisk() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) readHostConfig() error {
|
func (container *Container) readHostConfig() error {
|
||||||
container.hostConfig = &HostConfig{}
|
container.hostConfig = &runconfig.HostConfig{}
|
||||||
// If the hostconfig file does not exist, do not read it.
|
// If the hostconfig file does not exist, do not read it.
|
||||||
// (We still have to initialize container.hostConfig,
|
// (We still have to initialize container.hostConfig,
|
||||||
// but that's OK, since we just did that above.)
|
// but that's OK, since we just did that above.)
|
||||||
|
|
|
@ -5,23 +5,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseLxcConfOpt(t *testing.T) {
|
|
||||||
opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "}
|
|
||||||
|
|
||||||
for _, o := range opts {
|
|
||||||
k, v, err := parseLxcOpt(o)
|
|
||||||
if err != nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if k != "lxc.utsname" {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if v != "docker" {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseNetworkOptsPrivateOnly(t *testing.T) {
|
func TestParseNetworkOptsPrivateOnly(t *testing.T) {
|
||||||
ports, bindings, err := nat.ParsePortSpecs([]string{"192.168.1.100::80"})
|
ports, bindings, err := nat.ParsePortSpecs([]string{"192.168.1.100::80"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
3
graph.go
3
graph.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/dockerversion"
|
"github.com/dotcloud/docker/dockerversion"
|
||||||
"github.com/dotcloud/docker/graphdriver"
|
"github.com/dotcloud/docker/graphdriver"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -126,7 +127,7 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates a new image and registers it in the graph.
|
// Create creates a new image and registers it in the graph.
|
||||||
func (graph *Graph) Create(layerData archive.Archive, container *Container, comment, author string, config *Config) (*Image, error) {
|
func (graph *Graph) Create(layerData archive.Archive, container *Container, comment, author string, config *runconfig.Config) (*Image, error) {
|
||||||
img := &Image{
|
img := &Image{
|
||||||
ID: GenerateID(),
|
ID: GenerateID(),
|
||||||
Comment: comment,
|
Comment: comment,
|
||||||
|
|
23
image.go
23
image.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/graphdriver"
|
"github.com/dotcloud/docker/graphdriver"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -18,17 +19,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Parent string `json:"parent,omitempty"`
|
Parent string `json:"parent,omitempty"`
|
||||||
Comment string `json:"comment,omitempty"`
|
Comment string `json:"comment,omitempty"`
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
Container string `json:"container,omitempty"`
|
Container string `json:"container,omitempty"`
|
||||||
ContainerConfig Config `json:"container_config,omitempty"`
|
ContainerConfig runconfig.Config `json:"container_config,omitempty"`
|
||||||
DockerVersion string `json:"docker_version,omitempty"`
|
DockerVersion string `json:"docker_version,omitempty"`
|
||||||
Author string `json:"author,omitempty"`
|
Author string `json:"author,omitempty"`
|
||||||
Config *Config `json:"config,omitempty"`
|
Config *runconfig.Config `json:"config,omitempty"`
|
||||||
Architecture string `json:"architecture,omitempty"`
|
Architecture string `json:"architecture,omitempty"`
|
||||||
OS string `json:"os,omitempty"`
|
OS string `json:"os,omitempty"`
|
||||||
graph *Graph
|
graph *Graph
|
||||||
Size int64
|
Size int64
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/dotcloud/docker/api"
|
"github.com/dotcloud/docker/api"
|
||||||
"github.com/dotcloud/docker/dockerversion"
|
"github.com/dotcloud/docker/dockerversion"
|
||||||
"github.com/dotcloud/docker/engine"
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
@ -309,7 +310,7 @@ func TestGetContainersJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
beginLen := len(outs.Data)
|
beginLen := len(outs.Data)
|
||||||
|
|
||||||
containerID := createTestContainer(eng, &docker.Config{
|
containerID := createTestContainer(eng, &runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"echo", "test"},
|
Cmd: []string{"echo", "test"},
|
||||||
}, t)
|
}, t)
|
||||||
|
@ -346,7 +347,7 @@ func TestGetContainersExport(t *testing.T) {
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"touch", "/test"},
|
Cmd: []string{"touch", "/test"},
|
||||||
},
|
},
|
||||||
|
@ -394,7 +395,7 @@ func TestGetContainersChanges(t *testing.T) {
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/rm", "/etc/passwd"},
|
Cmd: []string{"/bin/rm", "/etc/passwd"},
|
||||||
},
|
},
|
||||||
|
@ -433,7 +434,7 @@ func TestGetContainersTop(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/sh", "-c", "cat"},
|
Cmd: []string{"/bin/sh", "-c", "cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -510,7 +511,7 @@ func TestGetContainersByName(t *testing.T) {
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"echo", "test"},
|
Cmd: []string{"echo", "test"},
|
||||||
},
|
},
|
||||||
|
@ -542,7 +543,7 @@ func TestPostCommit(t *testing.T) {
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"touch", "/test"},
|
Cmd: []string{"touch", "/test"},
|
||||||
},
|
},
|
||||||
|
@ -578,7 +579,7 @@ func TestPostContainersCreate(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
configJSON, err := json.Marshal(&docker.Config{
|
configJSON, err := json.Marshal(&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Memory: 33554432,
|
Memory: 33554432,
|
||||||
Cmd: []string{"touch", "/test"},
|
Cmd: []string{"touch", "/test"},
|
||||||
|
@ -620,7 +621,7 @@ func TestPostContainersKill(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/cat"},
|
Cmd: []string{"/bin/cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -659,7 +660,7 @@ func TestPostContainersRestart(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/top"},
|
Cmd: []string{"/bin/top"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -705,7 +706,7 @@ func TestPostContainersStart(t *testing.T) {
|
||||||
|
|
||||||
containerID := createTestContainer(
|
containerID := createTestContainer(
|
||||||
eng,
|
eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/cat"},
|
Cmd: []string{"/bin/cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -713,7 +714,7 @@ func TestPostContainersStart(t *testing.T) {
|
||||||
t,
|
t,
|
||||||
)
|
)
|
||||||
|
|
||||||
hostConfigJSON, err := json.Marshal(&docker.HostConfig{})
|
hostConfigJSON, err := json.Marshal(&runconfig.HostConfig{})
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON))
|
req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -758,7 +759,7 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
|
||||||
|
|
||||||
containerID := createTestContainer(
|
containerID := createTestContainer(
|
||||||
eng,
|
eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/cat"},
|
Cmd: []string{"/bin/cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -766,7 +767,7 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
|
||||||
t,
|
t,
|
||||||
)
|
)
|
||||||
|
|
||||||
hostConfigJSON, err := json.Marshal(&docker.HostConfig{
|
hostConfigJSON, err := json.Marshal(&runconfig.HostConfig{
|
||||||
Binds: []string{"/:/tmp"},
|
Binds: []string{"/:/tmp"},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -792,7 +793,7 @@ func TestPostContainersStop(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/top"},
|
Cmd: []string{"/bin/top"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -832,7 +833,7 @@ func TestPostContainersWait(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/sleep", "1"},
|
Cmd: []string{"/bin/sleep", "1"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -870,7 +871,7 @@ func TestPostContainersAttach(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/cat"},
|
Cmd: []string{"/bin/cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -948,7 +949,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"},
|
Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -1029,7 +1030,7 @@ func TestDeleteContainers(t *testing.T) {
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"touch", "/test"},
|
Cmd: []string{"touch", "/test"},
|
||||||
},
|
},
|
||||||
|
@ -1164,7 +1165,7 @@ func TestPostContainersCopy(t *testing.T) {
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
containerID := createTestContainer(eng,
|
containerID := createTestContainer(eng,
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"touch", "/test.txt"},
|
Cmd: []string{"touch", "/test.txt"},
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@ package docker
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker"
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -20,7 +20,7 @@ func TestIDFormat(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container1, _, err := runtime.Create(
|
container1, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/sh", "-c", "echo hello world"},
|
Cmd: []string{"/bin/sh", "-c", "echo hello world"},
|
||||||
},
|
},
|
||||||
|
@ -234,7 +234,7 @@ func TestCommitAutoRun(t *testing.T) {
|
||||||
t.Errorf("Container shouldn't be running")
|
t.Errorf("Container shouldn't be running")
|
||||||
}
|
}
|
||||||
|
|
||||||
img, err := runtime.Commit(container1, "", "", "unit test commited image", "", &docker.Config{Cmd: []string{"cat", "/world"}})
|
img, err := runtime.Commit(container1, "", "", "unit test commited image", "", &runconfig.Config{Cmd: []string{"cat", "/world"}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -415,7 +415,7 @@ func TestOutput(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"echo", "-n", "foobar"},
|
Cmd: []string{"echo", "-n", "foobar"},
|
||||||
},
|
},
|
||||||
|
@ -438,7 +438,7 @@ func TestContainerNetwork(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
|
Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
|
||||||
},
|
},
|
||||||
|
@ -460,7 +460,7 @@ func TestKillDifferentUser(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"cat"},
|
Cmd: []string{"cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -520,7 +520,7 @@ func TestCreateVolume(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
config, hc, _, err := docker.ParseRun([]string{"-v", "/var/lib/data", unitTestImageID, "echo", "hello", "world"}, nil)
|
config, hc, _, err := runconfig.Parse([]string{"-v", "/var/lib/data", unitTestImageID, "echo", "hello", "world"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,7 @@ func TestCreateVolume(t *testing.T) {
|
||||||
func TestKill(t *testing.T) {
|
func TestKill(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sleep", "2"},
|
Cmd: []string{"sleep", "2"},
|
||||||
},
|
},
|
||||||
|
@ -596,7 +596,7 @@ func TestExitCode(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
trueContainer, _, err := runtime.Create(&docker.Config{
|
trueContainer, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/true"},
|
Cmd: []string{"/bin/true"},
|
||||||
}, "")
|
}, "")
|
||||||
|
@ -611,7 +611,7 @@ func TestExitCode(t *testing.T) {
|
||||||
t.Fatalf("Unexpected exit code %d (expected 0)", code)
|
t.Fatalf("Unexpected exit code %d (expected 0)", code)
|
||||||
}
|
}
|
||||||
|
|
||||||
falseContainer, _, err := runtime.Create(&docker.Config{
|
falseContainer, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/false"},
|
Cmd: []string{"/bin/false"},
|
||||||
}, "")
|
}, "")
|
||||||
|
@ -630,7 +630,7 @@ func TestExitCode(t *testing.T) {
|
||||||
func TestRestart(t *testing.T) {
|
func TestRestart(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"echo", "-n", "foobar"},
|
Cmd: []string{"echo", "-n", "foobar"},
|
||||||
},
|
},
|
||||||
|
@ -661,7 +661,7 @@ func TestRestart(t *testing.T) {
|
||||||
func TestRestartStdin(t *testing.T) {
|
func TestRestartStdin(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"cat"},
|
Cmd: []string{"cat"},
|
||||||
|
|
||||||
|
@ -739,7 +739,7 @@ func TestUser(t *testing.T) {
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
// Default user must be root
|
// Default user must be root
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"id"},
|
Cmd: []string{"id"},
|
||||||
},
|
},
|
||||||
|
@ -758,7 +758,7 @@ func TestUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a username
|
// Set a username
|
||||||
container, _, err = runtime.Create(&docker.Config{
|
container, _, err = runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"id"},
|
Cmd: []string{"id"},
|
||||||
|
|
||||||
|
@ -779,7 +779,7 @@ func TestUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a UID
|
// Set a UID
|
||||||
container, _, err = runtime.Create(&docker.Config{
|
container, _, err = runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"id"},
|
Cmd: []string{"id"},
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@ func TestUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a different user by uid
|
// Set a different user by uid
|
||||||
container, _, err = runtime.Create(&docker.Config{
|
container, _, err = runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"id"},
|
Cmd: []string{"id"},
|
||||||
|
|
||||||
|
@ -823,7 +823,7 @@ func TestUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a different user by username
|
// Set a different user by username
|
||||||
container, _, err = runtime.Create(&docker.Config{
|
container, _, err = runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"id"},
|
Cmd: []string{"id"},
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ func TestUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test an wrong username
|
// Test an wrong username
|
||||||
container, _, err = runtime.Create(&docker.Config{
|
container, _, err = runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"id"},
|
Cmd: []string{"id"},
|
||||||
|
|
||||||
|
@ -866,7 +866,7 @@ func TestMultipleContainers(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container1, _, err := runtime.Create(&docker.Config{
|
container1, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sleep", "2"},
|
Cmd: []string{"sleep", "2"},
|
||||||
},
|
},
|
||||||
|
@ -877,7 +877,7 @@ func TestMultipleContainers(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer runtime.Destroy(container1)
|
defer runtime.Destroy(container1)
|
||||||
|
|
||||||
container2, _, err := runtime.Create(&docker.Config{
|
container2, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sleep", "2"},
|
Cmd: []string{"sleep", "2"},
|
||||||
},
|
},
|
||||||
|
@ -921,7 +921,7 @@ func TestMultipleContainers(t *testing.T) {
|
||||||
func TestStdin(t *testing.T) {
|
func TestStdin(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"cat"},
|
Cmd: []string{"cat"},
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ func TestStdin(t *testing.T) {
|
||||||
func TestTty(t *testing.T) {
|
func TestTty(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"cat"},
|
Cmd: []string{"cat"},
|
||||||
|
|
||||||
|
@ -1013,7 +1013,7 @@ func TestEnv(t *testing.T) {
|
||||||
os.Setenv("TRICKY", "tri\ncky\n")
|
os.Setenv("TRICKY", "tri\ncky\n")
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
config, _, _, err := docker.ParseRun([]string{"-e=FALSE=true", "-e=TRUE", "-e=TRICKY", GetTestImage(runtime).ID, "env"}, nil)
|
config, _, _, err := runconfig.Parse([]string{"-e=FALSE=true", "-e=TRUE", "-e=TRICKY", GetTestImage(runtime).ID, "env"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1067,7 @@ func TestEntrypoint(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Entrypoint: []string{"/bin/echo"},
|
Entrypoint: []string{"/bin/echo"},
|
||||||
Cmd: []string{"-n", "foobar"},
|
Cmd: []string{"-n", "foobar"},
|
||||||
|
@ -1091,7 +1091,7 @@ func TestEntrypointNoCmd(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Entrypoint: []string{"/bin/echo", "foobar"},
|
Entrypoint: []string{"/bin/echo", "foobar"},
|
||||||
},
|
},
|
||||||
|
@ -1114,7 +1114,7 @@ func BenchmarkRunSequencial(b *testing.B) {
|
||||||
runtime := mkRuntime(b)
|
runtime := mkRuntime(b)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"echo", "-n", "foo"},
|
Cmd: []string{"echo", "-n", "foo"},
|
||||||
},
|
},
|
||||||
|
@ -1147,7 +1147,7 @@ func BenchmarkRunParallel(b *testing.B) {
|
||||||
complete := make(chan error)
|
complete := make(chan error)
|
||||||
tasks = append(tasks, complete)
|
tasks = append(tasks, complete)
|
||||||
go func(i int, complete chan error) {
|
go func(i int, complete chan error) {
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"echo", "-n", "foo"},
|
Cmd: []string{"echo", "-n", "foo"},
|
||||||
},
|
},
|
||||||
|
@ -1301,7 +1301,7 @@ func TestFromVolumesInReadonlyMode(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
||||||
Volumes: map[string]struct{}{"/test": {}},
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
@ -1321,7 +1321,7 @@ func TestFromVolumesInReadonlyMode(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
container2, _, err := runtime.Create(
|
container2, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
||||||
VolumesFrom: container.ID + ":ro",
|
VolumesFrom: container.ID + ":ro",
|
||||||
|
@ -1362,7 +1362,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
||||||
Volumes: map[string]struct{}{"/test": {}},
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
@ -1382,7 +1382,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
container2, _, err := runtime.Create(
|
container2, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
||||||
VolumesFrom: container.ID,
|
VolumesFrom: container.ID,
|
||||||
|
@ -1418,7 +1418,7 @@ func TestRestartWithVolumes(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"echo", "-n", "foobar"},
|
Cmd: []string{"echo", "-n", "foobar"},
|
||||||
Volumes: map[string]struct{}{"/test": {}},
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
@ -1462,7 +1462,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
||||||
Volumes: map[string]struct{}{"/test": {}},
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
@ -1491,7 +1491,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
container2, _, err := runtime.Create(
|
container2, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"cat", "/test/foo"},
|
Cmd: []string{"cat", "/test/foo"},
|
||||||
VolumesFrom: container.ID,
|
VolumesFrom: container.ID,
|
||||||
|
@ -1529,7 +1529,7 @@ func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
config, hc, _, err := docker.ParseRun([]string{"-n=false", GetTestImage(runtime).ID, "ip", "addr", "show"}, nil)
|
config, hc, _, err := runconfig.Parse([]string{"-n=false", GetTestImage(runtime).ID, "ip", "addr", "show"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -1617,7 +1617,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
||||||
Volumes: map[string]struct{}{"/test": {}},
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
@ -1646,7 +1646,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
container2, _, err := runtime.Create(
|
container2, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"},
|
Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"},
|
||||||
Volumes: map[string]struct{}{"/other": {}},
|
Volumes: map[string]struct{}{"/other": {}},
|
||||||
|
@ -1668,7 +1668,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
container3, _, err := runtime.Create(
|
container3, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
||||||
VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","),
|
VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","),
|
||||||
|
@ -1696,7 +1696,7 @@ func TestRestartGhost(t *testing.T) {
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(
|
container, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
||||||
Volumes: map[string]struct{}{"/test": {}},
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/dotcloud/docker"
|
"github.com/dotcloud/docker"
|
||||||
"github.com/dotcloud/docker/engine"
|
"github.com/dotcloud/docker/engine"
|
||||||
"github.com/dotcloud/docker/nat"
|
"github.com/dotcloud/docker/nat"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/sysinit"
|
"github.com/dotcloud/docker/sysinit"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
|
@ -200,7 +201,7 @@ func TestRuntimeCreate(t *testing.T) {
|
||||||
t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
|
t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
|
||||||
}
|
}
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"ls", "-al"},
|
Cmd: []string{"ls", "-al"},
|
||||||
},
|
},
|
||||||
|
@ -243,23 +244,23 @@ func TestRuntimeCreate(t *testing.T) {
|
||||||
|
|
||||||
// Test that conflict error displays correct details
|
// Test that conflict error displays correct details
|
||||||
testContainer, _, _ := runtime.Create(
|
testContainer, _, _ := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"ls", "-al"},
|
Cmd: []string{"ls", "-al"},
|
||||||
},
|
},
|
||||||
"conflictname",
|
"conflictname",
|
||||||
)
|
)
|
||||||
if _, _, err := runtime.Create(&docker.Config{Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}}, testContainer.Name); err == nil || !strings.Contains(err.Error(), utils.TruncateID(testContainer.ID)) {
|
if _, _, err := runtime.Create(&runconfig.Config{Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}}, testContainer.Name); err == nil || !strings.Contains(err.Error(), utils.TruncateID(testContainer.ID)) {
|
||||||
t.Fatalf("Name conflict error doesn't include the correct short id. Message was: %s", err.Error())
|
t.Fatalf("Name conflict error doesn't include the correct short id. Message was: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure create with bad parameters returns an error
|
// Make sure create with bad parameters returns an error
|
||||||
if _, _, err = runtime.Create(&docker.Config{Image: GetTestImage(runtime).ID}, ""); err == nil {
|
if _, _, err = runtime.Create(&runconfig.Config{Image: GetTestImage(runtime).ID}, ""); err == nil {
|
||||||
t.Fatal("Builder.Create should throw an error when Cmd is missing")
|
t.Fatal("Builder.Create should throw an error when Cmd is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, err := runtime.Create(
|
if _, _, err := runtime.Create(
|
||||||
&docker.Config{
|
&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{},
|
Cmd: []string{},
|
||||||
},
|
},
|
||||||
|
@ -268,7 +269,7 @@ func TestRuntimeCreate(t *testing.T) {
|
||||||
t.Fatal("Builder.Create should throw an error when Cmd is empty")
|
t.Fatal("Builder.Create should throw an error when Cmd is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &docker.Config{
|
config := &runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"/bin/ls"},
|
Cmd: []string{"/bin/ls"},
|
||||||
PortSpecs: []string{"80"},
|
PortSpecs: []string{"80"},
|
||||||
|
@ -281,7 +282,7 @@ func TestRuntimeCreate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// test expose 80:8000
|
// test expose 80:8000
|
||||||
container, warnings, err := runtime.Create(&docker.Config{
|
container, warnings, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"ls", "-al"},
|
Cmd: []string{"ls", "-al"},
|
||||||
PortSpecs: []string{"80:8000"},
|
PortSpecs: []string{"80:8000"},
|
||||||
|
@ -300,7 +301,7 @@ func TestDestroy(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"ls", "-al"},
|
Cmd: []string{"ls", "-al"},
|
||||||
}, "")
|
}, "")
|
||||||
|
@ -712,7 +713,7 @@ func TestDefaultContainerName(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -736,7 +737,7 @@ func TestRandomContainerName(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{GetTestImage(runtime).ID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -767,7 +768,7 @@ func TestContainerNameValidation(t *testing.T) {
|
||||||
{"abc-123_AAA.1", true},
|
{"abc-123_AAA.1", true},
|
||||||
{"\000asdf", false},
|
{"\000asdf", false},
|
||||||
} {
|
} {
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !test.Valid {
|
if !test.Valid {
|
||||||
continue
|
continue
|
||||||
|
@ -808,7 +809,7 @@ func TestLinkChildContainer(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -824,7 +825,7 @@ func TestLinkChildContainer(t *testing.T) {
|
||||||
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
|
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, _, _, err = docker.ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
|
config, _, _, err = runconfig.Parse([]string{GetTestImage(runtime).ID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -850,7 +851,7 @@ func TestGetAllChildren(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -866,7 +867,7 @@ func TestGetAllChildren(t *testing.T) {
|
||||||
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
|
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, _, _, err = docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err = runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -903,7 +904,7 @@ func TestDestroyWithInitLayer(t *testing.T) {
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
defer nuke(runtime)
|
defer nuke(runtime)
|
||||||
|
|
||||||
container, _, err := runtime.Create(&docker.Config{
|
container, _, err := runtime.Create(&runconfig.Config{
|
||||||
Image: GetTestImage(runtime).ID,
|
Image: GetTestImage(runtime).ID,
|
||||||
Cmd: []string{"ls", "-al"},
|
Cmd: []string{"ls", "-al"},
|
||||||
}, "")
|
}, "")
|
||||||
|
|
|
@ -3,6 +3,7 @@ package docker
|
||||||
import (
|
import (
|
||||||
"github.com/dotcloud/docker"
|
"github.com/dotcloud/docker"
|
||||||
"github.com/dotcloud/docker/engine"
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -71,7 +72,7 @@ func TestCreateRm(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -118,7 +119,7 @@ func TestCreateNumberHostname(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{"-h", "web.0", unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{"-h", "web.0", unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +131,7 @@ func TestCreateNumberUsername(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{"-u", "1002", unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{"-u", "1002", unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -142,7 +143,7 @@ func TestCreateRmVolumes(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config, hostConfig, _, err := docker.ParseRun([]string{"-v", "/srv", unitTestImageID, "echo", "test"}, nil)
|
config, hostConfig, _, err := runconfig.Parse([]string{"-v", "/srv", unitTestImageID, "echo", "test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -202,7 +203,7 @@ func TestCommit(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "/bin/cat"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "/bin/cat"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -224,7 +225,7 @@ func TestRestartKillWait(t *testing.T) {
|
||||||
runtime := mkRuntimeFromEngine(eng, t)
|
runtime := mkRuntimeFromEngine(eng, t)
|
||||||
defer runtime.Nuke()
|
defer runtime.Nuke()
|
||||||
|
|
||||||
config, hostConfig, _, err := docker.ParseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
|
config, hostConfig, _, err := runconfig.Parse([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -302,7 +303,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
|
||||||
srv := mkServerFromEngine(eng, t)
|
srv := mkServerFromEngine(eng, t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config, hostConfig, _, err := docker.ParseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
|
config, hostConfig, _, err := runconfig.Parse([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -401,7 +402,7 @@ func TestRmi(t *testing.T) {
|
||||||
|
|
||||||
initialImages := getAllImages(eng, t)
|
initialImages := getAllImages(eng, t)
|
||||||
|
|
||||||
config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "echo", "test"}, nil)
|
config, hostConfig, _, err := runconfig.Parse([]string{unitTestImageID, "echo", "test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -548,7 +549,7 @@ func TestListContainers(t *testing.T) {
|
||||||
srv := mkServerFromEngine(eng, t)
|
srv := mkServerFromEngine(eng, t)
|
||||||
defer mkRuntimeFromEngine(eng, t).Nuke()
|
defer mkRuntimeFromEngine(eng, t).Nuke()
|
||||||
|
|
||||||
config := docker.Config{
|
config := runconfig.Config{
|
||||||
Image: unitTestImageID,
|
Image: unitTestImageID,
|
||||||
Cmd: []string{"/bin/sh", "-c", "cat"},
|
Cmd: []string{"/bin/sh", "-c", "cat"},
|
||||||
OpenStdin: true,
|
OpenStdin: true,
|
||||||
|
@ -671,7 +672,7 @@ func TestDeleteTagWithExistingContainers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a container from the image
|
// Create a container from the image
|
||||||
config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
|
config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
"github.com/dotcloud/docker"
|
"github.com/dotcloud/docker"
|
||||||
"github.com/dotcloud/docker/engine"
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ func mkRuntime(f utils.Fataler) *docker.Runtime {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNamedTestContainer(eng *engine.Engine, config *docker.Config, f utils.Fataler, name string) (shortId string) {
|
func createNamedTestContainer(eng *engine.Engine, config *runconfig.Config, f utils.Fataler, name string) (shortId string) {
|
||||||
job := eng.Job("create", name)
|
job := eng.Job("create", name)
|
||||||
if err := job.ImportEnv(config); err != nil {
|
if err := job.ImportEnv(config); err != nil {
|
||||||
f.Fatal(err)
|
f.Fatal(err)
|
||||||
|
@ -60,7 +61,7 @@ func createNamedTestContainer(eng *engine.Engine, config *docker.Config, f utils
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestContainer(eng *engine.Engine, config *docker.Config, f utils.Fataler) (shortId string) {
|
func createTestContainer(eng *engine.Engine, config *runconfig.Config, f utils.Fataler) (shortId string) {
|
||||||
return createNamedTestContainer(eng, config, f, "")
|
return createNamedTestContainer(eng, config, f, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +253,8 @@ func readFile(src string, t *testing.T) (content string) {
|
||||||
// dynamically replaced by the current test image.
|
// dynamically replaced by the current test image.
|
||||||
// The caller is responsible for destroying the container.
|
// The caller is responsible for destroying the container.
|
||||||
// Call t.Fatal() at the first error.
|
// Call t.Fatal() at the first error.
|
||||||
func mkContainer(r *docker.Runtime, args []string, t *testing.T) (*docker.Container, *docker.HostConfig, error) {
|
func mkContainer(r *docker.Runtime, args []string, t *testing.T) (*docker.Container, *runconfig.HostConfig, error) {
|
||||||
config, hc, _, err := docker.ParseRun(args, nil)
|
config, hc, _, err := runconfig.Parse(args, nil)
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil && t != nil {
|
if err != nil && t != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -2,13 +2,14 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/dotcloud/docker/nat"
|
"github.com/dotcloud/docker/nat"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newMockLinkContainer(id string, ip string) *Container {
|
func newMockLinkContainer(id string, ip string) *Container {
|
||||||
return &Container{
|
return &Container{
|
||||||
Config: &Config{},
|
Config: &runconfig.Config{},
|
||||||
ID: id,
|
ID: id,
|
||||||
NetworkSettings: &NetworkSettings{
|
NetworkSettings: &NetworkSettings{
|
||||||
IPAddress: ip,
|
IPAddress: ip,
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package runconfig
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
if a == nil || b == nil ||
|
||||||
|
a.OpenStdin || b.OpenStdin {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a.AttachStdout != b.AttachStdout ||
|
||||||
|
a.AttachStderr != b.AttachStderr ||
|
||||||
|
a.User != b.User ||
|
||||||
|
a.Memory != b.Memory ||
|
||||||
|
a.MemorySwap != b.MemorySwap ||
|
||||||
|
a.CpuShares != b.CpuShares ||
|
||||||
|
a.OpenStdin != b.OpenStdin ||
|
||||||
|
a.Tty != b.Tty ||
|
||||||
|
a.VolumesFrom != b.VolumesFrom {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(a.Cmd) != len(b.Cmd) ||
|
||||||
|
len(a.Dns) != len(b.Dns) ||
|
||||||
|
len(a.Env) != len(b.Env) ||
|
||||||
|
len(a.PortSpecs) != len(b.PortSpecs) ||
|
||||||
|
len(a.ExposedPorts) != len(b.ExposedPorts) ||
|
||||||
|
len(a.Entrypoint) != len(b.Entrypoint) ||
|
||||||
|
len(a.Volumes) != len(b.Volumes) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(a.Cmd); i++ {
|
||||||
|
if a.Cmd[i] != b.Cmd[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(a.Dns); i++ {
|
||||||
|
if a.Dns[i] != b.Dns[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(a.Env); i++ {
|
||||||
|
if a.Env[i] != b.Env[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(a.PortSpecs); i++ {
|
||||||
|
if a.PortSpecs[i] != b.PortSpecs[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k := range a.ExposedPorts {
|
||||||
|
if _, exists := b.ExposedPorts[k]; !exists {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(a.Entrypoint); i++ {
|
||||||
|
if a.Entrypoint[i] != b.Entrypoint[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for key := range a.Volumes {
|
||||||
|
if _, exists := b.Volumes[key]; !exists {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package runconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"github.com/dotcloud/docker/nat"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note: the Config structure 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.
|
||||||
|
type Config struct {
|
||||||
|
Hostname string
|
||||||
|
Domainname string
|
||||||
|
User string
|
||||||
|
Memory int64 // Memory limit (in bytes)
|
||||||
|
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
|
||||||
|
CpuShares int64 // CPU shares (relative weight vs. other containers)
|
||||||
|
AttachStdin bool
|
||||||
|
AttachStdout bool
|
||||||
|
AttachStderr bool
|
||||||
|
PortSpecs []string // Deprecated - Can be in the format of 8080/tcp
|
||||||
|
ExposedPorts map[nat.Port]struct{}
|
||||||
|
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
|
||||||
|
Cmd []string
|
||||||
|
Dns []string
|
||||||
|
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
||||||
|
Volumes map[string]struct{}
|
||||||
|
VolumesFrom string
|
||||||
|
WorkingDir string
|
||||||
|
Entrypoint []string
|
||||||
|
NetworkDisabled bool
|
||||||
|
OnBuild []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContainerConfigFromJob(job *engine.Job) *Config {
|
||||||
|
config := &Config{
|
||||||
|
Hostname: job.Getenv("Hostname"),
|
||||||
|
Domainname: job.Getenv("Domainname"),
|
||||||
|
User: job.Getenv("User"),
|
||||||
|
Memory: job.GetenvInt64("Memory"),
|
||||||
|
MemorySwap: job.GetenvInt64("MemorySwap"),
|
||||||
|
CpuShares: job.GetenvInt64("CpuShares"),
|
||||||
|
AttachStdin: job.GetenvBool("AttachStdin"),
|
||||||
|
AttachStdout: job.GetenvBool("AttachStdout"),
|
||||||
|
AttachStderr: job.GetenvBool("AttachStderr"),
|
||||||
|
Tty: job.GetenvBool("Tty"),
|
||||||
|
OpenStdin: job.GetenvBool("OpenStdin"),
|
||||||
|
StdinOnce: job.GetenvBool("StdinOnce"),
|
||||||
|
Image: job.Getenv("Image"),
|
||||||
|
VolumesFrom: job.Getenv("VolumesFrom"),
|
||||||
|
WorkingDir: job.Getenv("WorkingDir"),
|
||||||
|
NetworkDisabled: job.GetenvBool("NetworkDisabled"),
|
||||||
|
}
|
||||||
|
job.GetenvJson("ExposedPorts", &config.ExposedPorts)
|
||||||
|
job.GetenvJson("Volumes", &config.Volumes)
|
||||||
|
if PortSpecs := job.GetenvList("PortSpecs"); PortSpecs != nil {
|
||||||
|
config.PortSpecs = PortSpecs
|
||||||
|
}
|
||||||
|
if Env := job.GetenvList("Env"); Env != nil {
|
||||||
|
config.Env = Env
|
||||||
|
}
|
||||||
|
if Cmd := job.GetenvList("Cmd"); Cmd != nil {
|
||||||
|
config.Cmd = Cmd
|
||||||
|
}
|
||||||
|
if Dns := job.GetenvList("Dns"); Dns != nil {
|
||||||
|
config.Dns = Dns
|
||||||
|
}
|
||||||
|
if Entrypoint := job.GetenvList("Entrypoint"); Entrypoint != nil {
|
||||||
|
config.Entrypoint = Entrypoint
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package docker
|
package runconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/dotcloud/docker/nat"
|
"github.com/dotcloud/docker/nat"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCompareConfig(t *testing.T) {
|
func TestCompare(t *testing.T) {
|
||||||
volumes1 := make(map[string]struct{})
|
volumes1 := make(map[string]struct{})
|
||||||
volumes1["/test1"] = struct{}{}
|
volumes1["/test1"] = struct{}{}
|
||||||
config1 := Config{
|
config1 := Config{
|
||||||
|
@ -45,24 +45,24 @@ func TestCompareConfig(t *testing.T) {
|
||||||
VolumesFrom: "11111111",
|
VolumesFrom: "11111111",
|
||||||
Volumes: volumes2,
|
Volumes: volumes2,
|
||||||
}
|
}
|
||||||
if CompareConfig(&config1, &config2) {
|
if Compare(&config1, &config2) {
|
||||||
t.Fatalf("CompareConfig should return false, Dns are different")
|
t.Fatalf("Compare should return false, Dns are different")
|
||||||
}
|
}
|
||||||
if CompareConfig(&config1, &config3) {
|
if Compare(&config1, &config3) {
|
||||||
t.Fatalf("CompareConfig should return false, PortSpecs are different")
|
t.Fatalf("Compare should return false, PortSpecs are different")
|
||||||
}
|
}
|
||||||
if CompareConfig(&config1, &config4) {
|
if Compare(&config1, &config4) {
|
||||||
t.Fatalf("CompareConfig should return false, VolumesFrom are different")
|
t.Fatalf("Compare should return false, VolumesFrom are different")
|
||||||
}
|
}
|
||||||
if CompareConfig(&config1, &config5) {
|
if Compare(&config1, &config5) {
|
||||||
t.Fatalf("CompareConfig should return false, Volumes are different")
|
t.Fatalf("Compare should return false, Volumes are different")
|
||||||
}
|
}
|
||||||
if !CompareConfig(&config1, &config1) {
|
if !Compare(&config1, &config1) {
|
||||||
t.Fatalf("CompareConfig should return true")
|
t.Fatalf("Compare should return true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMergeConfig(t *testing.T) {
|
func TestMerge(t *testing.T) {
|
||||||
volumesImage := make(map[string]struct{})
|
volumesImage := make(map[string]struct{})
|
||||||
volumesImage["/test1"] = struct{}{}
|
volumesImage["/test1"] = struct{}{}
|
||||||
volumesImage["/test2"] = struct{}{}
|
volumesImage["/test2"] = struct{}{}
|
||||||
|
@ -83,7 +83,7 @@ func TestMergeConfig(t *testing.T) {
|
||||||
Volumes: volumesUser,
|
Volumes: volumesUser,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := MergeConfig(configUser, configImage); err != nil {
|
if err := Merge(configUser, configImage); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ func TestMergeConfig(t *testing.T) {
|
||||||
ExposedPorts: ports,
|
ExposedPorts: ports,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := MergeConfig(configUser, configImage2); err != nil {
|
if err := Merge(configUser, configImage2); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package runconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dotcloud/docker/engine"
|
||||||
|
"github.com/dotcloud/docker/nat"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HostConfig struct {
|
||||||
|
Binds []string
|
||||||
|
ContainerIDFile string
|
||||||
|
LxcConf []KeyValuePair
|
||||||
|
Privileged bool
|
||||||
|
PortBindings nat.PortMap
|
||||||
|
Links []string
|
||||||
|
PublishAllPorts bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyValuePair struct {
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
||||||
|
hostConfig := &HostConfig{
|
||||||
|
ContainerIDFile: job.Getenv("ContainerIDFile"),
|
||||||
|
Privileged: job.GetenvBool("Privileged"),
|
||||||
|
PublishAllPorts: job.GetenvBool("PublishAllPorts"),
|
||||||
|
}
|
||||||
|
job.GetenvJson("LxcConf", &hostConfig.LxcConf)
|
||||||
|
job.GetenvJson("PortBindings", &hostConfig.PortBindings)
|
||||||
|
if Binds := job.GetenvList("Binds"); Binds != nil {
|
||||||
|
hostConfig.Binds = Binds
|
||||||
|
}
|
||||||
|
if Links := job.GetenvList("Links"); Links != nil {
|
||||||
|
hostConfig.Links = Links
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostConfig
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
package runconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dotcloud/docker/nat"
|
||||||
|
"github.com/dotcloud/docker/utils"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Merge(userConf, imageConf *Config) error {
|
||||||
|
if userConf.User == "" {
|
||||||
|
userConf.User = imageConf.User
|
||||||
|
}
|
||||||
|
if userConf.Memory == 0 {
|
||||||
|
userConf.Memory = imageConf.Memory
|
||||||
|
}
|
||||||
|
if userConf.MemorySwap == 0 {
|
||||||
|
userConf.MemorySwap = imageConf.MemorySwap
|
||||||
|
}
|
||||||
|
if userConf.CpuShares == 0 {
|
||||||
|
userConf.CpuShares = imageConf.CpuShares
|
||||||
|
}
|
||||||
|
if userConf.ExposedPorts == nil || len(userConf.ExposedPorts) == 0 {
|
||||||
|
userConf.ExposedPorts = imageConf.ExposedPorts
|
||||||
|
} else if imageConf.ExposedPorts != nil {
|
||||||
|
if userConf.ExposedPorts == nil {
|
||||||
|
userConf.ExposedPorts = make(nat.PortSet)
|
||||||
|
}
|
||||||
|
for port := range imageConf.ExposedPorts {
|
||||||
|
if _, exists := userConf.ExposedPorts[port]; !exists {
|
||||||
|
userConf.ExposedPorts[port] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if userConf.PortSpecs != nil && len(userConf.PortSpecs) > 0 {
|
||||||
|
if userConf.ExposedPorts == nil {
|
||||||
|
userConf.ExposedPorts = make(nat.PortSet)
|
||||||
|
}
|
||||||
|
ports, _, err := nat.ParsePortSpecs(userConf.PortSpecs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for port := range ports {
|
||||||
|
if _, exists := userConf.ExposedPorts[port]; !exists {
|
||||||
|
userConf.ExposedPorts[port] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userConf.PortSpecs = nil
|
||||||
|
}
|
||||||
|
if imageConf.PortSpecs != nil && len(imageConf.PortSpecs) > 0 {
|
||||||
|
// FIXME: I think we can safely remove this. Leaving it for now for the sake of reverse-compat paranoia.
|
||||||
|
utils.Debugf("Migrating image port specs to containter: %s", strings.Join(imageConf.PortSpecs, ", "))
|
||||||
|
if userConf.ExposedPorts == nil {
|
||||||
|
userConf.ExposedPorts = make(nat.PortSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
ports, _, err := nat.ParsePortSpecs(imageConf.PortSpecs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for port := range ports {
|
||||||
|
if _, exists := userConf.ExposedPorts[port]; !exists {
|
||||||
|
userConf.ExposedPorts[port] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !userConf.Tty {
|
||||||
|
userConf.Tty = imageConf.Tty
|
||||||
|
}
|
||||||
|
if !userConf.OpenStdin {
|
||||||
|
userConf.OpenStdin = imageConf.OpenStdin
|
||||||
|
}
|
||||||
|
if !userConf.StdinOnce {
|
||||||
|
userConf.StdinOnce = imageConf.StdinOnce
|
||||||
|
}
|
||||||
|
if userConf.Env == nil || len(userConf.Env) == 0 {
|
||||||
|
userConf.Env = imageConf.Env
|
||||||
|
} else {
|
||||||
|
for _, imageEnv := range imageConf.Env {
|
||||||
|
found := false
|
||||||
|
imageEnvKey := strings.Split(imageEnv, "=")[0]
|
||||||
|
for _, userEnv := range userConf.Env {
|
||||||
|
userEnvKey := strings.Split(userEnv, "=")[0]
|
||||||
|
if imageEnvKey == userEnvKey {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
userConf.Env = append(userConf.Env, imageEnv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
|
||||||
|
userConf.Cmd = imageConf.Cmd
|
||||||
|
}
|
||||||
|
if userConf.Dns == nil || len(userConf.Dns) == 0 {
|
||||||
|
userConf.Dns = imageConf.Dns
|
||||||
|
} else {
|
||||||
|
//duplicates aren't an issue here
|
||||||
|
userConf.Dns = append(userConf.Dns, imageConf.Dns...)
|
||||||
|
}
|
||||||
|
if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
|
||||||
|
userConf.Entrypoint = imageConf.Entrypoint
|
||||||
|
}
|
||||||
|
if userConf.WorkingDir == "" {
|
||||||
|
userConf.WorkingDir = imageConf.WorkingDir
|
||||||
|
}
|
||||||
|
if userConf.VolumesFrom == "" {
|
||||||
|
userConf.VolumesFrom = imageConf.VolumesFrom
|
||||||
|
}
|
||||||
|
if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
|
||||||
|
userConf.Volumes = imageConf.Volumes
|
||||||
|
} else {
|
||||||
|
for k, v := range imageConf.Volumes {
|
||||||
|
userConf.Volumes[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,246 @@
|
||||||
|
package runconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/dotcloud/docker/nat"
|
||||||
|
flag "github.com/dotcloud/docker/pkg/mflag"
|
||||||
|
"github.com/dotcloud/docker/pkg/opts"
|
||||||
|
"github.com/dotcloud/docker/pkg/sysinfo"
|
||||||
|
"github.com/dotcloud/docker/utils"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidWorikingDirectory = fmt.Errorf("The working directory is invalid. It needs to be an absolute path.")
|
||||||
|
ErrConflictAttachDetach = fmt.Errorf("Conflicting options: -a and -d")
|
||||||
|
ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: -rm and -d")
|
||||||
|
)
|
||||||
|
|
||||||
|
//FIXME Only used in tests
|
||||||
|
func Parse(args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||||
|
cmd := flag.NewFlagSet("run", flag.ContinueOnError)
|
||||||
|
cmd.SetOutput(ioutil.Discard)
|
||||||
|
cmd.Usage = nil
|
||||||
|
return parseRun(cmd, args, sysInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: this maps the legacy commands.go code. It should be merged with Parse to only expose a single parse function.
|
||||||
|
func ParseSubcommand(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||||
|
return parseRun(cmd, args, sysInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) {
|
||||||
|
var (
|
||||||
|
// FIXME: use utils.ListOpts for attach and volumes?
|
||||||
|
flAttach = opts.NewListOpts(opts.ValidateAttach)
|
||||||
|
flVolumes = opts.NewListOpts(opts.ValidatePath)
|
||||||
|
flLinks = opts.NewListOpts(opts.ValidateLink)
|
||||||
|
flEnv = opts.NewListOpts(opts.ValidateEnv)
|
||||||
|
|
||||||
|
flPublish opts.ListOpts
|
||||||
|
flExpose opts.ListOpts
|
||||||
|
flDns opts.ListOpts
|
||||||
|
flVolumesFrom opts.ListOpts
|
||||||
|
flLxcOpts opts.ListOpts
|
||||||
|
|
||||||
|
flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
|
||||||
|
flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: Run container in the background, print new container id")
|
||||||
|
flNetwork = cmd.Bool([]string{"n", "-networking"}, true, "Enable networking for this container")
|
||||||
|
flPrivileged = cmd.Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
|
||||||
|
flPublishAll = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to the host interfaces")
|
||||||
|
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")
|
||||||
|
flContainerIDFile = cmd.String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
|
||||||
|
flEntrypoint = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default entrypoint of the image")
|
||||||
|
flHostname = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
|
||||||
|
flMemoryString = cmd.String([]string{"m", "-memory"}, "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
|
||||||
|
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID")
|
||||||
|
flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
|
||||||
|
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
||||||
|
|
||||||
|
// For documentation purpose
|
||||||
|
_ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
||||||
|
_ = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to stdin, stdout or stderr.")
|
||||||
|
cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
|
||||||
|
cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container (name:alias)")
|
||||||
|
cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables")
|
||||||
|
|
||||||
|
cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat))
|
||||||
|
cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
|
||||||
|
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
||||||
|
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
||||||
|
cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
||||||
|
|
||||||
|
if err := cmd.Parse(args); err != nil {
|
||||||
|
return nil, nil, cmd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the kernel supports memory limit cgroup.
|
||||||
|
if sysInfo != nil && *flMemoryString != "" && !sysInfo.MemoryLimit {
|
||||||
|
*flMemoryString = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate input params
|
||||||
|
if *flDetach && flAttach.Len() > 0 {
|
||||||
|
return nil, nil, cmd, ErrConflictAttachDetach
|
||||||
|
}
|
||||||
|
if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
|
||||||
|
return nil, nil, cmd, ErrInvalidWorikingDirectory
|
||||||
|
}
|
||||||
|
if *flDetach && *flAutoRemove {
|
||||||
|
return nil, nil, cmd, ErrConflictDetachAutoRemove
|
||||||
|
}
|
||||||
|
|
||||||
|
// If neither -d or -a are set, attach to everything by default
|
||||||
|
if flAttach.Len() == 0 && !*flDetach {
|
||||||
|
if !*flDetach {
|
||||||
|
flAttach.Set("stdout")
|
||||||
|
flAttach.Set("stderr")
|
||||||
|
if *flStdin {
|
||||||
|
flAttach.Set("stdin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var flMemory int64
|
||||||
|
if *flMemoryString != "" {
|
||||||
|
parsedMemory, err := utils.RAMInBytes(*flMemoryString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, cmd, err
|
||||||
|
}
|
||||||
|
flMemory = parsedMemory
|
||||||
|
}
|
||||||
|
|
||||||
|
var binds []string
|
||||||
|
// add any bind targets to the list of container volumes
|
||||||
|
for bind := range flVolumes.GetMap() {
|
||||||
|
if arr := strings.Split(bind, ":"); len(arr) > 1 {
|
||||||
|
if arr[0] == "/" {
|
||||||
|
return nil, nil, cmd, fmt.Errorf("Invalid bind mount: source can't be '/'")
|
||||||
|
}
|
||||||
|
dstDir := arr[1]
|
||||||
|
flVolumes.Set(dstDir)
|
||||||
|
binds = append(binds, bind)
|
||||||
|
flVolumes.Delete(bind)
|
||||||
|
} else if bind == "/" {
|
||||||
|
return nil, nil, cmd, fmt.Errorf("Invalid volume: path can't be '/'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
parsedArgs = cmd.Args()
|
||||||
|
runCmd []string
|
||||||
|
entrypoint []string
|
||||||
|
image string
|
||||||
|
)
|
||||||
|
if len(parsedArgs) >= 1 {
|
||||||
|
image = cmd.Arg(0)
|
||||||
|
}
|
||||||
|
if len(parsedArgs) > 1 {
|
||||||
|
runCmd = parsedArgs[1:]
|
||||||
|
}
|
||||||
|
if *flEntrypoint != "" {
|
||||||
|
entrypoint = []string{*flEntrypoint}
|
||||||
|
}
|
||||||
|
|
||||||
|
lxcConf, err := parseLxcConfOpts(flLxcOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, cmd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
domainname string
|
||||||
|
hostname = *flHostname
|
||||||
|
parts = strings.SplitN(hostname, ".", 2)
|
||||||
|
)
|
||||||
|
if len(parts) > 1 {
|
||||||
|
hostname = parts[0]
|
||||||
|
domainname = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
ports, portBindings, err := nat.ParsePortSpecs(flPublish.GetAll())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, cmd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge in exposed ports to the map of published ports
|
||||||
|
for _, e := range flExpose.GetAll() {
|
||||||
|
if strings.Contains(e, ":") {
|
||||||
|
return nil, nil, cmd, fmt.Errorf("Invalid port format for --expose: %s", e)
|
||||||
|
}
|
||||||
|
p := nat.NewPort(nat.SplitProtoPort(e))
|
||||||
|
if _, exists := ports[p]; !exists {
|
||||||
|
ports[p] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &Config{
|
||||||
|
Hostname: hostname,
|
||||||
|
Domainname: domainname,
|
||||||
|
PortSpecs: nil, // Deprecated
|
||||||
|
ExposedPorts: ports,
|
||||||
|
User: *flUser,
|
||||||
|
Tty: *flTty,
|
||||||
|
NetworkDisabled: !*flNetwork,
|
||||||
|
OpenStdin: *flStdin,
|
||||||
|
Memory: flMemory,
|
||||||
|
CpuShares: *flCpuShares,
|
||||||
|
AttachStdin: flAttach.Get("stdin"),
|
||||||
|
AttachStdout: flAttach.Get("stdout"),
|
||||||
|
AttachStderr: flAttach.Get("stderr"),
|
||||||
|
Env: flEnv.GetAll(),
|
||||||
|
Cmd: runCmd,
|
||||||
|
Dns: flDns.GetAll(),
|
||||||
|
Image: image,
|
||||||
|
Volumes: flVolumes.GetMap(),
|
||||||
|
VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","),
|
||||||
|
Entrypoint: entrypoint,
|
||||||
|
WorkingDir: *flWorkingDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
hostConfig := &HostConfig{
|
||||||
|
Binds: binds,
|
||||||
|
ContainerIDFile: *flContainerIDFile,
|
||||||
|
LxcConf: lxcConf,
|
||||||
|
Privileged: *flPrivileged,
|
||||||
|
PortBindings: portBindings,
|
||||||
|
Links: flLinks.GetAll(),
|
||||||
|
PublishAllPorts: *flPublishAll,
|
||||||
|
}
|
||||||
|
|
||||||
|
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
||||||
|
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
||||||
|
config.MemorySwap = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// When allocating stdin in attached mode, close stdin at client disconnect
|
||||||
|
if config.OpenStdin && config.AttachStdin {
|
||||||
|
config.StdinOnce = true
|
||||||
|
}
|
||||||
|
return config, hostConfig, cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseLxcConfOpts(opts opts.ListOpts) ([]KeyValuePair, error) {
|
||||||
|
out := make([]KeyValuePair, opts.Len())
|
||||||
|
for i, o := range opts.GetAll() {
|
||||||
|
k, v, err := parseLxcOpt(o)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[i] = KeyValuePair{Key: k, Value: v}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseLxcOpt(opt string) (string, string, error) {
|
||||||
|
parts := strings.SplitN(opt, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package runconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseLxcConfOpt(t *testing.T) {
|
||||||
|
opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
k, v, err := parseLxcOpt(o)
|
||||||
|
if err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if k != "lxc.utsname" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if v != "docker" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
runtime.go
11
runtime.go
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/dotcloud/docker/networkdriver/portallocator"
|
"github.com/dotcloud/docker/networkdriver/portallocator"
|
||||||
"github.com/dotcloud/docker/pkg/graphdb"
|
"github.com/dotcloud/docker/pkg/graphdb"
|
||||||
"github.com/dotcloud/docker/pkg/sysinfo"
|
"github.com/dotcloud/docker/pkg/sysinfo"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -329,7 +330,7 @@ func (runtime *Runtime) restore() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create creates a new container from the given configuration with a given name.
|
// Create creates a new container from the given configuration with a given name.
|
||||||
func (runtime *Runtime) Create(config *Config, name string) (*Container, []string, error) {
|
func (runtime *Runtime) Create(config *runconfig.Config, name string) (*Container, []string, error) {
|
||||||
// Lookup image
|
// Lookup image
|
||||||
img, err := runtime.repositories.LookupImage(config.Image)
|
img, err := runtime.repositories.LookupImage(config.Image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -347,7 +348,7 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
|
||||||
return nil, nil, fmt.Errorf("Cannot create container with more than %d parents", MaxImageDepth)
|
return nil, nil, fmt.Errorf("Cannot create container with more than %d parents", MaxImageDepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDeprecatedExpose := func(config *Config) bool {
|
checkDeprecatedExpose := func(config *runconfig.Config) bool {
|
||||||
if config != nil {
|
if config != nil {
|
||||||
if config.PortSpecs != nil {
|
if config.PortSpecs != nil {
|
||||||
for _, p := range config.PortSpecs {
|
for _, p := range config.PortSpecs {
|
||||||
|
@ -366,7 +367,7 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
|
||||||
}
|
}
|
||||||
|
|
||||||
if img.Config != nil {
|
if img.Config != nil {
|
||||||
if err := MergeConfig(config, img.Config); err != nil {
|
if err := runconfig.Merge(config, img.Config); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,7 +442,7 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
|
||||||
Path: entrypoint,
|
Path: entrypoint,
|
||||||
Args: args, //FIXME: de-duplicate from config
|
Args: args, //FIXME: de-duplicate from config
|
||||||
Config: config,
|
Config: config,
|
||||||
hostConfig: &HostConfig{},
|
hostConfig: &runconfig.HostConfig{},
|
||||||
Image: img.ID, // Always use the resolved image id
|
Image: img.ID, // Always use the resolved image id
|
||||||
NetworkSettings: &NetworkSettings{},
|
NetworkSettings: &NetworkSettings{},
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -518,7 +519,7 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
|
||||||
|
|
||||||
// Commit creates a new filesystem image from the current state of a container.
|
// Commit creates a new filesystem image from the current state of a container.
|
||||||
// The image can optionally be tagged into a repository
|
// The image can optionally be tagged into a repository
|
||||||
func (runtime *Runtime) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
|
func (runtime *Runtime) Commit(container *Container, repository, tag, comment, author string, config *runconfig.Config) (*Image, error) {
|
||||||
// FIXME: freeze the container before copying it to avoid data corruption?
|
// FIXME: freeze the container before copying it to avoid data corruption?
|
||||||
// FIXME: this shouldn't be in commands.
|
// FIXME: this shouldn't be in commands.
|
||||||
if err := container.Mount(); err != nil {
|
if err := container.Mount(); err != nil {
|
||||||
|
|
17
server.go
17
server.go
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/dotcloud/docker/engine"
|
"github.com/dotcloud/docker/engine"
|
||||||
"github.com/dotcloud/docker/pkg/graphdb"
|
"github.com/dotcloud/docker/pkg/graphdb"
|
||||||
"github.com/dotcloud/docker/registry"
|
"github.com/dotcloud/docker/registry"
|
||||||
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -662,7 +663,7 @@ func (srv *Server) ImageInsert(job *engine.Job) engine.Status {
|
||||||
}
|
}
|
||||||
defer file.Body.Close()
|
defer file.Body.Close()
|
||||||
|
|
||||||
config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.sysInfo)
|
config, _, _, err := runconfig.Parse([]string{img.ID, "echo", "insert", url, path}, srv.runtime.sysInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return job.Error(err)
|
return job.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -1043,7 +1044,7 @@ func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
|
||||||
if container == nil {
|
if container == nil {
|
||||||
return job.Errorf("No such container: %s", name)
|
return job.Errorf("No such container: %s", name)
|
||||||
}
|
}
|
||||||
var config Config
|
var config runconfig.Config
|
||||||
if err := job.GetenvJson("config", &config); err != nil {
|
if err := job.GetenvJson("config", &config); err != nil {
|
||||||
return job.Error(err)
|
return job.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -1623,7 +1624,7 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
|
||||||
} else if len(job.Args) > 1 {
|
} else if len(job.Args) > 1 {
|
||||||
return job.Errorf("Usage: %s", job.Name)
|
return job.Errorf("Usage: %s", job.Name)
|
||||||
}
|
}
|
||||||
config := ContainerConfigFromJob(job)
|
config := runconfig.ContainerConfigFromJob(job)
|
||||||
if config.Memory != 0 && config.Memory < 524288 {
|
if config.Memory != 0 && config.Memory < 524288 {
|
||||||
return job.Errorf("Minimum memory limit allowed is 512k")
|
return job.Errorf("Minimum memory limit allowed is 512k")
|
||||||
}
|
}
|
||||||
|
@ -1989,7 +1990,7 @@ func (srv *Server) canDeleteImage(imgID string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error) {
|
func (srv *Server) ImageGetCached(imgID string, config *runconfig.Config) (*Image, error) {
|
||||||
|
|
||||||
// Retrieve all images
|
// Retrieve all images
|
||||||
images, err := srv.runtime.graph.Map()
|
images, err := srv.runtime.graph.Map()
|
||||||
|
@ -2013,7 +2014,7 @@ func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if CompareConfig(&img.ContainerConfig, config) {
|
if runconfig.Compare(&img.ContainerConfig, config) {
|
||||||
if match == nil || match.Created.Before(img.Created) {
|
if match == nil || match.Created.Before(img.Created) {
|
||||||
match = img
|
match = img
|
||||||
}
|
}
|
||||||
|
@ -2022,7 +2023,7 @@ func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error)
|
||||||
return match, nil
|
return match, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) RegisterLinks(container *Container, hostConfig *HostConfig) error {
|
func (srv *Server) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error {
|
||||||
runtime := srv.runtime
|
runtime := srv.runtime
|
||||||
|
|
||||||
if hostConfig != nil && hostConfig.Links != nil {
|
if hostConfig != nil && hostConfig.Links != nil {
|
||||||
|
@ -2066,7 +2067,7 @@ func (srv *Server) ContainerStart(job *engine.Job) engine.Status {
|
||||||
}
|
}
|
||||||
// If no environment was set, then no hostconfig was passed.
|
// If no environment was set, then no hostconfig was passed.
|
||||||
if len(job.Environ()) > 0 {
|
if len(job.Environ()) > 0 {
|
||||||
hostConfig := ContainerHostConfigFromJob(job)
|
hostConfig := runconfig.ContainerHostConfigFromJob(job)
|
||||||
// Validate the HostConfig binds. Make sure that:
|
// Validate the HostConfig binds. Make sure that:
|
||||||
// 1) the source of a bind mount isn't /
|
// 1) the source of a bind mount isn't /
|
||||||
// The bind mount "/:/foo" isn't allowed.
|
// The bind mount "/:/foo" isn't allowed.
|
||||||
|
@ -2310,7 +2311,7 @@ func (srv *Server) JobInspect(job *engine.Job) engine.Status {
|
||||||
}
|
}
|
||||||
object = &struct {
|
object = &struct {
|
||||||
*Container
|
*Container
|
||||||
HostConfig *HostConfig
|
HostConfig *runconfig.HostConfig
|
||||||
}{container, container.hostConfig}
|
}{container, container.hostConfig}
|
||||||
default:
|
default:
|
||||||
return job.Errorf("Unknown kind: %s", kind)
|
return job.Errorf("Unknown kind: %s", kind)
|
||||||
|
|
205
utils.go
205
utils.go
|
@ -1,14 +1,12 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/dotcloud/docker/archive"
|
"github.com/dotcloud/docker/archive"
|
||||||
"github.com/dotcloud/docker/nat"
|
"github.com/dotcloud/docker/nat"
|
||||||
"github.com/dotcloud/docker/pkg/namesgenerator"
|
"github.com/dotcloud/docker/pkg/namesgenerator"
|
||||||
"github.com/dotcloud/docker/pkg/opts"
|
"github.com/dotcloud/docker/runconfig"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,204 +14,7 @@ type Change struct {
|
||||||
archive.Change
|
archive.Change
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare two Config struct. Do not compare the "Image" nor "Hostname" fields
|
func migratePortMappings(config *runconfig.Config, hostConfig *runconfig.HostConfig) error {
|
||||||
// If OpenStdin is set, then it differs
|
|
||||||
func CompareConfig(a, b *Config) bool {
|
|
||||||
if a == nil || b == nil ||
|
|
||||||
a.OpenStdin || b.OpenStdin {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if a.AttachStdout != b.AttachStdout ||
|
|
||||||
a.AttachStderr != b.AttachStderr ||
|
|
||||||
a.User != b.User ||
|
|
||||||
a.Memory != b.Memory ||
|
|
||||||
a.MemorySwap != b.MemorySwap ||
|
|
||||||
a.CpuShares != b.CpuShares ||
|
|
||||||
a.OpenStdin != b.OpenStdin ||
|
|
||||||
a.Tty != b.Tty ||
|
|
||||||
a.VolumesFrom != b.VolumesFrom {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(a.Cmd) != len(b.Cmd) ||
|
|
||||||
len(a.Dns) != len(b.Dns) ||
|
|
||||||
len(a.Env) != len(b.Env) ||
|
|
||||||
len(a.PortSpecs) != len(b.PortSpecs) ||
|
|
||||||
len(a.ExposedPorts) != len(b.ExposedPorts) ||
|
|
||||||
len(a.Entrypoint) != len(b.Entrypoint) ||
|
|
||||||
len(a.Volumes) != len(b.Volumes) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(a.Cmd); i++ {
|
|
||||||
if a.Cmd[i] != b.Cmd[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(a.Dns); i++ {
|
|
||||||
if a.Dns[i] != b.Dns[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(a.Env); i++ {
|
|
||||||
if a.Env[i] != b.Env[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(a.PortSpecs); i++ {
|
|
||||||
if a.PortSpecs[i] != b.PortSpecs[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range a.ExposedPorts {
|
|
||||||
if _, exists := b.ExposedPorts[k]; !exists {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(a.Entrypoint); i++ {
|
|
||||||
if a.Entrypoint[i] != b.Entrypoint[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for key := range a.Volumes {
|
|
||||||
if _, exists := b.Volumes[key]; !exists {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func MergeConfig(userConf, imageConf *Config) error {
|
|
||||||
if userConf.User == "" {
|
|
||||||
userConf.User = imageConf.User
|
|
||||||
}
|
|
||||||
if userConf.Memory == 0 {
|
|
||||||
userConf.Memory = imageConf.Memory
|
|
||||||
}
|
|
||||||
if userConf.MemorySwap == 0 {
|
|
||||||
userConf.MemorySwap = imageConf.MemorySwap
|
|
||||||
}
|
|
||||||
if userConf.CpuShares == 0 {
|
|
||||||
userConf.CpuShares = imageConf.CpuShares
|
|
||||||
}
|
|
||||||
if userConf.ExposedPorts == nil || len(userConf.ExposedPorts) == 0 {
|
|
||||||
userConf.ExposedPorts = imageConf.ExposedPorts
|
|
||||||
} else if imageConf.ExposedPorts != nil {
|
|
||||||
if userConf.ExposedPorts == nil {
|
|
||||||
userConf.ExposedPorts = make(nat.PortSet)
|
|
||||||
}
|
|
||||||
for port := range imageConf.ExposedPorts {
|
|
||||||
if _, exists := userConf.ExposedPorts[port]; !exists {
|
|
||||||
userConf.ExposedPorts[port] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if userConf.PortSpecs != nil && len(userConf.PortSpecs) > 0 {
|
|
||||||
if userConf.ExposedPorts == nil {
|
|
||||||
userConf.ExposedPorts = make(nat.PortSet)
|
|
||||||
}
|
|
||||||
ports, _, err := nat.ParsePortSpecs(userConf.PortSpecs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for port := range ports {
|
|
||||||
if _, exists := userConf.ExposedPorts[port]; !exists {
|
|
||||||
userConf.ExposedPorts[port] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
userConf.PortSpecs = nil
|
|
||||||
}
|
|
||||||
if imageConf.PortSpecs != nil && len(imageConf.PortSpecs) > 0 {
|
|
||||||
utils.Debugf("Migrating image port specs to containter: %s", strings.Join(imageConf.PortSpecs, ", "))
|
|
||||||
if userConf.ExposedPorts == nil {
|
|
||||||
userConf.ExposedPorts = make(nat.PortSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
ports, _, err := nat.ParsePortSpecs(imageConf.PortSpecs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for port := range ports {
|
|
||||||
if _, exists := userConf.ExposedPorts[port]; !exists {
|
|
||||||
userConf.ExposedPorts[port] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !userConf.Tty {
|
|
||||||
userConf.Tty = imageConf.Tty
|
|
||||||
}
|
|
||||||
if !userConf.OpenStdin {
|
|
||||||
userConf.OpenStdin = imageConf.OpenStdin
|
|
||||||
}
|
|
||||||
if !userConf.StdinOnce {
|
|
||||||
userConf.StdinOnce = imageConf.StdinOnce
|
|
||||||
}
|
|
||||||
if userConf.Env == nil || len(userConf.Env) == 0 {
|
|
||||||
userConf.Env = imageConf.Env
|
|
||||||
} else {
|
|
||||||
for _, imageEnv := range imageConf.Env {
|
|
||||||
found := false
|
|
||||||
imageEnvKey := strings.Split(imageEnv, "=")[0]
|
|
||||||
for _, userEnv := range userConf.Env {
|
|
||||||
userEnvKey := strings.Split(userEnv, "=")[0]
|
|
||||||
if imageEnvKey == userEnvKey {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
userConf.Env = append(userConf.Env, imageEnv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
|
|
||||||
userConf.Cmd = imageConf.Cmd
|
|
||||||
}
|
|
||||||
if userConf.Dns == nil || len(userConf.Dns) == 0 {
|
|
||||||
userConf.Dns = imageConf.Dns
|
|
||||||
} else {
|
|
||||||
//duplicates aren't an issue here
|
|
||||||
userConf.Dns = append(userConf.Dns, imageConf.Dns...)
|
|
||||||
}
|
|
||||||
if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
|
|
||||||
userConf.Entrypoint = imageConf.Entrypoint
|
|
||||||
}
|
|
||||||
if userConf.WorkingDir == "" {
|
|
||||||
userConf.WorkingDir = imageConf.WorkingDir
|
|
||||||
}
|
|
||||||
if userConf.VolumesFrom == "" {
|
|
||||||
userConf.VolumesFrom = imageConf.VolumesFrom
|
|
||||||
}
|
|
||||||
if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
|
|
||||||
userConf.Volumes = imageConf.Volumes
|
|
||||||
} else {
|
|
||||||
for k, v := range imageConf.Volumes {
|
|
||||||
userConf.Volumes[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseLxcConfOpts(opts opts.ListOpts) ([]KeyValuePair, error) {
|
|
||||||
out := make([]KeyValuePair, opts.Len())
|
|
||||||
for i, o := range opts.GetAll() {
|
|
||||||
k, v, err := parseLxcOpt(o)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
out[i] = KeyValuePair{Key: k, Value: v}
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseLxcOpt(opt string) (string, string, error) {
|
|
||||||
parts := strings.SplitN(opt, "=", 2)
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func migratePortMappings(config *Config, hostConfig *HostConfig) error {
|
|
||||||
if config.PortSpecs != nil {
|
if config.PortSpecs != nil {
|
||||||
ports, bindings, err := nat.ParsePortSpecs(config.PortSpecs)
|
ports, bindings, err := nat.ParsePortSpecs(config.PortSpecs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -222,7 +23,7 @@ func migratePortMappings(config *Config, hostConfig *HostConfig) error {
|
||||||
config.PortSpecs = nil
|
config.PortSpecs = nil
|
||||||
if len(bindings) > 0 {
|
if len(bindings) > 0 {
|
||||||
if hostConfig == nil {
|
if hostConfig == nil {
|
||||||
hostConfig = &HostConfig{}
|
hostConfig = &runconfig.HostConfig{}
|
||||||
}
|
}
|
||||||
hostConfig.PortBindings = bindings
|
hostConfig.PortBindings = bindings
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue