| ... | ... |
@@ -246,7 +246,7 @@ func (b *buildFile) CmdVolume(args string) error {
|
| 246 | 246 |
volume = []string{args}
|
| 247 | 247 |
} |
| 248 | 248 |
if b.config.Volumes == nil {
|
| 249 |
- b.config.Volumes = PathOpts{}
|
|
| 249 |
+ b.config.Volumes = map[string]struct{}{}
|
|
| 250 | 250 |
} |
| 251 | 251 |
for _, v := range volume {
|
| 252 | 252 |
b.config.Volumes[v] = struct{}{}
|
| ... | ... |
@@ -23,7 +23,6 @@ import ( |
| 23 | 23 |
"os" |
| 24 | 24 |
"os/signal" |
| 25 | 25 |
"path" |
| 26 |
- "path/filepath" |
|
| 27 | 26 |
"reflect" |
| 28 | 27 |
"regexp" |
| 29 | 28 |
"runtime" |
| ... | ... |
@@ -1622,58 +1621,6 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
|
| 1622 | 1622 |
// Ports type - Used to parse multiple -p flags |
| 1623 | 1623 |
type ports []int |
| 1624 | 1624 |
|
| 1625 |
-// AttachOpts stores arguments to 'docker run -a', eg. which streams to attach to |
|
| 1626 |
-type AttachOpts map[string]bool |
|
| 1627 |
- |
|
| 1628 |
-func (opts AttachOpts) String() string { return fmt.Sprintf("%v", map[string]bool(opts)) }
|
|
| 1629 |
-func (opts AttachOpts) Set(val string) error {
|
|
| 1630 |
- if val != "stdin" && val != "stdout" && val != "stderr" {
|
|
| 1631 |
- return fmt.Errorf("Unsupported stream name: %s", val)
|
|
| 1632 |
- } |
|
| 1633 |
- opts[val] = true |
|
| 1634 |
- return nil |
|
| 1635 |
-} |
|
| 1636 |
- |
|
| 1637 |
-// LinkOpts stores arguments to `docker run -link` |
|
| 1638 |
-type LinkOpts []string |
|
| 1639 |
- |
|
| 1640 |
-func (link *LinkOpts) String() string { return fmt.Sprintf("%v", []string(*link)) }
|
|
| 1641 |
-func (link *LinkOpts) Set(val string) error {
|
|
| 1642 |
- if _, err := parseLink(val); err != nil {
|
|
| 1643 |
- return err |
|
| 1644 |
- } |
|
| 1645 |
- *link = append(*link, val) |
|
| 1646 |
- return nil |
|
| 1647 |
-} |
|
| 1648 |
- |
|
| 1649 |
-// PathOpts stores a unique set of absolute paths |
|
| 1650 |
-type PathOpts map[string]struct{}
|
|
| 1651 |
- |
|
| 1652 |
-func (opts PathOpts) String() string { return fmt.Sprintf("%v", map[string]struct{}(opts)) }
|
|
| 1653 |
-func (opts PathOpts) Set(val string) error {
|
|
| 1654 |
- var containerPath string |
|
| 1655 |
- |
|
| 1656 |
- if strings.Count(val, ":") > 2 {
|
|
| 1657 |
- return fmt.Errorf("bad format for volumes: %s", val)
|
|
| 1658 |
- } |
|
| 1659 |
- |
|
| 1660 |
- if splited := strings.SplitN(val, ":", 2); len(splited) == 1 {
|
|
| 1661 |
- containerPath = splited[0] |
|
| 1662 |
- val = filepath.Clean(splited[0]) |
|
| 1663 |
- } else {
|
|
| 1664 |
- containerPath = splited[1] |
|
| 1665 |
- val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1]))
|
|
| 1666 |
- } |
|
| 1667 |
- |
|
| 1668 |
- if !filepath.IsAbs(containerPath) {
|
|
| 1669 |
- utils.Debugf("%s is not an absolute path", containerPath)
|
|
| 1670 |
- return fmt.Errorf("%s is not an absolute path", containerPath)
|
|
| 1671 |
- } |
|
| 1672 |
- opts[val] = struct{}{}
|
|
| 1673 |
- |
|
| 1674 |
- return nil |
|
| 1675 |
-} |
|
| 1676 |
- |
|
| 1677 | 1625 |
func (cli *DockerCli) CmdTag(args ...string) error {
|
| 1678 | 1626 |
cmd := cli.Subcmd("tag", "[OPTIONS] IMAGE REPOSITORY[:TAG]", "Tag an image into a repository")
|
| 1679 | 1627 |
force := cmd.Bool("f", false, "Force")
|
| ... | ... |
@@ -1719,16 +1666,16 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, |
| 1719 | 1719 |
func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Config, *HostConfig, *flag.FlagSet, error) {
|
| 1720 | 1720 |
var ( |
| 1721 | 1721 |
// FIXME: use utils.ListOpts for attach and volumes? |
| 1722 |
- flAttach = AttachOpts{}
|
|
| 1723 |
- flVolumes = PathOpts{}
|
|
| 1724 |
- flLinks = LinkOpts{}
|
|
| 1722 |
+ flAttach = NewListOpts(ValidateAttach) |
|
| 1723 |
+ flVolumes = NewListOpts(ValidatePath) |
|
| 1724 |
+ flLinks = NewListOpts(ValidateLink) |
|
| 1725 |
+ flEnv = NewListOpts(ValidateEnv) |
|
| 1725 | 1726 |
|
| 1726 |
- flPublish utils.ListOpts |
|
| 1727 |
- flExpose utils.ListOpts |
|
| 1728 |
- flEnv utils.ListOpts |
|
| 1729 |
- flDns utils.ListOpts |
|
| 1730 |
- flVolumesFrom utils.ListOpts |
|
| 1731 |
- flLxcOpts utils.ListOpts |
|
| 1727 |
+ flPublish ListOpts |
|
| 1728 |
+ flExpose ListOpts |
|
| 1729 |
+ flDns ListOpts |
|
| 1730 |
+ flVolumesFrom ListOpts |
|
| 1731 |
+ flLxcOpts ListOpts |
|
| 1732 | 1732 |
|
| 1733 | 1733 |
flAutoRemove = cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)")
|
| 1734 | 1734 |
flDetach = cmd.Bool("d", false, "Detached mode: Run container in the background, print new container id")
|
| ... | ... |
@@ -1750,13 +1697,13 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1750 | 1750 |
_ = cmd.String("name", "", "Assign a name to the container")
|
| 1751 | 1751 |
) |
| 1752 | 1752 |
|
| 1753 |
- cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.") |
|
| 1754 |
- cmd.Var(flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)") |
|
| 1753 |
+ cmd.Var(&flAttach, "a", "Attach to stdin, stdout or stderr.") |
|
| 1754 |
+ cmd.Var(&flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)") |
|
| 1755 | 1755 |
cmd.Var(&flLinks, "link", "Add link to another container (name:alias)") |
| 1756 |
+ cmd.Var(&flEnv, "e", "Set environment variables") |
|
| 1756 | 1757 |
|
| 1757 | 1758 |
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))
|
| 1758 | 1759 |
cmd.Var(&flExpose, "expose", "Expose a port from the container without publishing it to your host") |
| 1759 |
- cmd.Var(&flEnv, "e", "Set environment variables") |
|
| 1760 | 1760 |
cmd.Var(&flDns, "dns", "Set custom dns servers") |
| 1761 | 1761 |
cmd.Var(&flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)") |
| 1762 | 1762 |
cmd.Var(&flLxcOpts, "lxc-conf", "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"") |
| ... | ... |
@@ -1771,7 +1718,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1771 | 1771 |
} |
| 1772 | 1772 |
|
| 1773 | 1773 |
// Validate input params |
| 1774 |
- if *flDetach && len(flAttach) > 0 {
|
|
| 1774 |
+ if *flDetach && flAttach.Len() > 0 {
|
|
| 1775 | 1775 |
return nil, nil, cmd, ErrConflictAttachDetach |
| 1776 | 1776 |
} |
| 1777 | 1777 |
if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) {
|
| ... | ... |
@@ -1782,7 +1729,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1782 | 1782 |
} |
| 1783 | 1783 |
|
| 1784 | 1784 |
// If neither -d or -a are set, attach to everything by default |
| 1785 |
- if len(flAttach) == 0 && !*flDetach {
|
|
| 1785 |
+ if flAttach.Len() == 0 && !*flDetach {
|
|
| 1786 | 1786 |
if !*flDetach {
|
| 1787 | 1787 |
flAttach.Set("stdout")
|
| 1788 | 1788 |
flAttach.Set("stderr")
|
| ... | ... |
@@ -1792,17 +1739,6 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1792 | 1792 |
} |
| 1793 | 1793 |
} |
| 1794 | 1794 |
|
| 1795 |
- var envs []string |
|
| 1796 |
- for _, env := range flEnv {
|
|
| 1797 |
- arr := strings.Split(env, "=") |
|
| 1798 |
- if len(arr) > 1 {
|
|
| 1799 |
- envs = append(envs, env) |
|
| 1800 |
- } else {
|
|
| 1801 |
- v := os.Getenv(env) |
|
| 1802 |
- envs = append(envs, env+"="+v) |
|
| 1803 |
- } |
|
| 1804 |
- } |
|
| 1805 |
- |
|
| 1806 | 1795 |
var flMemory int64 |
| 1807 | 1796 |
if *flMemoryString != "" {
|
| 1808 | 1797 |
parsedMemory, err := utils.RAMInBytes(*flMemoryString) |
| ... | ... |
@@ -1814,16 +1750,15 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1814 | 1814 |
|
| 1815 | 1815 |
var binds []string |
| 1816 | 1816 |
// add any bind targets to the list of container volumes |
| 1817 |
- for bind := range flVolumes {
|
|
| 1818 |
- arr := strings.Split(bind, ":") |
|
| 1819 |
- if len(arr) > 1 {
|
|
| 1817 |
+ for bind := range flVolumes.GetMap() {
|
|
| 1818 |
+ if arr := strings.Split(bind, ":"); len(arr) > 1 {
|
|
| 1820 | 1819 |
if arr[0] == "/" {
|
| 1821 | 1820 |
return nil, nil, cmd, fmt.Errorf("Invalid bind mount: source can't be '/'")
|
| 1822 | 1821 |
} |
| 1823 | 1822 |
dstDir := arr[1] |
| 1824 |
- flVolumes[dstDir] = struct{}{}
|
|
| 1823 |
+ flVolumes.Set(dstDir) |
|
| 1825 | 1824 |
binds = append(binds, bind) |
| 1826 |
- delete(flVolumes, bind) |
|
| 1825 |
+ flVolumes.Delete(bind) |
|
| 1827 | 1826 |
} |
| 1828 | 1827 |
} |
| 1829 | 1828 |
|
| ... | ... |
@@ -1858,13 +1793,13 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1858 | 1858 |
domainname = parts[1] |
| 1859 | 1859 |
} |
| 1860 | 1860 |
|
| 1861 |
- ports, portBindings, err := parsePortSpecs(flPublish) |
|
| 1861 |
+ ports, portBindings, err := parsePortSpecs(flPublish.GetAll()) |
|
| 1862 | 1862 |
if err != nil {
|
| 1863 | 1863 |
return nil, nil, cmd, err |
| 1864 | 1864 |
} |
| 1865 | 1865 |
|
| 1866 | 1866 |
// Merge in exposed ports to the map of published ports |
| 1867 |
- for _, e := range flExpose {
|
|
| 1867 |
+ for _, e := range flExpose.GetAll() {
|
|
| 1868 | 1868 |
if strings.Contains(e, ":") {
|
| 1869 | 1869 |
return nil, nil, cmd, fmt.Errorf("Invalid port format for -expose: %s", e)
|
| 1870 | 1870 |
} |
| ... | ... |
@@ -1885,15 +1820,15 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1885 | 1885 |
OpenStdin: *flStdin, |
| 1886 | 1886 |
Memory: flMemory, |
| 1887 | 1887 |
CpuShares: *flCpuShares, |
| 1888 |
- AttachStdin: flAttach["stdin"], |
|
| 1889 |
- AttachStdout: flAttach["stdout"], |
|
| 1890 |
- AttachStderr: flAttach["stderr"], |
|
| 1891 |
- Env: envs, |
|
| 1888 |
+ AttachStdin: flAttach.Get("stdin"),
|
|
| 1889 |
+ AttachStdout: flAttach.Get("stdout"),
|
|
| 1890 |
+ AttachStderr: flAttach.Get("stderr"),
|
|
| 1891 |
+ Env: flEnv.GetAll(), |
|
| 1892 | 1892 |
Cmd: runCmd, |
| 1893 |
- Dns: flDns, |
|
| 1893 |
+ Dns: flDns.GetAll(), |
|
| 1894 | 1894 |
Image: image, |
| 1895 |
- Volumes: flVolumes, |
|
| 1896 |
- VolumesFrom: strings.Join(flVolumesFrom, ","), |
|
| 1895 |
+ Volumes: flVolumes.GetMap(), |
|
| 1896 |
+ VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","), |
|
| 1897 | 1897 |
Entrypoint: entrypoint, |
| 1898 | 1898 |
WorkingDir: *flWorkingDir, |
| 1899 | 1899 |
} |
| ... | ... |
@@ -1904,7 +1839,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1904 | 1904 |
LxcConf: lxcConf, |
| 1905 | 1905 |
Privileged: *flPrivileged, |
| 1906 | 1906 |
PortBindings: portBindings, |
| 1907 |
- Links: flLinks, |
|
| 1907 |
+ Links: flLinks.GetAll(), |
|
| 1908 | 1908 |
PublishAllPorts: *flPublishAll, |
| 1909 | 1909 |
} |
| 1910 | 1910 |
|
| ... | ... |
@@ -23,22 +23,24 @@ func main() {
|
| 23 | 23 |
sysinit.SysInit() |
| 24 | 24 |
return |
| 25 | 25 |
} |
| 26 |
- // FIXME: Switch d and D ? (to be more sshd like) |
|
| 27 |
- flVersion := flag.Bool("v", false, "Print version information and quit")
|
|
| 28 |
- flDaemon := flag.Bool("d", false, "Enable daemon mode")
|
|
| 29 |
- flDebug := flag.Bool("D", false, "Enable debug mode")
|
|
| 30 |
- flAutoRestart := flag.Bool("r", true, "Restart previously running containers")
|
|
| 31 |
- bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
|
|
| 32 |
- pidfile := flag.String("p", "/var/run/docker.pid", "Path to use for daemon PID file")
|
|
| 33 |
- flRoot := flag.String("g", "/var/lib/docker", "Path to use as the root of the docker runtime")
|
|
| 34 |
- flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS headers in the remote API")
|
|
| 35 |
- flDns := flag.String("dns", "", "Force docker to use specific DNS servers")
|
|
| 36 |
- flHosts := utils.ListOpts{fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)}
|
|
| 26 |
+ |
|
| 27 |
+ var ( |
|
| 28 |
+ flVersion = flag.Bool("v", false, "Print version information and quit")
|
|
| 29 |
+ flDaemon = flag.Bool("d", false, "Enable daemon mode")
|
|
| 30 |
+ flDebug = flag.Bool("D", false, "Enable debug mode")
|
|
| 31 |
+ flAutoRestart = flag.Bool("r", true, "Restart previously running containers")
|
|
| 32 |
+ bridgeName = flag.String("b", "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
|
|
| 33 |
+ pidfile = flag.String("p", "/var/run/docker.pid", "Path to use for daemon PID file")
|
|
| 34 |
+ flRoot = flag.String("g", "/var/lib/docker", "Path to use as the root of the docker runtime")
|
|
| 35 |
+ flEnableCors = flag.Bool("api-enable-cors", false, "Enable CORS headers in the remote API")
|
|
| 36 |
+ flDns = flag.String("dns", "", "Force docker to use specific DNS servers")
|
|
| 37 |
+ flEnableIptables = flag.Bool("iptables", true, "Disable docker's addition of iptables rules")
|
|
| 38 |
+ flDefaultIp = flag.String("ip", "0.0.0.0", "Default IP address to use when binding container ports")
|
|
| 39 |
+ flInterContainerComm = flag.Bool("icc", true, "Enable inter-container communication")
|
|
| 40 |
+ flGraphDriver = flag.String("s", "", "Force the docker runtime to use a specific storage driver")
|
|
| 41 |
+ flHosts = docker.NewListOpts(docker.ValidateHost) |
|
| 42 |
+ ) |
|
| 37 | 43 |
flag.Var(&flHosts, "H", "Multiple tcp://host:port or unix://path/to/socket to bind in daemon mode, single connection otherwise") |
| 38 |
- flEnableIptables := flag.Bool("iptables", true, "Disable docker's addition of iptables rules")
|
|
| 39 |
- flDefaultIp := flag.String("ip", "0.0.0.0", "Default IP address to use when binding container ports")
|
|
| 40 |
- flInterContainerComm := flag.Bool("icc", true, "Enable inter-container communication")
|
|
| 41 |
- flGraphDriver := flag.String("s", "", "Force the docker runtime to use a specific storage driver")
|
|
| 42 | 44 |
|
| 43 | 45 |
flag.Parse() |
| 44 | 46 |
|
| ... | ... |
@@ -46,16 +48,9 @@ func main() {
|
| 46 | 46 |
showVersion() |
| 47 | 47 |
return |
| 48 | 48 |
} |
| 49 |
- if len(flHosts) > 1 {
|
|
| 50 |
- flHosts = flHosts[1:] //trick to display a nice default value in the usage |
|
| 51 |
- } |
|
| 52 |
- for i, flHost := range flHosts {
|
|
| 53 |
- host, err := utils.ParseHost(docker.DEFAULTHTTPHOST, docker.DEFAULTHTTPPORT, flHost) |
|
| 54 |
- if err == nil {
|
|
| 55 |
- flHosts[i] = host |
|
| 56 |
- } else {
|
|
| 57 |
- log.Fatal(err) |
|
| 58 |
- } |
|
| 49 |
+ if flHosts.Len() == 0 {
|
|
| 50 |
+ // If we do not have a host, default to unix socket |
|
| 51 |
+ flHosts.Set(fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET))
|
|
| 59 | 52 |
} |
| 60 | 53 |
|
| 61 | 54 |
if *flDebug {
|
| ... | ... |
@@ -88,16 +83,16 @@ func main() {
|
| 88 | 88 |
log.Fatal(err) |
| 89 | 89 |
} |
| 90 | 90 |
// Serve api |
| 91 |
- job = eng.Job("serveapi", flHosts...)
|
|
| 91 |
+ job = eng.Job("serveapi", flHosts.GetAll()...)
|
|
| 92 | 92 |
job.SetenvBool("Logging", true)
|
| 93 | 93 |
if err := job.Run(); err != nil {
|
| 94 | 94 |
log.Fatal(err) |
| 95 | 95 |
} |
| 96 | 96 |
} else {
|
| 97 |
- if len(flHosts) > 1 {
|
|
| 97 |
+ if flHosts.Len() > 1 {
|
|
| 98 | 98 |
log.Fatal("Please specify only one -H")
|
| 99 | 99 |
} |
| 100 |
- protoAddrParts := strings.SplitN(flHosts[0], "://", 2) |
|
| 100 |
+ protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2) |
|
| 101 | 101 |
if err := docker.ParseCommands(protoAddrParts[0], protoAddrParts[1], flag.Args()...); err != nil {
|
| 102 | 102 |
if sterr, ok := err.(*utils.StatusError); ok {
|
| 103 | 103 |
if sterr.Status != "" {
|
| 104 | 104 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,136 @@ |
| 0 |
+package docker |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "github.com/dotcloud/docker/utils" |
|
| 5 |
+ "os" |
|
| 6 |
+ "path/filepath" |
|
| 7 |
+ "strings" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// ListOpts type |
|
| 11 |
+type ListOpts struct {
|
|
| 12 |
+ values []string |
|
| 13 |
+ validator ValidatorFctType |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 16 |
+func NewListOpts(validator ValidatorFctType) ListOpts {
|
|
| 17 |
+ return ListOpts{
|
|
| 18 |
+ validator: validator, |
|
| 19 |
+ } |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+func (opts *ListOpts) String() string {
|
|
| 23 |
+ return fmt.Sprintf("%v", []string(opts.values))
|
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+// Set validates if needed the input value and add it to the |
|
| 27 |
+// internal slice. |
|
| 28 |
+func (opts *ListOpts) Set(value string) error {
|
|
| 29 |
+ if opts.validator != nil {
|
|
| 30 |
+ v, err := opts.validator(value) |
|
| 31 |
+ if err != nil {
|
|
| 32 |
+ return err |
|
| 33 |
+ } |
|
| 34 |
+ value = v |
|
| 35 |
+ } |
|
| 36 |
+ opts.values = append(opts.values, value) |
|
| 37 |
+ return nil |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 40 |
+// Delete remove the given element from the slice. |
|
| 41 |
+func (opts *ListOpts) Delete(key string) {
|
|
| 42 |
+ for i, k := range opts.values {
|
|
| 43 |
+ if k == key {
|
|
| 44 |
+ opts.values = append(opts.values[:i], opts.values[i+1:]...) |
|
| 45 |
+ return |
|
| 46 |
+ } |
|
| 47 |
+ } |
|
| 48 |
+} |
|
| 49 |
+ |
|
| 50 |
+// GetMap returns the content of values in a map in order to avoid |
|
| 51 |
+// duplicates. |
|
| 52 |
+// FIXME: can we remove this? |
|
| 53 |
+func (opts *ListOpts) GetMap() map[string]struct{} {
|
|
| 54 |
+ ret := make(map[string]struct{})
|
|
| 55 |
+ for _, k := range opts.values {
|
|
| 56 |
+ ret[k] = struct{}{}
|
|
| 57 |
+ } |
|
| 58 |
+ return ret |
|
| 59 |
+} |
|
| 60 |
+ |
|
| 61 |
+// GetAll returns the values' slice. |
|
| 62 |
+// FIXME: Can we remove this? |
|
| 63 |
+func (opts *ListOpts) GetAll() []string {
|
|
| 64 |
+ return opts.values |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+// Get checks the existence of the given key. |
|
| 68 |
+func (opts *ListOpts) Get(key string) bool {
|
|
| 69 |
+ for _, k := range opts.values {
|
|
| 70 |
+ if k == key {
|
|
| 71 |
+ return true |
|
| 72 |
+ } |
|
| 73 |
+ } |
|
| 74 |
+ return false |
|
| 75 |
+} |
|
| 76 |
+ |
|
| 77 |
+// Len returns the amount of element in the slice. |
|
| 78 |
+func (opts *ListOpts) Len() int {
|
|
| 79 |
+ return len(opts.values) |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+// Validators |
|
| 83 |
+type ValidatorFctType func(val string) (string, error) |
|
| 84 |
+ |
|
| 85 |
+func ValidateAttach(val string) (string, error) {
|
|
| 86 |
+ if val != "stdin" && val != "stdout" && val != "stderr" {
|
|
| 87 |
+ return val, fmt.Errorf("Unsupported stream name: %s", val)
|
|
| 88 |
+ } |
|
| 89 |
+ return val, nil |
|
| 90 |
+} |
|
| 91 |
+ |
|
| 92 |
+func ValidateLink(val string) (string, error) {
|
|
| 93 |
+ if _, err := parseLink(val); err != nil {
|
|
| 94 |
+ return val, err |
|
| 95 |
+ } |
|
| 96 |
+ return val, nil |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+func ValidatePath(val string) (string, error) {
|
|
| 100 |
+ var containerPath string |
|
| 101 |
+ |
|
| 102 |
+ if strings.Count(val, ":") > 2 {
|
|
| 103 |
+ return val, fmt.Errorf("bad format for volumes: %s", val)
|
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ splited := strings.SplitN(val, ":", 2) |
|
| 107 |
+ if len(splited) == 1 {
|
|
| 108 |
+ containerPath = splited[0] |
|
| 109 |
+ val = filepath.Clean(splited[0]) |
|
| 110 |
+ } else {
|
|
| 111 |
+ containerPath = splited[1] |
|
| 112 |
+ val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1]))
|
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ if !filepath.IsAbs(containerPath) {
|
|
| 116 |
+ return val, fmt.Errorf("%s is not an absolute path", containerPath)
|
|
| 117 |
+ } |
|
| 118 |
+ return val, nil |
|
| 119 |
+} |
|
| 120 |
+ |
|
| 121 |
+func ValidateEnv(val string) (string, error) {
|
|
| 122 |
+ arr := strings.Split(val, "=") |
|
| 123 |
+ if len(arr) > 1 {
|
|
| 124 |
+ return val, nil |
|
| 125 |
+ } |
|
| 126 |
+ return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil
|
|
| 127 |
+} |
|
| 128 |
+ |
|
| 129 |
+func ValidateHost(val string) (string, error) {
|
|
| 130 |
+ host, err := utils.ParseHost(DEFAULTHTTPHOST, DEFAULTHTTPPORT, val) |
|
| 131 |
+ if err != nil {
|
|
| 132 |
+ return val, err |
|
| 133 |
+ } |
|
| 134 |
+ return host, nil |
|
| 135 |
+} |
| ... | ... |
@@ -215,9 +215,9 @@ func MergeConfig(userConf, imageConf *Config) error {
|
| 215 | 215 |
return nil |
| 216 | 216 |
} |
| 217 | 217 |
|
| 218 |
-func parseLxcConfOpts(opts utils.ListOpts) ([]KeyValuePair, error) {
|
|
| 219 |
- out := make([]KeyValuePair, len(opts)) |
|
| 220 |
- for i, o := range opts {
|
|
| 218 |
+func parseLxcConfOpts(opts ListOpts) ([]KeyValuePair, error) {
|
|
| 219 |
+ out := make([]KeyValuePair, opts.Len()) |
|
| 220 |
+ for i, o := range opts.GetAll() {
|
|
| 221 | 221 |
k, v, err := parseLxcOpt(o) |
| 222 | 222 |
if err != nil {
|
| 223 | 223 |
return nil, err |
| ... | ... |
@@ -34,18 +34,6 @@ type Fataler interface {
|
| 34 | 34 |
Fatal(args ...interface{})
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 |
-// ListOpts type |
|
| 38 |
-type ListOpts []string |
|
| 39 |
- |
|
| 40 |
-func (opts *ListOpts) String() string {
|
|
| 41 |
- return fmt.Sprint(*opts) |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-func (opts *ListOpts) Set(value string) error {
|
|
| 45 |
- *opts = append(*opts, value) |
|
| 46 |
- return nil |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 | 37 |
// Go is a basic promise implementation: it wraps calls a function in a goroutine, |
| 50 | 38 |
// and returns a channel which will later return the function's return value. |
| 51 | 39 |
func Go(f func() error) chan error {
|