mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	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
					
				
					 23 changed files with 731 additions and 674 deletions
				
			
		
							
								
								
									
										11
									
								
								buildfile.go
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								buildfile.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -9,6 +9,7 @@ import (
 | 
			
		|||
	"github.com/dotcloud/docker/archive"
 | 
			
		||||
	"github.com/dotcloud/docker/auth"
 | 
			
		||||
	"github.com/dotcloud/docker/registry"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +39,7 @@ type buildFile struct {
 | 
			
		|||
 | 
			
		||||
	image      string
 | 
			
		||||
	maintainer string
 | 
			
		||||
	config     *Config
 | 
			
		||||
	config     *runconfig.Config
 | 
			
		||||
 | 
			
		||||
	contextPath string
 | 
			
		||||
	context     *utils.TarSum
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +102,7 @@ func (b *buildFile) CmdFrom(name string) error {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	b.image = image.ID
 | 
			
		||||
	b.config = &Config{}
 | 
			
		||||
	b.config = &runconfig.Config{}
 | 
			
		||||
	if image.Config != nil {
 | 
			
		||||
		b.config = image.Config
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -158,14 +159,14 @@ func (b *buildFile) CmdRun(args string) error {
 | 
			
		|||
	if b.image == "" {
 | 
			
		||||
		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 {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd := b.config.Cmd
 | 
			
		||||
	b.config.Cmd = nil
 | 
			
		||||
	MergeConfig(b.config, config)
 | 
			
		||||
	runconfig.Merge(b.config, config)
 | 
			
		||||
 | 
			
		||||
	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{
 | 
			
		||||
		runtime:       srv.runtime,
 | 
			
		||||
		srv:           srv,
 | 
			
		||||
		config:        &Config{},
 | 
			
		||||
		config:        &runconfig.Config{},
 | 
			
		||||
		outStream:     outStream,
 | 
			
		||||
		errStream:     errStream,
 | 
			
		||||
		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/nat"
 | 
			
		||||
	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/registry"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -1449,11 +1448,11 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
 | 
			
		|||
	v.Set("comment", *flComment)
 | 
			
		||||
	v.Set("author", *flAuthor)
 | 
			
		||||
	var (
 | 
			
		||||
		config *Config
 | 
			
		||||
		config *runconfig.Config
 | 
			
		||||
		env    engine.Env
 | 
			
		||||
	)
 | 
			
		||||
	if *flConfig != "" {
 | 
			
		||||
		config = &Config{}
 | 
			
		||||
		config = &runconfig.Config{}
 | 
			
		||||
		if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1743,210 +1742,9 @@ func (cli *DockerCli) CmdTag(args ...string) error {
 | 
			
		|||
	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 {
 | 
			
		||||
	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 {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,17 @@
 | 
			
		|||
package docker
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func parse(t *testing.T, args string) (*Config, *HostConfig, error) {
 | 
			
		||||
	config, hostConfig, _, err := ParseRun(strings.Split(args+" ubuntu bash", " "), nil)
 | 
			
		||||
func parse(t *testing.T, args string) (*runconfig.Config, *runconfig.HostConfig, error) {
 | 
			
		||||
	config, hostConfig, _, err := runconfig.Parse(strings.Split(args+" ubuntu bash", " "), nil)
 | 
			
		||||
	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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										117
									
								
								container.go
									
										
									
									
									
								
							
							
						
						
									
										117
									
								
								container.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -11,6 +11,7 @@ import (
 | 
			
		|||
	"github.com/dotcloud/docker/nat"
 | 
			
		||||
	"github.com/dotcloud/docker/pkg/mount"
 | 
			
		||||
	"github.com/dotcloud/docker/pkg/term"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"github.com/kr/pty"
 | 
			
		||||
	"io"
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,7 @@ type Container struct {
 | 
			
		|||
	Path string
 | 
			
		||||
	Args []string
 | 
			
		||||
 | 
			
		||||
	Config *Config
 | 
			
		||||
	Config *runconfig.Config
 | 
			
		||||
	State  State
 | 
			
		||||
	Image  string
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -68,109 +69,11 @@ type Container struct {
 | 
			
		|||
	// Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
 | 
			
		||||
	// Easier than migrating older container configs :)
 | 
			
		||||
	VolumesRW  map[string]bool
 | 
			
		||||
	hostConfig *HostConfig
 | 
			
		||||
	hostConfig *runconfig.HostConfig
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
	SrcPath string
 | 
			
		||||
	DstPath string
 | 
			
		||||
| 
						 | 
				
			
			@ -178,18 +81,10 @@ type BindMap struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrContainerStart           = errors.New("The container failed to start. Unknown error")
 | 
			
		||||
	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")
 | 
			
		||||
	ErrContainerStart        = errors.New("The container failed to start. Unknown error")
 | 
			
		||||
	ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KeyValuePair struct {
 | 
			
		||||
	Key   string
 | 
			
		||||
	Value string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME: move deprecated port stuff to nat to clean up the core.
 | 
			
		||||
type PortMapping map[string]string // Deprecated
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +187,7 @@ func (container *Container) ToDisk() (err error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (container *Container) readHostConfig() error {
 | 
			
		||||
	container.hostConfig = &HostConfig{}
 | 
			
		||||
	container.hostConfig = &runconfig.HostConfig{}
 | 
			
		||||
	// If the hostconfig file does not exist, do not read it.
 | 
			
		||||
	// (We still have to initialize container.hostConfig,
 | 
			
		||||
	// but that's OK, since we just did that above.)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,23 +5,6 @@ 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()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseNetworkOptsPrivateOnly(t *testing.T) {
 | 
			
		||||
	ports, bindings, err := nat.ParsePortSpecs([]string{"192.168.1.100::80"})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								graph.go
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								graph.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"github.com/dotcloud/docker/archive"
 | 
			
		||||
	"github.com/dotcloud/docker/dockerversion"
 | 
			
		||||
	"github.com/dotcloud/docker/graphdriver"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"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.
 | 
			
		||||
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{
 | 
			
		||||
		ID:            GenerateID(),
 | 
			
		||||
		Comment:       comment,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										23
									
								
								image.go
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								image.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"github.com/dotcloud/docker/archive"
 | 
			
		||||
	"github.com/dotcloud/docker/graphdriver"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -18,17 +19,17 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
type Image struct {
 | 
			
		||||
	ID              string    `json:"id"`
 | 
			
		||||
	Parent          string    `json:"parent,omitempty"`
 | 
			
		||||
	Comment         string    `json:"comment,omitempty"`
 | 
			
		||||
	Created         time.Time `json:"created"`
 | 
			
		||||
	Container       string    `json:"container,omitempty"`
 | 
			
		||||
	ContainerConfig Config    `json:"container_config,omitempty"`
 | 
			
		||||
	DockerVersion   string    `json:"docker_version,omitempty"`
 | 
			
		||||
	Author          string    `json:"author,omitempty"`
 | 
			
		||||
	Config          *Config   `json:"config,omitempty"`
 | 
			
		||||
	Architecture    string    `json:"architecture,omitempty"`
 | 
			
		||||
	OS              string    `json:"os,omitempty"`
 | 
			
		||||
	ID              string            `json:"id"`
 | 
			
		||||
	Parent          string            `json:"parent,omitempty"`
 | 
			
		||||
	Comment         string            `json:"comment,omitempty"`
 | 
			
		||||
	Created         time.Time         `json:"created"`
 | 
			
		||||
	Container       string            `json:"container,omitempty"`
 | 
			
		||||
	ContainerConfig runconfig.Config  `json:"container_config,omitempty"`
 | 
			
		||||
	DockerVersion   string            `json:"docker_version,omitempty"`
 | 
			
		||||
	Author          string            `json:"author,omitempty"`
 | 
			
		||||
	Config          *runconfig.Config `json:"config,omitempty"`
 | 
			
		||||
	Architecture    string            `json:"architecture,omitempty"`
 | 
			
		||||
	OS              string            `json:"os,omitempty"`
 | 
			
		||||
	graph           *Graph
 | 
			
		||||
	Size            int64
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import (
 | 
			
		|||
	"github.com/dotcloud/docker/api"
 | 
			
		||||
	"github.com/dotcloud/docker/dockerversion"
 | 
			
		||||
	"github.com/dotcloud/docker/engine"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +310,7 @@ func TestGetContainersJSON(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
	beginLen := len(outs.Data)
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng, &docker.Config{
 | 
			
		||||
	containerID := createTestContainer(eng, &runconfig.Config{
 | 
			
		||||
		Image: unitTestImageID,
 | 
			
		||||
		Cmd:   []string{"echo", "test"},
 | 
			
		||||
	}, t)
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +347,7 @@ func TestGetContainersExport(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Create a container and remove a file
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: unitTestImageID,
 | 
			
		||||
			Cmd:   []string{"touch", "/test"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -394,7 +395,7 @@ func TestGetContainersChanges(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Create a container and remove a file
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: unitTestImageID,
 | 
			
		||||
			Cmd:   []string{"/bin/rm", "/etc/passwd"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -433,7 +434,7 @@ func TestGetContainersTop(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/sh", "-c", "cat"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -510,7 +511,7 @@ func TestGetContainersByName(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Create a container and remove a file
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: unitTestImageID,
 | 
			
		||||
			Cmd:   []string{"echo", "test"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -542,7 +543,7 @@ func TestPostCommit(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Create a container and remove a file
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: unitTestImageID,
 | 
			
		||||
			Cmd:   []string{"touch", "/test"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -578,7 +579,7 @@ func TestPostContainersCreate(t *testing.T) {
 | 
			
		|||
	eng := NewTestEngine(t)
 | 
			
		||||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	configJSON, err := json.Marshal(&docker.Config{
 | 
			
		||||
	configJSON, err := json.Marshal(&runconfig.Config{
 | 
			
		||||
		Image:  unitTestImageID,
 | 
			
		||||
		Memory: 33554432,
 | 
			
		||||
		Cmd:    []string{"touch", "/test"},
 | 
			
		||||
| 
						 | 
				
			
			@ -620,7 +621,7 @@ func TestPostContainersKill(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/cat"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -659,7 +660,7 @@ func TestPostContainersRestart(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/top"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -705,7 +706,7 @@ func TestPostContainersStart(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	containerID := createTestContainer(
 | 
			
		||||
		eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/cat"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -713,7 +714,7 @@ func TestPostContainersStart(t *testing.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))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -758,7 +759,7 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	containerID := createTestContainer(
 | 
			
		||||
		eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/cat"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -766,7 +767,7 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
 | 
			
		|||
		t,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	hostConfigJSON, err := json.Marshal(&docker.HostConfig{
 | 
			
		||||
	hostConfigJSON, err := json.Marshal(&runconfig.HostConfig{
 | 
			
		||||
		Binds: []string{"/:/tmp"},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -792,7 +793,7 @@ func TestPostContainersStop(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/top"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -832,7 +833,7 @@ func TestPostContainersWait(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/sleep", "1"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -870,7 +871,7 @@ func TestPostContainersAttach(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/cat"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -948,7 +949,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:     unitTestImageID,
 | 
			
		||||
			Cmd:       []string{"/bin/sh", "-c", "/bin/cat >&2"},
 | 
			
		||||
			OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -1029,7 +1030,7 @@ func TestDeleteContainers(t *testing.T) {
 | 
			
		|||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: unitTestImageID,
 | 
			
		||||
			Cmd:   []string{"touch", "/test"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -1164,7 +1165,7 @@ func TestPostContainersCopy(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Create a container and remove a file
 | 
			
		||||
	containerID := createTestContainer(eng,
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: unitTestImageID,
 | 
			
		||||
			Cmd:   []string{"touch", "/test.txt"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ package docker
 | 
			
		|||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/dotcloud/docker"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ func TestIDFormat(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container1, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:   []string{"/bin/sh", "-c", "echo hello world"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +234,7 @@ func TestCommitAutoRun(t *testing.T) {
 | 
			
		|||
		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 {
 | 
			
		||||
		t.Error(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +415,7 @@ func TestOutput(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:   []string{"echo", "-n", "foobar"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -438,7 +438,7 @@ func TestContainerNetwork(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:   []string{"ping", "-c", "1", "127.0.0.1"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -460,7 +460,7 @@ func TestKillDifferentUser(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image:     GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:       []string{"cat"},
 | 
			
		||||
		OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -520,7 +520,7 @@ func TestCreateVolume(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -552,7 +552,7 @@ func TestCreateVolume(t *testing.T) {
 | 
			
		|||
func TestKill(t *testing.T) {
 | 
			
		||||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"sleep", "2"},
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -596,7 +596,7 @@ func TestExitCode(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	trueContainer, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	trueContainer, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"/bin/true"},
 | 
			
		||||
	}, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -611,7 +611,7 @@ func TestExitCode(t *testing.T) {
 | 
			
		|||
		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,
 | 
			
		||||
		Cmd:   []string{"/bin/false"},
 | 
			
		||||
	}, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -630,7 +630,7 @@ func TestExitCode(t *testing.T) {
 | 
			
		|||
func TestRestart(t *testing.T) {
 | 
			
		||||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"echo", "-n", "foobar"},
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -661,7 +661,7 @@ func TestRestart(t *testing.T) {
 | 
			
		|||
func TestRestartStdin(t *testing.T) {
 | 
			
		||||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"cat"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -739,7 +739,7 @@ func TestUser(t *testing.T) {
 | 
			
		|||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	// Default user must be root
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"id"},
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -758,7 +758,7 @@ func TestUser(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Set a username
 | 
			
		||||
	container, _, err = runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err = runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"id"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -779,7 +779,7 @@ func TestUser(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Set a UID
 | 
			
		||||
	container, _, err = runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err = runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"id"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -800,7 +800,7 @@ func TestUser(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Set a different user by uid
 | 
			
		||||
	container, _, err = runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err = runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"id"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -823,7 +823,7 @@ func TestUser(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Set a different user by username
 | 
			
		||||
	container, _, err = runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err = runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"id"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -844,7 +844,7 @@ func TestUser(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Test an wrong username
 | 
			
		||||
	container, _, err = runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err = runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"id"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -866,7 +866,7 @@ func TestMultipleContainers(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container1, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container1, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"sleep", "2"},
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +877,7 @@ func TestMultipleContainers(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
	defer runtime.Destroy(container1)
 | 
			
		||||
 | 
			
		||||
	container2, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container2, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"sleep", "2"},
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -921,7 +921,7 @@ func TestMultipleContainers(t *testing.T) {
 | 
			
		|||
func TestStdin(t *testing.T) {
 | 
			
		||||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"cat"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -966,7 +966,7 @@ func TestStdin(t *testing.T) {
 | 
			
		|||
func TestTty(t *testing.T) {
 | 
			
		||||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"cat"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1013,7 +1013,7 @@ func TestEnv(t *testing.T) {
 | 
			
		|||
	os.Setenv("TRICKY", "tri\ncky\n")
 | 
			
		||||
	runtime := mkRuntime(t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1067,7 +1067,7 @@ func TestEntrypoint(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:      GetTestImage(runtime).ID,
 | 
			
		||||
			Entrypoint: []string{"/bin/echo"},
 | 
			
		||||
			Cmd:        []string{"-n", "foobar"},
 | 
			
		||||
| 
						 | 
				
			
			@ -1091,7 +1091,7 @@ func TestEntrypointNoCmd(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:      GetTestImage(runtime).ID,
 | 
			
		||||
			Entrypoint: []string{"/bin/echo", "foobar"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -1114,7 +1114,7 @@ func BenchmarkRunSequencial(b *testing.B) {
 | 
			
		|||
	runtime := mkRuntime(b)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	for i := 0; i < b.N; i++ {
 | 
			
		||||
		container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
		container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
			Image: GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:   []string{"echo", "-n", "foo"},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -1147,7 +1147,7 @@ func BenchmarkRunParallel(b *testing.B) {
 | 
			
		|||
		complete := make(chan error)
 | 
			
		||||
		tasks = append(tasks, complete)
 | 
			
		||||
		go func(i int, complete chan error) {
 | 
			
		||||
			container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
			container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
				Image: GetTestImage(runtime).ID,
 | 
			
		||||
				Cmd:   []string{"echo", "-n", "foo"},
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -1301,7 +1301,7 @@ func TestFromVolumesInReadonlyMode(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:   GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:     []string{"/bin/echo", "-n", "foobar"},
 | 
			
		||||
			Volumes: map[string]struct{}{"/test": {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -1321,7 +1321,7 @@ func TestFromVolumesInReadonlyMode(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	container2, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:       GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:         []string{"/bin/echo", "-n", "foobar"},
 | 
			
		||||
			VolumesFrom: container.ID + ":ro",
 | 
			
		||||
| 
						 | 
				
			
			@ -1362,7 +1362,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:   GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:     []string{"/bin/echo", "-n", "foobar"},
 | 
			
		||||
			Volumes: map[string]struct{}{"/test": {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -1382,7 +1382,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	container2, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:       GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:         []string{"/bin/echo", "-n", "foobar"},
 | 
			
		||||
			VolumesFrom: container.ID,
 | 
			
		||||
| 
						 | 
				
			
			@ -1418,7 +1418,7 @@ func TestRestartWithVolumes(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image:   GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:     []string{"echo", "-n", "foobar"},
 | 
			
		||||
		Volumes: map[string]struct{}{"/test": {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -1462,7 +1462,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image:   GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:     []string{"sh", "-c", "echo -n bar > /test/foo"},
 | 
			
		||||
		Volumes: map[string]struct{}{"/test": {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -1491,7 +1491,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	container2, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:       GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:         []string{"cat", "/test/foo"},
 | 
			
		||||
			VolumesFrom: container.ID,
 | 
			
		||||
| 
						 | 
				
			
			@ -1529,7 +1529,7 @@ func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1617,7 +1617,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image:   GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:     []string{"sh", "-c", "echo -n bar > /test/foo"},
 | 
			
		||||
		Volumes: map[string]struct{}{"/test": {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -1646,7 +1646,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	container2, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:   GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:     []string{"sh", "-c", "echo -n bar > /other/foo"},
 | 
			
		||||
			Volumes: map[string]struct{}{"/other": {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -1668,7 +1668,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	container3, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:       GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:         []string{"/bin/echo", "-n", "foobar"},
 | 
			
		||||
			VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","),
 | 
			
		||||
| 
						 | 
				
			
			@ -1696,7 +1696,7 @@ func TestRestartGhost(t *testing.T) {
 | 
			
		|||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image:   GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:     []string{"sh", "-c", "echo -n bar > /test/foo"},
 | 
			
		||||
			Volumes: map[string]struct{}{"/test": {}},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import (
 | 
			
		|||
	"github.com/dotcloud/docker"
 | 
			
		||||
	"github.com/dotcloud/docker/engine"
 | 
			
		||||
	"github.com/dotcloud/docker/nat"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/sysinit"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +201,7 @@ func TestRuntimeCreate(t *testing.T) {
 | 
			
		|||
		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,
 | 
			
		||||
		Cmd:   []string{"ls", "-al"},
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -243,23 +244,23 @@ func TestRuntimeCreate(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Test that conflict error displays correct details
 | 
			
		||||
	testContainer, _, _ := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:   []string{"ls", "-al"},
 | 
			
		||||
		},
 | 
			
		||||
		"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())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, _, err := runtime.Create(
 | 
			
		||||
		&docker.Config{
 | 
			
		||||
		&runconfig.Config{
 | 
			
		||||
			Image: GetTestImage(runtime).ID,
 | 
			
		||||
			Cmd:   []string{},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +269,7 @@ func TestRuntimeCreate(t *testing.T) {
 | 
			
		|||
		t.Fatal("Builder.Create should throw an error when Cmd is empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config := &docker.Config{
 | 
			
		||||
	config := &runconfig.Config{
 | 
			
		||||
		Image:     GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:       []string{"/bin/ls"},
 | 
			
		||||
		PortSpecs: []string{"80"},
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +282,7 @@ func TestRuntimeCreate(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// test expose 80:8000
 | 
			
		||||
	container, warnings, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, warnings, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image:     GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:       []string{"ls", "-al"},
 | 
			
		||||
		PortSpecs: []string{"80:8000"},
 | 
			
		||||
| 
						 | 
				
			
			@ -300,7 +301,7 @@ func TestDestroy(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"ls", "-al"},
 | 
			
		||||
	}, "")
 | 
			
		||||
| 
						 | 
				
			
			@ -712,7 +713,7 @@ func TestDefaultContainerName(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -736,7 +737,7 @@ func TestRandomContainerName(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -767,7 +768,7 @@ func TestContainerNameValidation(t *testing.T) {
 | 
			
		|||
		{"abc-123_AAA.1", true},
 | 
			
		||||
		{"\000asdf", false},
 | 
			
		||||
	} {
 | 
			
		||||
		config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
		config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if !test.Valid {
 | 
			
		||||
				continue
 | 
			
		||||
| 
						 | 
				
			
			@ -808,7 +809,7 @@ func TestLinkChildContainer(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -850,7 +851,7 @@ func TestGetAllChildren(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config, _, _, err = docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	config, _, _, err = runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -903,7 +904,7 @@ func TestDestroyWithInitLayer(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntime(t)
 | 
			
		||||
	defer nuke(runtime)
 | 
			
		||||
 | 
			
		||||
	container, _, err := runtime.Create(&docker.Config{
 | 
			
		||||
	container, _, err := runtime.Create(&runconfig.Config{
 | 
			
		||||
		Image: GetTestImage(runtime).ID,
 | 
			
		||||
		Cmd:   []string{"ls", "-al"},
 | 
			
		||||
	}, "")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package docker
 | 
			
		|||
import (
 | 
			
		||||
	"github.com/dotcloud/docker"
 | 
			
		||||
	"github.com/dotcloud/docker/engine"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +72,7 @@ func TestCreateRm(t *testing.T) {
 | 
			
		|||
	eng := NewTestEngine(t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +119,7 @@ func TestCreateNumberHostname(t *testing.T) {
 | 
			
		|||
	eng := NewTestEngine(t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +131,7 @@ func TestCreateNumberUsername(t *testing.T) {
 | 
			
		|||
	eng := NewTestEngine(t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +143,7 @@ func TestCreateRmVolumes(t *testing.T) {
 | 
			
		|||
	eng := NewTestEngine(t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +203,7 @@ func TestCommit(t *testing.T) {
 | 
			
		|||
	eng := NewTestEngine(t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +225,7 @@ func TestRestartKillWait(t *testing.T) {
 | 
			
		|||
	runtime := mkRuntimeFromEngine(eng, t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +303,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
 | 
			
		|||
	srv := mkServerFromEngine(eng, t)
 | 
			
		||||
	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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -401,7 +402,7 @@ func TestRmi(t *testing.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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -548,7 +549,7 @@ func TestListContainers(t *testing.T) {
 | 
			
		|||
	srv := mkServerFromEngine(eng, t)
 | 
			
		||||
	defer mkRuntimeFromEngine(eng, t).Nuke()
 | 
			
		||||
 | 
			
		||||
	config := docker.Config{
 | 
			
		||||
	config := runconfig.Config{
 | 
			
		||||
		Image:     unitTestImageID,
 | 
			
		||||
		Cmd:       []string{"/bin/sh", "-c", "cat"},
 | 
			
		||||
		OpenStdin: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -671,7 +672,7 @@ func TestDeleteTagWithExistingContainers(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// 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 {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/dotcloud/docker"
 | 
			
		||||
	"github.com/dotcloud/docker/engine"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +49,7 @@ func mkRuntime(f utils.Fataler) *docker.Runtime {
 | 
			
		|||
	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)
 | 
			
		||||
	if err := job.ImportEnv(config); err != nil {
 | 
			
		||||
		f.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +61,7 @@ func createNamedTestContainer(eng *engine.Engine, config *docker.Config, f utils
 | 
			
		|||
	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, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -252,8 +253,8 @@ func readFile(src string, t *testing.T) (content string) {
 | 
			
		|||
// dynamically replaced by the current test image.
 | 
			
		||||
// The caller is responsible for destroying the container.
 | 
			
		||||
// Call t.Fatal() at the first error.
 | 
			
		||||
func mkContainer(r *docker.Runtime, args []string, t *testing.T) (*docker.Container, *docker.HostConfig, error) {
 | 
			
		||||
	config, hc, _, err := docker.ParseRun(args, nil)
 | 
			
		||||
func mkContainer(r *docker.Runtime, args []string, t *testing.T) (*docker.Container, *runconfig.HostConfig, error) {
 | 
			
		||||
	config, hc, _, err := runconfig.Parse(args, nil)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err != nil && t != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,13 +2,14 @@ package docker
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/dotcloud/docker/nat"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func newMockLinkContainer(id string, ip string) *Container {
 | 
			
		||||
	return &Container{
 | 
			
		||||
		Config: &Config{},
 | 
			
		||||
		Config: &runconfig.Config{},
 | 
			
		||||
		ID:     id,
 | 
			
		||||
		NetworkSettings: &NetworkSettings{
 | 
			
		||||
			IPAddress: ip,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										67
									
								
								runconfig/compare.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								runconfig/compare.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								runconfig/config.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								runconfig/config.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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 (
 | 
			
		||||
	"github.com/dotcloud/docker/nat"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestCompareConfig(t *testing.T) {
 | 
			
		||||
func TestCompare(t *testing.T) {
 | 
			
		||||
	volumes1 := make(map[string]struct{})
 | 
			
		||||
	volumes1["/test1"] = struct{}{}
 | 
			
		||||
	config1 := Config{
 | 
			
		||||
| 
						 | 
				
			
			@ -45,24 +45,24 @@ func TestCompareConfig(t *testing.T) {
 | 
			
		|||
		VolumesFrom: "11111111",
 | 
			
		||||
		Volumes:     volumes2,
 | 
			
		||||
	}
 | 
			
		||||
	if CompareConfig(&config1, &config2) {
 | 
			
		||||
		t.Fatalf("CompareConfig should return false, Dns are different")
 | 
			
		||||
	if Compare(&config1, &config2) {
 | 
			
		||||
		t.Fatalf("Compare should return false, Dns are different")
 | 
			
		||||
	}
 | 
			
		||||
	if CompareConfig(&config1, &config3) {
 | 
			
		||||
		t.Fatalf("CompareConfig should return false, PortSpecs are different")
 | 
			
		||||
	if Compare(&config1, &config3) {
 | 
			
		||||
		t.Fatalf("Compare should return false, PortSpecs are different")
 | 
			
		||||
	}
 | 
			
		||||
	if CompareConfig(&config1, &config4) {
 | 
			
		||||
		t.Fatalf("CompareConfig should return false, VolumesFrom are different")
 | 
			
		||||
	if Compare(&config1, &config4) {
 | 
			
		||||
		t.Fatalf("Compare should return false, VolumesFrom are different")
 | 
			
		||||
	}
 | 
			
		||||
	if CompareConfig(&config1, &config5) {
 | 
			
		||||
		t.Fatalf("CompareConfig should return false, Volumes are different")
 | 
			
		||||
	if Compare(&config1, &config5) {
 | 
			
		||||
		t.Fatalf("Compare should return false, Volumes are different")
 | 
			
		||||
	}
 | 
			
		||||
	if !CompareConfig(&config1, &config1) {
 | 
			
		||||
		t.Fatalf("CompareConfig should return true")
 | 
			
		||||
	if !Compare(&config1, &config1) {
 | 
			
		||||
		t.Fatalf("Compare should return true")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestMergeConfig(t *testing.T) {
 | 
			
		||||
func TestMerge(t *testing.T) {
 | 
			
		||||
	volumesImage := make(map[string]struct{})
 | 
			
		||||
	volumesImage["/test1"] = struct{}{}
 | 
			
		||||
	volumesImage["/test2"] = struct{}{}
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +83,7 @@ func TestMergeConfig(t *testing.T) {
 | 
			
		|||
		Volumes:   volumesUser,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := MergeConfig(configUser, configImage); err != nil {
 | 
			
		||||
	if err := Merge(configUser, configImage); err != nil {
 | 
			
		||||
		t.Error(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +134,7 @@ func TestMergeConfig(t *testing.T) {
 | 
			
		|||
		ExposedPorts: ports,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := MergeConfig(configUser, configImage2); err != nil {
 | 
			
		||||
	if err := Merge(configUser, configImage2); err != nil {
 | 
			
		||||
		t.Error(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								runconfig/hostconfig.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								runconfig/hostconfig.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										119
									
								
								runconfig/merge.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								runconfig/merge.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										246
									
								
								runconfig/parse.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								runconfig/parse.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								runconfig/parse_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								runconfig/parse_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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/pkg/graphdb"
 | 
			
		||||
	"github.com/dotcloud/docker/pkg/sysinfo"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -329,7 +330,7 @@ func (runtime *Runtime) restore() error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
	img, err := runtime.repositories.LookupImage(config.Image)
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	checkDeprecatedExpose := func(config *Config) bool {
 | 
			
		||||
	checkDeprecatedExpose := func(config *runconfig.Config) bool {
 | 
			
		||||
		if config != nil {
 | 
			
		||||
			if config.PortSpecs != nil {
 | 
			
		||||
				for _, p := range config.PortSpecs {
 | 
			
		||||
| 
						 | 
				
			
			@ -366,7 +367,7 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +442,7 @@ func (runtime *Runtime) Create(config *Config, name string) (*Container, []strin
 | 
			
		|||
		Path:            entrypoint,
 | 
			
		||||
		Args:            args, //FIXME: de-duplicate from config
 | 
			
		||||
		Config:          config,
 | 
			
		||||
		hostConfig:      &HostConfig{},
 | 
			
		||||
		hostConfig:      &runconfig.HostConfig{},
 | 
			
		||||
		Image:           img.ID, // Always use the resolved image id
 | 
			
		||||
		NetworkSettings: &NetworkSettings{},
 | 
			
		||||
		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.
 | 
			
		||||
// 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: this shouldn't be in commands.
 | 
			
		||||
	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/pkg/graphdb"
 | 
			
		||||
	"github.com/dotcloud/docker/registry"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -662,7 +663,7 @@ func (srv *Server) ImageInsert(job *engine.Job) engine.Status {
 | 
			
		|||
	}
 | 
			
		||||
	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 {
 | 
			
		||||
		return job.Error(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1043,7 +1044,7 @@ func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
 | 
			
		|||
	if container == nil {
 | 
			
		||||
		return job.Errorf("No such container: %s", name)
 | 
			
		||||
	}
 | 
			
		||||
	var config Config
 | 
			
		||||
	var config runconfig.Config
 | 
			
		||||
	if err := job.GetenvJson("config", &config); err != nil {
 | 
			
		||||
		return job.Error(err)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1623,7 +1624,7 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
 | 
			
		|||
	} else if len(job.Args) > 1 {
 | 
			
		||||
		return job.Errorf("Usage: %s", job.Name)
 | 
			
		||||
	}
 | 
			
		||||
	config := ContainerConfigFromJob(job)
 | 
			
		||||
	config := runconfig.ContainerConfigFromJob(job)
 | 
			
		||||
	if config.Memory != 0 && config.Memory < 524288 {
 | 
			
		||||
		return job.Errorf("Minimum memory limit allowed is 512k")
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1989,7 +1990,7 @@ func (srv *Server) canDeleteImage(imgID string) error {
 | 
			
		|||
	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
 | 
			
		||||
	images, err := srv.runtime.graph.Map()
 | 
			
		||||
| 
						 | 
				
			
			@ -2013,7 +2014,7 @@ func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error)
 | 
			
		|||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if CompareConfig(&img.ContainerConfig, config) {
 | 
			
		||||
		if runconfig.Compare(&img.ContainerConfig, config) {
 | 
			
		||||
			if match == nil || match.Created.Before(img.Created) {
 | 
			
		||||
				match = img
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -2022,7 +2023,7 @@ func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error)
 | 
			
		|||
	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
 | 
			
		||||
 | 
			
		||||
	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 len(job.Environ()) > 0 {
 | 
			
		||||
		hostConfig := ContainerHostConfigFromJob(job)
 | 
			
		||||
		hostConfig := runconfig.ContainerHostConfigFromJob(job)
 | 
			
		||||
		// Validate the HostConfig binds. Make sure that:
 | 
			
		||||
		// 1) the source of a bind mount isn't /
 | 
			
		||||
		//         The bind mount "/:/foo" isn't allowed.
 | 
			
		||||
| 
						 | 
				
			
			@ -2310,7 +2311,7 @@ func (srv *Server) JobInspect(job *engine.Job) engine.Status {
 | 
			
		|||
		}
 | 
			
		||||
		object = &struct {
 | 
			
		||||
			*Container
 | 
			
		||||
			HostConfig *HostConfig
 | 
			
		||||
			HostConfig *runconfig.HostConfig
 | 
			
		||||
		}{container, container.hostConfig}
 | 
			
		||||
	default:
 | 
			
		||||
		return job.Errorf("Unknown kind: %s", kind)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										205
									
								
								utils.go
									
										
									
									
									
								
							
							
						
						
									
										205
									
								
								utils.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,14 +1,12 @@
 | 
			
		|||
package docker
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/dotcloud/docker/archive"
 | 
			
		||||
	"github.com/dotcloud/docker/nat"
 | 
			
		||||
	"github.com/dotcloud/docker/pkg/namesgenerator"
 | 
			
		||||
	"github.com/dotcloud/docker/pkg/opts"
 | 
			
		||||
	"github.com/dotcloud/docker/runconfig"
 | 
			
		||||
	"github.com/dotcloud/docker/utils"
 | 
			
		||||
	"io"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,204 +14,7 @@ type Change struct {
 | 
			
		|||
	archive.Change
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compare two Config struct. Do not compare the "Image" nor "Hostname" fields
 | 
			
		||||
// 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 {
 | 
			
		||||
func migratePortMappings(config *runconfig.Config, hostConfig *runconfig.HostConfig) error {
 | 
			
		||||
	if config.PortSpecs != nil {
 | 
			
		||||
		ports, bindings, err := nat.ParsePortSpecs(config.PortSpecs)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +23,7 @@ func migratePortMappings(config *Config, hostConfig *HostConfig) error {
 | 
			
		|||
		config.PortSpecs = nil
 | 
			
		||||
		if len(bindings) > 0 {
 | 
			
		||||
			if hostConfig == nil {
 | 
			
		||||
				hostConfig = &HostConfig{}
 | 
			
		||||
				hostConfig = &runconfig.HostConfig{}
 | 
			
		||||
			}
 | 
			
		||||
			hostConfig.PortBindings = bindings
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue