Skip to content

Commit

Permalink
Merge pull request moby#2829 from dotcloud/refactor_opts
Browse files Browse the repository at this point in the history
Refactor opts
  • Loading branch information
crosbymichael committed Dec 2, 2013
2 parents e1414a4 + 2bbc90e commit fe571dd
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 137 deletions.
2 changes: 1 addition & 1 deletion buildfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func (b *buildFile) CmdVolume(args string) error {
volume = []string{args}
}
if b.config.Volumes == nil {
b.config.Volumes = PathOpts{}
b.config.Volumes = map[string]struct{}{}
}
for _, v := range volume {
b.config.Volumes[v] = struct{}{}
Expand Down
121 changes: 28 additions & 93 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"os"
"os/signal"
"path"
"path/filepath"
"reflect"
"regexp"
"runtime"
Expand Down Expand Up @@ -1622,58 +1621,6 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
// Ports type - Used to parse multiple -p flags
type ports []int

// AttachOpts stores arguments to 'docker run -a', eg. which streams to attach to
type AttachOpts map[string]bool

func (opts AttachOpts) String() string { return fmt.Sprintf("%v", map[string]bool(opts)) }
func (opts AttachOpts) Set(val string) error {
if val != "stdin" && val != "stdout" && val != "stderr" {
return fmt.Errorf("Unsupported stream name: %s", val)
}
opts[val] = true
return nil
}

// LinkOpts stores arguments to `docker run -link`
type LinkOpts []string

func (link *LinkOpts) String() string { return fmt.Sprintf("%v", []string(*link)) }
func (link *LinkOpts) Set(val string) error {
if _, err := parseLink(val); err != nil {
return err
}
*link = append(*link, val)
return nil
}

// PathOpts stores a unique set of absolute paths
type PathOpts map[string]struct{}

func (opts PathOpts) String() string { return fmt.Sprintf("%v", map[string]struct{}(opts)) }
func (opts PathOpts) Set(val string) error {
var containerPath string

if strings.Count(val, ":") > 2 {
return fmt.Errorf("bad format for volumes: %s", val)
}

if splited := strings.SplitN(val, ":", 2); len(splited) == 1 {
containerPath = splited[0]
val = filepath.Clean(splited[0])
} else {
containerPath = splited[1]
val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1]))
}

if !filepath.IsAbs(containerPath) {
utils.Debugf("%s is not an absolute path", containerPath)
return fmt.Errorf("%s is not an absolute path", containerPath)
}
opts[val] = struct{}{}

return nil
}

func (cli *DockerCli) CmdTag(args ...string) error {
cmd := cli.Subcmd("tag", "[OPTIONS] IMAGE REPOSITORY[:TAG]", "Tag an image into a repository")
force := cmd.Bool("f", false, "Force")
Expand Down Expand Up @@ -1719,16 +1666,16 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Config, *HostConfig, *flag.FlagSet, error) {
var (
// FIXME: use utils.ListOpts for attach and volumes?
flAttach = AttachOpts{}
flVolumes = PathOpts{}
flLinks = LinkOpts{}
flAttach = NewListOpts(ValidateAttach)
flVolumes = NewListOpts(ValidatePath)
flLinks = NewListOpts(ValidateLink)
flEnv = NewListOpts(ValidateEnv)

flPublish utils.ListOpts
flExpose utils.ListOpts
flEnv utils.ListOpts
flDns utils.ListOpts
flVolumesFrom utils.ListOpts
flLxcOpts utils.ListOpts
flPublish ListOpts
flExpose ListOpts
flDns ListOpts
flVolumesFrom ListOpts
flLxcOpts ListOpts

flAutoRemove = cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)")
flDetach = cmd.Bool("d", false, "Detached mode: Run container in the background, print new container id")
Expand All @@ -1750,13 +1697,13 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
_ = cmd.String("name", "", "Assign a name to the container")
)

cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.")
cmd.Var(flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
cmd.Var(&flAttach, "a", "Attach to stdin, stdout or stderr.")
cmd.Var(&flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
cmd.Var(&flLinks, "link", "Add link to another container (name:alias)")
cmd.Var(&flEnv, "e", "Set environment variables")

cmd.Var(&flPublish, "p", fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", PortSpecTemplateFormat))
cmd.Var(&flExpose, "expose", "Expose a port from the container without publishing it to your host")
cmd.Var(&flEnv, "e", "Set environment variables")
cmd.Var(&flDns, "dns", "Set custom dns servers")
cmd.Var(&flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)")
cmd.Var(&flLxcOpts, "lxc-conf", "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
Expand All @@ -1771,7 +1718,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
}

// Validate input params
if *flDetach && len(flAttach) > 0 {
if *flDetach && flAttach.Len() > 0 {
return nil, nil, cmd, ErrConflictAttachDetach
}
if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
Expand All @@ -1782,7 +1729,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
}

// If neither -d or -a are set, attach to everything by default
if len(flAttach) == 0 && !*flDetach {
if flAttach.Len() == 0 && !*flDetach {
if !*flDetach {
flAttach.Set("stdout")
flAttach.Set("stderr")
Expand All @@ -1792,17 +1739,6 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
}
}

var envs []string
for _, env := range flEnv {
arr := strings.Split(env, "=")
if len(arr) > 1 {
envs = append(envs, env)
} else {
v := os.Getenv(env)
envs = append(envs, env+"="+v)
}
}

var flMemory int64
if *flMemoryString != "" {
parsedMemory, err := utils.RAMInBytes(*flMemoryString)
Expand All @@ -1814,16 +1750,15 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co

var binds []string
// add any bind targets to the list of container volumes
for bind := range flVolumes {
arr := strings.Split(bind, ":")
if len(arr) > 1 {
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[dstDir] = struct{}{}
flVolumes.Set(dstDir)
binds = append(binds, bind)
delete(flVolumes, bind)
flVolumes.Delete(bind)
}
}

Expand Down Expand Up @@ -1858,13 +1793,13 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
domainname = parts[1]
}

ports, portBindings, err := parsePortSpecs(flPublish)
ports, portBindings, err := 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 {
for _, e := range flExpose.GetAll() {
if strings.Contains(e, ":") {
return nil, nil, cmd, fmt.Errorf("Invalid port format for -expose: %s", e)
}
Expand All @@ -1885,15 +1820,15 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
OpenStdin: *flStdin,
Memory: flMemory,
CpuShares: *flCpuShares,
AttachStdin: flAttach["stdin"],
AttachStdout: flAttach["stdout"],
AttachStderr: flAttach["stderr"],
Env: envs,
AttachStdin: flAttach.Get("stdin"),
AttachStdout: flAttach.Get("stdout"),
AttachStderr: flAttach.Get("stderr"),
Env: flEnv.GetAll(),
Cmd: runCmd,
Dns: flDns,
Dns: flDns.GetAll(),
Image: image,
Volumes: flVolumes,
VolumesFrom: strings.Join(flVolumesFrom, ","),
Volumes: flVolumes.GetMap(),
VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","),
Entrypoint: entrypoint,
WorkingDir: *flWorkingDir,
}
Expand All @@ -1904,7 +1839,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co
LxcConf: lxcConf,
Privileged: *flPrivileged,
PortBindings: portBindings,
Links: flLinks,
Links: flLinks.GetAll(),
PublishAllPorts: *flPublishAll,
}

Expand Down
51 changes: 23 additions & 28 deletions docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,34 @@ func main() {
sysinit.SysInit()
return
}
// FIXME: Switch d and D ? (to be more sshd like)
flVersion := flag.Bool("v", false, "Print version information and quit")
flDaemon := flag.Bool("d", false, "Enable daemon mode")
flDebug := flag.Bool("D", false, "Enable debug mode")
flAutoRestart := flag.Bool("r", true, "Restart previously running containers")
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
pidfile := flag.String("p", "/var/run/docker.pid", "Path to use for daemon PID file")
flRoot := flag.String("g", "/var/lib/docker", "Path to use as the root of the docker runtime")
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS headers in the remote API")
flDns := flag.String("dns", "", "Force docker to use specific DNS servers")
flHosts := utils.ListOpts{fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)}

var (
flVersion = flag.Bool("v", false, "Print version information and quit")
flDaemon = flag.Bool("d", false, "Enable daemon mode")
flDebug = flag.Bool("D", false, "Enable debug mode")
flAutoRestart = flag.Bool("r", true, "Restart previously running containers")
bridgeName = flag.String("b", "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
pidfile = flag.String("p", "/var/run/docker.pid", "Path to use for daemon PID file")
flRoot = flag.String("g", "/var/lib/docker", "Path to use as the root of the docker runtime")
flEnableCors = flag.Bool("api-enable-cors", false, "Enable CORS headers in the remote API")
flDns = flag.String("dns", "", "Force docker to use specific DNS servers")
flEnableIptables = flag.Bool("iptables", true, "Disable docker's addition of iptables rules")
flDefaultIp = flag.String("ip", "0.0.0.0", "Default IP address to use when binding container ports")
flInterContainerComm = flag.Bool("icc", true, "Enable inter-container communication")
flGraphDriver = flag.String("s", "", "Force the docker runtime to use a specific storage driver")
flHosts = docker.NewListOpts(docker.ValidateHost)
)
flag.Var(&flHosts, "H", "Multiple tcp://host:port or unix://path/to/socket to bind in daemon mode, single connection otherwise")
flEnableIptables := flag.Bool("iptables", true, "Disable docker's addition of iptables rules")
flDefaultIp := flag.String("ip", "0.0.0.0", "Default IP address to use when binding container ports")
flInterContainerComm := flag.Bool("icc", true, "Enable inter-container communication")
flGraphDriver := flag.String("s", "", "Force the docker runtime to use a specific storage driver")

flag.Parse()

if *flVersion {
showVersion()
return
}
if len(flHosts) > 1 {
flHosts = flHosts[1:] //trick to display a nice default value in the usage
}
for i, flHost := range flHosts {
host, err := utils.ParseHost(docker.DEFAULTHTTPHOST, docker.DEFAULTHTTPPORT, flHost)
if err == nil {
flHosts[i] = host
} else {
log.Fatal(err)
}
if flHosts.Len() == 0 {
// If we do not have a host, default to unix socket
flHosts.Set(fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET))
}

if *flDebug {
Expand Down Expand Up @@ -88,16 +83,16 @@ func main() {
log.Fatal(err)
}
// Serve api
job = eng.Job("serveapi", flHosts...)
job = eng.Job("serveapi", flHosts.GetAll()...)
job.SetenvBool("Logging", true)
if err := job.Run(); err != nil {
log.Fatal(err)
}
} else {
if len(flHosts) > 1 {
if flHosts.Len() > 1 {
log.Fatal("Please specify only one -H")
}
protoAddrParts := strings.SplitN(flHosts[0], "://", 2)
protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2)
if err := docker.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
if sterr, ok := err.(*utils.StatusError); ok {
if sterr.Status != "" {
Expand Down
Loading

0 comments on commit fe571dd

Please sign in to comment.