瀏覽代碼

Updating CallFunc to match the Docker CLI API changes

Updated Docker deps to pickup UI changes

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 10 年之前
父節點
當前提交
678d50f5b5
共有 56 個文件被更改,包括 4368 次插入51 次删除
  1. 23 18
      libnetwork/Godeps/Godeps.json
  2. 83 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/attach.go
  3. 310 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/build.go
  4. 203 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/cli.go
  5. 17 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/client.go
  6. 80 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/commit.go
  7. 57 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/cp.go
  8. 160 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/create.go
  9. 52 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/diff.go
  10. 62 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/events.go
  11. 131 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/exec.go
  12. 46 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/export.go
  13. 34 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/help.go
  14. 257 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/hijack.go
  15. 73 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/history.go
  16. 126 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/images.go
  17. 64 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/import.go
  18. 91 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/info.go
  19. 124 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/inspect.go
  20. 32 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/kill.go
  21. 41 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/load.go
  22. 144 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/login.go
  23. 36 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/logout.go
  24. 69 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/logs.go
  25. 30 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/pause.go
  26. 64 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/port.go
  27. 175 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/ps.go
  28. 47 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/pull.go
  29. 49 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/push.go
  30. 25 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/rename.go
  31. 38 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/restart.go
  32. 54 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/rm.go
  33. 59 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/rmi.go
  34. 247 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/run.go
  35. 57 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/save.go
  36. 84 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/search.go
  37. 167 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/start.go
  38. 198 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/stats.go
  39. 29 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/stats_unit_test.go
  40. 40 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/stop.go
  41. 41 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/tag.go
  42. 46 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/top.go
  43. 30 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/unpause.go
  44. 345 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/utils.go
  45. 61 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/version.go
  46. 34 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/wait.go
  47. 14 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/ioutils/fmt.go
  48. 17 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/ioutils/fmt_test.go
  49. 1 2
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/ioutils/readers_test.go
  50. 22 7
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/flag.go
  51. 18 5
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/plugins/client.go
  52. 43 1
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/plugins/client_test.go
  53. 1 5
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/plugins/discovery_test.go
  54. 3 2
      libnetwork/client/client.go
  55. 7 4
      libnetwork/client/client_test.go
  56. 7 7
      libnetwork/cmd/dnet/dnet.go

+ 23 - 18
libnetwork/Godeps/Godeps.json

@@ -27,48 +27,53 @@
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/homedir",
 			"ImportPath": "github.com/docker/docker/pkg/homedir",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/ioutils",
 			"ImportPath": "github.com/docker/docker/pkg/ioutils",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/mflag",
 			"ImportPath": "github.com/docker/docker/pkg/mflag",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/parsers",
 			"ImportPath": "github.com/docker/docker/pkg/parsers",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/plugins",
 			"ImportPath": "github.com/docker/docker/pkg/plugins",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/proxy",
 			"ImportPath": "github.com/docker/docker/pkg/proxy",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/reexec",
 			"ImportPath": "github.com/docker/docker/pkg/reexec",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/stringid",
 			"ImportPath": "github.com/docker/docker/pkg/stringid",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/term",
 			"ImportPath": "github.com/docker/docker/pkg/term",
-			"Comment": "v1.4.1-3479-ga9172f5",
-			"Rev": "a9172f572e13086859c652e2d581950e910d63d4"
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
+		},
+		{
+			"ImportPath": "github.com/docker/docker/api/client",
+			"Comment": "v1.4.1-4106-g637023a",
+			"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/docker/libcontainer/user",
 			"ImportPath": "github.com/docker/libcontainer/user",

+ 83 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/attach.go

@@ -0,0 +1,83 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/url"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/signal"
+)
+
+// CmdAttach attaches to a running container.
+//
+// Usage: docker attach [OPTIONS] CONTAINER
+func (cli *DockerCli) CmdAttach(args ...string) error {
+	var (
+		cmd     = cli.Subcmd("attach", "CONTAINER", "Attach to a running container", true)
+		noStdin = cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach STDIN")
+		proxy   = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy all received signals to the process")
+	)
+	cmd.Require(flag.Exact, 1)
+
+	cmd.ParseFlags(args, true)
+	name := cmd.Arg(0)
+
+	stream, _, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	var c types.ContainerJSON
+	if err := json.NewDecoder(stream).Decode(&c); err != nil {
+		return err
+	}
+
+	if !c.State.Running {
+		return fmt.Errorf("You cannot attach to a stopped container, start it first")
+	}
+
+	if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil {
+		return err
+	}
+
+	if c.Config.Tty && cli.isTerminalOut {
+		if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
+			logrus.Debugf("Error monitoring TTY size: %s", err)
+		}
+	}
+
+	var in io.ReadCloser
+
+	v := url.Values{}
+	v.Set("stream", "1")
+	if !*noStdin && c.Config.OpenStdin {
+		v.Set("stdin", "1")
+		in = cli.in
+	}
+
+	v.Set("stdout", "1")
+	v.Set("stderr", "1")
+
+	if *proxy && !c.Config.Tty {
+		sigc := cli.forwardAllSignals(cmd.Arg(0))
+		defer signal.StopCatch(sigc)
+	}
+
+	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), c.Config.Tty, in, cli.out, cli.err, nil, nil); err != nil {
+		return err
+	}
+
+	_, status, err := getExitCode(cli, cmd.Arg(0))
+	if err != nil {
+		return err
+	}
+	if status != 0 {
+		return StatusError{StatusCode: status}
+	}
+
+	return nil
+}

+ 310 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/build.go

@@ -0,0 +1,310 @@
+package client
+
+import (
+	"bufio"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"strings"
+
+	"github.com/docker/docker/api"
+	"github.com/docker/docker/graph/tags"
+	"github.com/docker/docker/pkg/archive"
+	"github.com/docker/docker/pkg/fileutils"
+	"github.com/docker/docker/pkg/jsonmessage"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/pkg/progressreader"
+	"github.com/docker/docker/pkg/streamformatter"
+	"github.com/docker/docker/pkg/symlink"
+	"github.com/docker/docker/pkg/units"
+	"github.com/docker/docker/pkg/urlutil"
+	"github.com/docker/docker/registry"
+	"github.com/docker/docker/utils"
+)
+
+const (
+	tarHeaderSize = 512
+)
+
+// CmdBuild builds a new image from the source code at a given path.
+//
+// If '-' is provided instead of a path or URL, Docker will build an image from either a Dockerfile or tar archive read from STDIN.
+//
+// Usage: docker build [OPTIONS] PATH | URL | -
+func (cli *DockerCli) CmdBuild(args ...string) error {
+	cmd := cli.Subcmd("build", "PATH | URL | -", "Build a new image from the source code at PATH", true)
+	tag := cmd.String([]string{"t", "-tag"}, "", "Repository name (and optionally a tag) for the image")
+	suppressOutput := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress the verbose output generated by the containers")
+	noCache := cmd.Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
+	rm := cmd.Bool([]string{"#rm", "-rm"}, true, "Remove intermediate containers after a successful build")
+	forceRm := cmd.Bool([]string{"-force-rm"}, false, "Always remove intermediate containers")
+	pull := cmd.Bool([]string{"-pull"}, false, "Always attempt to pull a newer version of the image")
+	dockerfileName := cmd.String([]string{"f", "-file"}, "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
+	flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit")
+	flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
+	flCPUShares := cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
+	flCpuPeriod := cmd.Int64([]string{"-cpu-period"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
+	flCpuQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
+	flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
+	flCPUSetMems := cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
+	flCgroupParent := cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
+
+	cmd.Require(flag.Exact, 1)
+	cmd.ParseFlags(args, true)
+
+	var (
+		context  archive.Archive
+		isRemote bool
+		err      error
+	)
+
+	_, err = exec.LookPath("git")
+	hasGit := err == nil
+	if cmd.Arg(0) == "-" {
+		// As a special case, 'docker build -' will build from either an empty context with the
+		// contents of stdin as a Dockerfile, or a tar-ed context from stdin.
+		buf := bufio.NewReader(cli.in)
+		magic, err := buf.Peek(tarHeaderSize)
+		if err != nil && err != io.EOF {
+			return fmt.Errorf("failed to peek context header from STDIN: %v", err)
+		}
+		if !archive.IsArchive(magic) {
+			dockerfile, err := ioutil.ReadAll(buf)
+			if err != nil {
+				return fmt.Errorf("failed to read Dockerfile from STDIN: %v", err)
+			}
+
+			// -f option has no meaning when we're reading it from stdin,
+			// so just use our default Dockerfile name
+			*dockerfileName = api.DefaultDockerfileName
+			context, err = archive.Generate(*dockerfileName, string(dockerfile))
+		} else {
+			context = ioutil.NopCloser(buf)
+		}
+	} else if urlutil.IsURL(cmd.Arg(0)) && (!urlutil.IsGitURL(cmd.Arg(0)) || !hasGit) {
+		isRemote = true
+	} else {
+		root := cmd.Arg(0)
+		if urlutil.IsGitURL(root) {
+			root, err = utils.GitClone(root)
+			if err != nil {
+				return err
+			}
+			defer os.RemoveAll(root)
+		}
+		if _, err := os.Stat(root); err != nil {
+			return err
+		}
+
+		absRoot, err := filepath.Abs(root)
+		if err != nil {
+			return err
+		}
+
+		filename := *dockerfileName // path to Dockerfile
+
+		if *dockerfileName == "" {
+			// No -f/--file was specified so use the default
+			*dockerfileName = api.DefaultDockerfileName
+			filename = filepath.Join(absRoot, *dockerfileName)
+
+			// Just to be nice ;-) look for 'dockerfile' too but only
+			// use it if we found it, otherwise ignore this check
+			if _, err = os.Lstat(filename); os.IsNotExist(err) {
+				tmpFN := path.Join(absRoot, strings.ToLower(*dockerfileName))
+				if _, err = os.Lstat(tmpFN); err == nil {
+					*dockerfileName = strings.ToLower(*dockerfileName)
+					filename = tmpFN
+				}
+			}
+		}
+
+		origDockerfile := *dockerfileName // used for error msg
+		if filename, err = filepath.Abs(filename); err != nil {
+			return err
+		}
+
+		// Verify that 'filename' is within the build context
+		filename, err = symlink.FollowSymlinkInScope(filename, absRoot)
+		if err != nil {
+			return fmt.Errorf("The Dockerfile (%s) must be within the build context (%s)", origDockerfile, root)
+		}
+
+		// Now reset the dockerfileName to be relative to the build context
+		*dockerfileName, err = filepath.Rel(absRoot, filename)
+		if err != nil {
+			return err
+		}
+		// And canonicalize dockerfile name to a platform-independent one
+		*dockerfileName, err = archive.CanonicalTarNameForPath(*dockerfileName)
+		if err != nil {
+			return fmt.Errorf("Cannot canonicalize dockerfile path %s: %v", *dockerfileName, err)
+		}
+
+		if _, err = os.Lstat(filename); os.IsNotExist(err) {
+			return fmt.Errorf("Cannot locate Dockerfile: %s", origDockerfile)
+		}
+		var includes = []string{"."}
+
+		excludes, err := utils.ReadDockerIgnore(path.Join(root, ".dockerignore"))
+		if err != nil {
+			return err
+		}
+
+		// If .dockerignore mentions .dockerignore or the Dockerfile
+		// then make sure we send both files over to the daemon
+		// because Dockerfile is, obviously, needed no matter what, and
+		// .dockerignore is needed to know if either one needs to be
+		// removed.  The deamon will remove them for us, if needed, after it
+		// parses the Dockerfile.
+		keepThem1, _ := fileutils.Matches(".dockerignore", excludes)
+		keepThem2, _ := fileutils.Matches(*dockerfileName, excludes)
+		if keepThem1 || keepThem2 {
+			includes = append(includes, ".dockerignore", *dockerfileName)
+		}
+
+		if err := utils.ValidateContextDirectory(root, excludes); err != nil {
+			return fmt.Errorf("Error checking context: '%s'.", err)
+		}
+		options := &archive.TarOptions{
+			Compression:     archive.Uncompressed,
+			ExcludePatterns: excludes,
+			IncludeFiles:    includes,
+		}
+		context, err = archive.TarWithOptions(root, options)
+		if err != nil {
+			return err
+		}
+	}
+
+	// windows: show error message about modified file permissions
+	// FIXME: this is not a valid warning when the daemon is running windows. should be removed once docker engine for windows can build.
+	if runtime.GOOS == "windows" {
+		fmt.Fprintln(cli.err, `SECURITY WARNING: You are building a Docker image from Windows against a Linux Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.`)
+	}
+
+	var body io.Reader
+	// Setup an upload progress bar
+	// FIXME: ProgressReader shouldn't be this annoying to use
+	if context != nil {
+		sf := streamformatter.NewStreamFormatter()
+		body = progressreader.New(progressreader.Config{
+			In:        context,
+			Out:       cli.out,
+			Formatter: sf,
+			NewLines:  true,
+			ID:        "",
+			Action:    "Sending build context to Docker daemon",
+		})
+	}
+
+	var memory int64
+	if *flMemoryString != "" {
+		parsedMemory, err := units.RAMInBytes(*flMemoryString)
+		if err != nil {
+			return err
+		}
+		memory = parsedMemory
+	}
+
+	var memorySwap int64
+	if *flMemorySwap != "" {
+		if *flMemorySwap == "-1" {
+			memorySwap = -1
+		} else {
+			parsedMemorySwap, err := units.RAMInBytes(*flMemorySwap)
+			if err != nil {
+				return err
+			}
+			memorySwap = parsedMemorySwap
+		}
+	}
+	// Send the build context
+	v := &url.Values{}
+
+	//Check if the given image name can be resolved
+	if *tag != "" {
+		repository, tag := parsers.ParseRepositoryTag(*tag)
+		if err := registry.ValidateRepositoryName(repository); err != nil {
+			return err
+		}
+		if len(tag) > 0 {
+			if err := tags.ValidateTagName(tag); err != nil {
+				return err
+			}
+		}
+	}
+
+	v.Set("t", *tag)
+
+	if *suppressOutput {
+		v.Set("q", "1")
+	}
+	if isRemote {
+		v.Set("remote", cmd.Arg(0))
+	}
+	if *noCache {
+		v.Set("nocache", "1")
+	}
+	if *rm {
+		v.Set("rm", "1")
+	} else {
+		v.Set("rm", "0")
+	}
+
+	if *forceRm {
+		v.Set("forcerm", "1")
+	}
+
+	if *pull {
+		v.Set("pull", "1")
+	}
+
+	v.Set("cpusetcpus", *flCPUSetCpus)
+	v.Set("cpusetmems", *flCPUSetMems)
+	v.Set("cpushares", strconv.FormatInt(*flCPUShares, 10))
+	v.Set("cpuquota", strconv.FormatInt(*flCpuQuota, 10))
+	v.Set("cpuperiod", strconv.FormatInt(*flCpuPeriod, 10))
+	v.Set("memory", strconv.FormatInt(memory, 10))
+	v.Set("memswap", strconv.FormatInt(memorySwap, 10))
+	v.Set("cgroupparent", *flCgroupParent)
+
+	v.Set("dockerfile", *dockerfileName)
+
+	headers := http.Header(make(map[string][]string))
+	buf, err := json.Marshal(cli.configFile.AuthConfigs)
+	if err != nil {
+		return err
+	}
+	headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
+
+	if context != nil {
+		headers.Set("Content-Type", "application/tar")
+	}
+	sopts := &streamOpts{
+		rawTerminal: true,
+		in:          body,
+		out:         cli.out,
+		headers:     headers,
+	}
+	err = cli.stream("POST", fmt.Sprintf("/build?%s", v.Encode()), sopts)
+	if jerr, ok := err.(*jsonmessage.JSONError); ok {
+		// If no error code is set, default to 1
+		if jerr.Code == 0 {
+			jerr.Code = 1
+		}
+		return StatusError{Status: jerr.Message, StatusCode: jerr.Code}
+	}
+	return err
+}

+ 203 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/cli.go

@@ -0,0 +1,203 @@
+package client
+
+import (
+	"crypto/tls"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"path/filepath"
+	"reflect"
+	"strings"
+	"text/template"
+
+	"github.com/docker/docker/cliconfig"
+	"github.com/docker/docker/pkg/homedir"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/term"
+	"github.com/docker/docker/utils"
+)
+
+// DockerCli represents the docker command line client.
+// Instances of the client can be returned from NewDockerCli.
+type DockerCli struct {
+	// proto holds the client protocol i.e. unix.
+	proto string
+	// addr holds the client address.
+	addr string
+
+	// configFile has the client configuration file
+	configFile *cliconfig.ConfigFile
+	// in holds the input stream and closer (io.ReadCloser) for the client.
+	in io.ReadCloser
+	// out holds the output stream (io.Writer) for the client.
+	out io.Writer
+	// err holds the error stream (io.Writer) for the client.
+	err io.Writer
+	// keyFile holds the key file as a string.
+	keyFile string
+	// tlsConfig holds the TLS configuration for the client, and will
+	// set the scheme to https in NewDockerCli if present.
+	tlsConfig *tls.Config
+	// scheme holds the scheme of the client i.e. https.
+	scheme string
+	// inFd holds the file descriptor of the client's STDIN (if valid).
+	inFd uintptr
+	// outFd holds file descriptor of the client's STDOUT (if valid).
+	outFd uintptr
+	// isTerminalIn indicates whether the client's STDIN is a TTY
+	isTerminalIn bool
+	// isTerminalOut dindicates whether the client's STDOUT is a TTY
+	isTerminalOut bool
+	// transport holds the client transport instance.
+	transport *http.Transport
+}
+
+var funcMap = template.FuncMap{
+	"json": func(v interface{}) string {
+		a, _ := json.Marshal(v)
+		return string(a)
+	},
+}
+
+func (cli *DockerCli) Out() io.Writer {
+	return cli.out
+}
+
+func (cli *DockerCli) Err() io.Writer {
+	return cli.err
+}
+
+func (cli *DockerCli) getMethod(args ...string) (func(...string) error, bool) {
+	camelArgs := make([]string, len(args))
+	for i, s := range args {
+		if len(s) == 0 {
+			return nil, false
+		}
+		camelArgs[i] = strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
+	}
+	methodName := "Cmd" + strings.Join(camelArgs, "")
+	method := reflect.ValueOf(cli).MethodByName(methodName)
+	if !method.IsValid() {
+		return nil, false
+	}
+	return method.Interface().(func(...string) error), true
+}
+
+// Cmd executes the specified command.
+func (cli *DockerCli) Cmd(args ...string) error {
+	if len(args) > 1 {
+		method, exists := cli.getMethod(args[:2]...)
+		if exists {
+			return method(args[2:]...)
+		}
+	}
+	if len(args) > 0 {
+		method, exists := cli.getMethod(args[0])
+		if !exists {
+			return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'.", args[0])
+		}
+		return method(args[1:]...)
+	}
+	return cli.CmdHelp()
+}
+
+// Subcmd is a subcommand of the main "docker" command.
+// A subcommand represents an action that can be performed
+// from the Docker command line client.
+//
+// To see all available subcommands, run "docker --help".
+func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bool) *flag.FlagSet {
+	var errorHandling flag.ErrorHandling
+	if exitOnError {
+		errorHandling = flag.ExitOnError
+	} else {
+		errorHandling = flag.ContinueOnError
+	}
+	flags := flag.NewFlagSet(name, errorHandling)
+	if signature != "" {
+		signature = " " + signature
+	}
+	flags.Usage = func() {
+		flags.ShortUsage()
+		flags.PrintDefaults()
+	}
+	flags.ShortUsage = func() {
+		options := ""
+		if flags.FlagCountUndeprecated() > 0 {
+			options = " [OPTIONS]"
+		}
+		fmt.Fprintf(flags.Out(), "\nUsage: docker %s%s%s\n\n%s\n", name, options, signature, description)
+	}
+	return flags
+}
+
+// CheckTtyInput checks if we are trying to attach to a container tty
+// from a non-tty client input stream, and if so, returns an error.
+func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
+	// In order to attach to a container tty, input stream for the client must
+	// be a tty itself: redirecting or piping the client standard input is
+	// incompatible with `docker run -t`, `docker exec -t` or `docker attach`.
+	if ttyMode && attachStdin && !cli.isTerminalIn {
+		return errors.New("cannot enable tty mode on non tty input")
+	}
+	return nil
+}
+
+// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err.
+// The key file, protocol (i.e. unix) and address are passed in as strings, along with the tls.Config. If the tls.Config
+// is set the client scheme will be set to https.
+// The client will be given a 32-second timeout (see https://github.com/docker/docker/pull/8035).
+func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, addr string, tlsConfig *tls.Config) *DockerCli {
+	var (
+		inFd          uintptr
+		outFd         uintptr
+		isTerminalIn  = false
+		isTerminalOut = false
+		scheme        = "http"
+	)
+
+	if tlsConfig != nil {
+		scheme = "https"
+	}
+	if in != nil {
+		inFd, isTerminalIn = term.GetFdInfo(in)
+	}
+
+	if out != nil {
+		outFd, isTerminalOut = term.GetFdInfo(out)
+	}
+
+	if err == nil {
+		err = out
+	}
+
+	// The transport is created here for reuse during the client session.
+	tr := &http.Transport{
+		TLSClientConfig: tlsConfig,
+	}
+	utils.ConfigureTCPTransport(tr, proto, addr)
+
+	configFile, e := cliconfig.Load(filepath.Join(homedir.Get(), ".docker"))
+	if e != nil {
+		fmt.Fprintf(err, "WARNING: Error loading config file:%v\n", e)
+	}
+
+	return &DockerCli{
+		proto:         proto,
+		addr:          addr,
+		configFile:    configFile,
+		in:            in,
+		out:           out,
+		err:           err,
+		keyFile:       keyFile,
+		inFd:          inFd,
+		outFd:         outFd,
+		isTerminalIn:  isTerminalIn,
+		isTerminalOut: isTerminalOut,
+		tlsConfig:     tlsConfig,
+		scheme:        scheme,
+		transport:     tr,
+	}
+}

+ 17 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/client.go

@@ -0,0 +1,17 @@
+// Package client provides a command-line interface for Docker.
+//
+// Run "docker help SUBCOMMAND" or "docker SUBCOMMAND --help" to see more information on any Docker subcommand, including the full list of options supported for the subcommand.
+// See https://docs.docker.com/installation/ for instructions on installing Docker.
+package client
+
+import "fmt"
+
+// An StatusError reports an unsuccessful exit by a command.
+type StatusError struct {
+	Status     string
+	StatusCode int
+}
+
+func (e StatusError) Error() string {
+	return fmt.Sprintf("Status: %s, Code: %d", e.Status, e.StatusCode)
+}

+ 80 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/commit.go

@@ -0,0 +1,80 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/opts"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/registry"
+	"github.com/docker/docker/runconfig"
+)
+
+// CmdCommit creates a new image from a container's changes.
+//
+// Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
+func (cli *DockerCli) CmdCommit(args ...string) error {
+	cmd := cli.Subcmd("commit", "CONTAINER [REPOSITORY[:TAG]]", "Create a new image from a container's changes", true)
+	flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit")
+	flComment := cmd.String([]string{"m", "-message"}, "", "Commit message")
+	flAuthor := cmd.String([]string{"a", "#author", "-author"}, "", "Author (e.g., \"John Hannibal Smith <hannibal@a-team.com>\")")
+	flChanges := opts.NewListOpts(nil)
+	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
+	// FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
+	flConfig := cmd.String([]string{"#run", "#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands")
+	cmd.Require(flag.Max, 2)
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	var (
+		name            = cmd.Arg(0)
+		repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1))
+	)
+
+	//Check if the given image name can be resolved
+	if repository != "" {
+		if err := registry.ValidateRepositoryName(repository); err != nil {
+			return err
+		}
+	}
+
+	v := url.Values{}
+	v.Set("container", name)
+	v.Set("repo", repository)
+	v.Set("tag", tag)
+	v.Set("comment", *flComment)
+	v.Set("author", *flAuthor)
+	for _, change := range flChanges.GetAll() {
+		v.Add("changes", change)
+	}
+
+	if *flPause != true {
+		v.Set("pause", "0")
+	}
+
+	var (
+		config   *runconfig.Config
+		response types.ContainerCommitResponse
+	)
+
+	if *flConfig != "" {
+		config = &runconfig.Config{}
+		if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
+			return err
+		}
+	}
+	stream, _, _, err := cli.call("POST", "/commit?"+v.Encode(), config, nil)
+	if err != nil {
+		return err
+	}
+
+	if err := json.NewDecoder(stream).Decode(&response); err != nil {
+		return err
+	}
+
+	fmt.Fprintln(cli.out, response.ID)
+	return nil
+}

+ 57 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/cp.go

@@ -0,0 +1,57 @@
+package client
+
+import (
+	"fmt"
+	"io"
+	"strings"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/pkg/archive"
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdCp copies files/folders from a path on the container to a directory on the host running the command.
+//
+// If HOSTDIR is '-', the data is written as a tar file to STDOUT.
+//
+// Usage: docker cp CONTAINER:PATH HOSTDIR
+func (cli *DockerCli) CmdCp(args ...string) error {
+	cmd := cli.Subcmd("cp", "CONTAINER:PATH HOSTDIR|-", "Copy files/folders from a PATH on the container to a HOSTDIR on the host\nrunning the command. Use '-' to write the data as a tar file to STDOUT.", true)
+	cmd.Require(flag.Exact, 2)
+
+	cmd.ParseFlags(args, true)
+
+	// deal with path name with `:`
+	info := strings.SplitN(cmd.Arg(0), ":", 2)
+
+	if len(info) != 2 {
+		return fmt.Errorf("Error: Path not specified")
+	}
+
+	cfg := &types.CopyConfig{
+		Resource: info[1],
+	}
+	stream, _, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", cfg, nil)
+	if stream != nil {
+		defer stream.Close()
+	}
+	if statusCode == 404 {
+		return fmt.Errorf("No such container: %v", info[0])
+	}
+	if err != nil {
+		return err
+	}
+
+	hostPath := cmd.Arg(1)
+	if statusCode == 200 {
+		if hostPath == "-" {
+			_, err = io.Copy(cli.out, stream)
+		} else {
+			err = archive.Untar(stream, hostPath, &archive.TarOptions{NoLchown: true})
+		}
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}

+ 160 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/create.go

@@ -0,0 +1,160 @@
+package client
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/url"
+	"os"
+	"strings"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/graph/tags"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/registry"
+	"github.com/docker/docker/runconfig"
+	"github.com/docker/docker/utils"
+)
+
+func (cli *DockerCli) pullImage(image string) error {
+	return cli.pullImageCustomOut(image, cli.out)
+}
+
+func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
+	v := url.Values{}
+	repos, tag := parsers.ParseRepositoryTag(image)
+	// pull only the image tagged 'latest' if no tag was specified
+	if tag == "" {
+		tag = tags.DEFAULTTAG
+	}
+	v.Set("fromImage", repos)
+	v.Set("tag", tag)
+
+	// Resolve the Repository name from fqn to RepositoryInfo
+	repoInfo, err := registry.ParseRepositoryInfo(repos)
+	if err != nil {
+		return err
+	}
+
+	// Resolve the Auth config relevant for this server
+	authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index)
+	buf, err := json.Marshal(authConfig)
+	if err != nil {
+		return err
+	}
+
+	registryAuthHeader := []string{
+		base64.URLEncoding.EncodeToString(buf),
+	}
+	sopts := &streamOpts{
+		rawTerminal: true,
+		out:         out,
+		headers:     map[string][]string{"X-Registry-Auth": registryAuthHeader},
+	}
+	if err := cli.stream("POST", "/images/create?"+v.Encode(), sopts); err != nil {
+		return err
+	}
+	return nil
+}
+
+type cidFile struct {
+	path    string
+	file    *os.File
+	written bool
+}
+
+func newCIDFile(path string) (*cidFile, error) {
+	if _, err := os.Stat(path); err == nil {
+		return nil, fmt.Errorf("Container ID file found, make sure the other container isn't running or delete %s", path)
+	}
+
+	f, err := os.Create(path)
+	if err != nil {
+		return nil, fmt.Errorf("Failed to create the container ID file: %s", err)
+	}
+
+	return &cidFile{path: path, file: f}, nil
+}
+
+func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runconfig.HostConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
+	containerValues := url.Values{}
+	if name != "" {
+		containerValues.Set("name", name)
+	}
+
+	mergedConfig := runconfig.MergeConfigs(config, hostConfig)
+
+	var containerIDFile *cidFile
+	if cidfile != "" {
+		var err error
+		if containerIDFile, err = newCIDFile(cidfile); err != nil {
+			return nil, err
+		}
+		defer containerIDFile.Close()
+	}
+
+	//create the container
+	stream, _, statusCode, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil)
+	//if image not found try to pull it
+	if statusCode == 404 && strings.Contains(err.Error(), config.Image) {
+		repo, tag := parsers.ParseRepositoryTag(config.Image)
+		if tag == "" {
+			tag = tags.DEFAULTTAG
+		}
+		fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", utils.ImageReference(repo, tag))
+
+		// we don't want to write to stdout anything apart from container.ID
+		if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil {
+			return nil, err
+		}
+		// Retry
+		if stream, _, _, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil); err != nil {
+			return nil, err
+		}
+	} else if err != nil {
+		return nil, err
+	}
+
+	var response types.ContainerCreateResponse
+	if err := json.NewDecoder(stream).Decode(&response); err != nil {
+		return nil, err
+	}
+	for _, warning := range response.Warnings {
+		fmt.Fprintf(cli.err, "WARNING: %s\n", warning)
+	}
+	if containerIDFile != nil {
+		if err = containerIDFile.Write(response.ID); err != nil {
+			return nil, err
+		}
+	}
+	return &response, nil
+}
+
+// CmdCreate creates a new container from a given image.
+//
+// Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
+func (cli *DockerCli) CmdCreate(args ...string) error {
+	cmd := cli.Subcmd("create", "IMAGE [COMMAND] [ARG...]", "Create a new container", true)
+
+	// These are flags not stored in Config/HostConfig
+	var (
+		flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
+	)
+
+	config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
+	if err != nil {
+		cmd.ReportError(err.Error(), true)
+		os.Exit(1)
+	}
+	if config.Image == "" {
+		cmd.Usage()
+		return nil
+	}
+	response, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName)
+	if err != nil {
+		return err
+	}
+	fmt.Fprintf(cli.out, "%s\n", response.ID)
+	return nil
+}

+ 52 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/diff.go

@@ -0,0 +1,52 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/pkg/archive"
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdDiff shows changes on a container's filesystem.
+//
+// Each changed file is printed on a separate line, prefixed with a single
+// character that indicates the status of the file: C (modified), A (added),
+// or D (deleted).
+//
+// Usage: docker diff CONTAINER
+func (cli *DockerCli) CmdDiff(args ...string) error {
+	cmd := cli.Subcmd("diff", "CONTAINER", "Inspect changes on a container's filesystem", true)
+	cmd.Require(flag.Exact, 1)
+	cmd.ParseFlags(args, true)
+
+	if cmd.Arg(0) == "" {
+		return fmt.Errorf("Container name cannot be empty")
+	}
+
+	rdr, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/changes", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	changes := []types.ContainerChange{}
+	if err := json.NewDecoder(rdr).Decode(&changes); err != nil {
+		return err
+	}
+
+	for _, change := range changes {
+		var kind string
+		switch change.Kind {
+		case archive.ChangeModify:
+			kind = "C"
+		case archive.ChangeAdd:
+			kind = "A"
+		case archive.ChangeDelete:
+			kind = "D"
+		}
+		fmt.Fprintf(cli.out, "%s %s\n", kind, change.Path)
+	}
+
+	return nil
+}

+ 62 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/events.go

@@ -0,0 +1,62 @@
+package client
+
+import (
+	"net/url"
+	"time"
+
+	"github.com/docker/docker/opts"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers/filters"
+	"github.com/docker/docker/pkg/timeutils"
+)
+
+// CmdEvents prints a live stream of real time events from the server.
+//
+// Usage: docker events [OPTIONS]
+func (cli *DockerCli) CmdEvents(args ...string) error {
+	cmd := cli.Subcmd("events", "", "Get real time events from the server", true)
+	since := cmd.String([]string{"#since", "-since"}, "", "Show all events created since timestamp")
+	until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp")
+	flFilter := opts.NewListOpts(nil)
+	cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
+	cmd.Require(flag.Exact, 0)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		v               = url.Values{}
+		eventFilterArgs = filters.Args{}
+	)
+
+	// Consolidate all filter flags, and sanity check them early.
+	// They'll get process in the daemon/server.
+	for _, f := range flFilter.GetAll() {
+		var err error
+		eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs)
+		if err != nil {
+			return err
+		}
+	}
+	ref := time.Now()
+	if *since != "" {
+		v.Set("since", timeutils.GetTimestamp(*since, ref))
+	}
+	if *until != "" {
+		v.Set("until", timeutils.GetTimestamp(*until, ref))
+	}
+	if len(eventFilterArgs) > 0 {
+		filterJSON, err := filters.ToParam(eventFilterArgs)
+		if err != nil {
+			return err
+		}
+		v.Set("filters", filterJSON)
+	}
+	sopts := &streamOpts{
+		rawTerminal: true,
+		out:         cli.out,
+	}
+	if err := cli.stream("GET", "/events?"+v.Encode(), sopts); err != nil {
+		return err
+	}
+	return nil
+}

+ 131 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/exec.go

@@ -0,0 +1,131 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/pkg/promise"
+	"github.com/docker/docker/runconfig"
+)
+
+// CmdExec runs a command in a running container.
+//
+// Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
+func (cli *DockerCli) CmdExec(args ...string) error {
+	cmd := cli.Subcmd("exec", "CONTAINER COMMAND [ARG...]", "Run a command in a running container", true)
+
+	execConfig, err := runconfig.ParseExec(cmd, args)
+	// just in case the ParseExec does not exit
+	if execConfig.Container == "" || err != nil {
+		return StatusError{StatusCode: 1}
+	}
+
+	stream, _, _, err := cli.call("POST", "/containers/"+execConfig.Container+"/exec", execConfig, nil)
+	if err != nil {
+		return err
+	}
+
+	var response types.ContainerExecCreateResponse
+	if err := json.NewDecoder(stream).Decode(&response); err != nil {
+		return err
+	}
+
+	execID := response.ID
+
+	if execID == "" {
+		fmt.Fprintf(cli.out, "exec ID empty")
+		return nil
+	}
+
+	//Temp struct for execStart so that we don't need to transfer all the execConfig
+	execStartCheck := &types.ExecStartCheck{
+		Detach: execConfig.Detach,
+		Tty:    execConfig.Tty,
+	}
+
+	if !execConfig.Detach {
+		if err := cli.CheckTtyInput(execConfig.AttachStdin, execConfig.Tty); err != nil {
+			return err
+		}
+	} else {
+		if _, _, err := readBody(cli.call("POST", "/exec/"+execID+"/start", execStartCheck, nil)); err != nil {
+			return err
+		}
+		// For now don't print this - wait for when we support exec wait()
+		// fmt.Fprintf(cli.out, "%s\n", execID)
+		return nil
+	}
+
+	// Interactive exec requested.
+	var (
+		out, stderr io.Writer
+		in          io.ReadCloser
+		hijacked    = make(chan io.Closer)
+		errCh       chan error
+	)
+
+	// Block the return until the chan gets closed
+	defer func() {
+		logrus.Debugf("End of CmdExec(), Waiting for hijack to finish.")
+		if _, ok := <-hijacked; ok {
+			fmt.Fprintln(cli.err, "Hijack did not finish (chan still open)")
+		}
+	}()
+
+	if execConfig.AttachStdin {
+		in = cli.in
+	}
+	if execConfig.AttachStdout {
+		out = cli.out
+	}
+	if execConfig.AttachStderr {
+		if execConfig.Tty {
+			stderr = cli.out
+		} else {
+			stderr = cli.err
+		}
+	}
+	errCh = promise.Go(func() error {
+		return cli.hijack("POST", "/exec/"+execID+"/start", execConfig.Tty, in, out, stderr, hijacked, execConfig)
+	})
+
+	// Acknowledge the hijack before starting
+	select {
+	case closer := <-hijacked:
+		// Make sure that hijack gets closed when returning. (result
+		// in closing hijack chan and freeing server's goroutines.
+		if closer != nil {
+			defer closer.Close()
+		}
+	case err := <-errCh:
+		if err != nil {
+			logrus.Debugf("Error hijack: %s", err)
+			return err
+		}
+	}
+
+	if execConfig.Tty && cli.isTerminalIn {
+		if err := cli.monitorTtySize(execID, true); err != nil {
+			fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
+		}
+	}
+
+	if err := <-errCh; err != nil {
+		logrus.Debugf("Error hijack: %s", err)
+		return err
+	}
+
+	var status int
+	if _, status, err = getExecExitCode(cli, execID); err != nil {
+		return err
+	}
+
+	if status != 0 {
+		return StatusError{StatusCode: status}
+	}
+
+	return nil
+}

+ 46 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/export.go

@@ -0,0 +1,46 @@
+package client
+
+import (
+	"errors"
+	"io"
+	"os"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdExport exports a filesystem as a tar archive.
+//
+// The tar archive is streamed to STDOUT by default or written to a file.
+//
+// Usage: docker export [OPTIONS] CONTAINER
+func (cli *DockerCli) CmdExport(args ...string) error {
+	cmd := cli.Subcmd("export", "CONTAINER", "Export a filesystem as a tar archive (streamed to STDOUT by default)", true)
+	outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT")
+	cmd.Require(flag.Exact, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		output io.Writer = cli.out
+		err    error
+	)
+	if *outfile != "" {
+		output, err = os.Create(*outfile)
+		if err != nil {
+			return err
+		}
+	} else if cli.isTerminalOut {
+		return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
+	}
+
+	image := cmd.Arg(0)
+	sopts := &streamOpts{
+		rawTerminal: true,
+		out:         output,
+	}
+	if err := cli.stream("GET", "/containers/"+image+"/export", sopts); err != nil {
+		return err
+	}
+
+	return nil
+}

+ 34 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/help.go

@@ -0,0 +1,34 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdHelp displays information on a Docker command.
+//
+// If more than one command is specified, information is only shown for the first command.
+//
+// Usage: docker help COMMAND or docker COMMAND --help
+func (cli *DockerCli) CmdHelp(args ...string) error {
+	if len(args) > 1 {
+		method, exists := cli.getMethod(args[:2]...)
+		if exists {
+			method("--help")
+			return nil
+		}
+	}
+	if len(args) > 0 {
+		method, exists := cli.getMethod(args[0])
+		if !exists {
+			return fmt.Errorf("docker: '%s' is not a docker command. See 'docker --help'.", args[0])
+		}
+		method("--help")
+		return nil
+	}
+
+	flag.Usage()
+
+	return nil
+}

+ 257 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/hijack.go

@@ -0,0 +1,257 @@
+package client
+
+import (
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"net/http/httputil"
+	"os"
+	"runtime"
+	"strings"
+	"time"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api"
+	"github.com/docker/docker/autogen/dockerversion"
+	"github.com/docker/docker/pkg/promise"
+	"github.com/docker/docker/pkg/stdcopy"
+	"github.com/docker/docker/pkg/term"
+)
+
+type tlsClientCon struct {
+	*tls.Conn
+	rawConn net.Conn
+}
+
+func (c *tlsClientCon) CloseWrite() error {
+	// Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
+	// on its underlying connection.
+	if cwc, ok := c.rawConn.(interface {
+		CloseWrite() error
+	}); ok {
+		return cwc.CloseWrite()
+	}
+	return nil
+}
+
+func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) {
+	return tlsDialWithDialer(new(net.Dialer), network, addr, config)
+}
+
+// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in
+// order to return our custom tlsClientCon struct which holds both the tls.Conn
+// object _and_ its underlying raw connection. The rationale for this is that
+// we need to be able to close the write end of the connection when attaching,
+// which tls.Conn does not provide.
+func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
+	// We want the Timeout and Deadline values from dialer to cover the
+	// whole process: TCP connection and TLS handshake. This means that we
+	// also need to start our own timers now.
+	timeout := dialer.Timeout
+
+	if !dialer.Deadline.IsZero() {
+		deadlineTimeout := dialer.Deadline.Sub(time.Now())
+		if timeout == 0 || deadlineTimeout < timeout {
+			timeout = deadlineTimeout
+		}
+	}
+
+	var errChannel chan error
+
+	if timeout != 0 {
+		errChannel = make(chan error, 2)
+		time.AfterFunc(timeout, func() {
+			errChannel <- errors.New("")
+		})
+	}
+
+	rawConn, err := dialer.Dial(network, addr)
+	if err != nil {
+		return nil, err
+	}
+	// When we set up a TCP connection for hijack, there could be long periods
+	// of inactivity (a long running command with no output) that in certain
+	// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
+	// state. Setting TCP KeepAlive on the socket connection will prohibit
+	// ECONNTIMEOUT unless the socket connection truly is broken
+	if tcpConn, ok := rawConn.(*net.TCPConn); ok {
+		tcpConn.SetKeepAlive(true)
+		tcpConn.SetKeepAlivePeriod(30 * time.Second)
+	}
+
+	colonPos := strings.LastIndex(addr, ":")
+	if colonPos == -1 {
+		colonPos = len(addr)
+	}
+	hostname := addr[:colonPos]
+
+	// If no ServerName is set, infer the ServerName
+	// from the hostname we're connecting to.
+	if config.ServerName == "" {
+		// Make a copy to avoid polluting argument or default.
+		c := *config
+		c.ServerName = hostname
+		config = &c
+	}
+
+	conn := tls.Client(rawConn, config)
+
+	if timeout == 0 {
+		err = conn.Handshake()
+	} else {
+		go func() {
+			errChannel <- conn.Handshake()
+		}()
+
+		err = <-errChannel
+	}
+
+	if err != nil {
+		rawConn.Close()
+		return nil, err
+	}
+
+	// This is Docker difference with standard's crypto/tls package: returned a
+	// wrapper which holds both the TLS and raw connections.
+	return &tlsClientCon{conn, rawConn}, nil
+}
+
+func (cli *DockerCli) dial() (net.Conn, error) {
+	if cli.tlsConfig != nil && cli.proto != "unix" {
+		// Notice this isn't Go standard's tls.Dial function
+		return tlsDial(cli.proto, cli.addr, cli.tlsConfig)
+	}
+	return net.Dial(cli.proto, cli.addr)
+}
+
+func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan io.Closer, data interface{}) error {
+	defer func() {
+		if started != nil {
+			close(started)
+		}
+	}()
+
+	params, err := cli.encodeData(data)
+	if err != nil {
+		return err
+	}
+	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params)
+	if err != nil {
+		return err
+	}
+
+	// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
+	// then the user can't change OUR headers
+	for k, v := range cli.configFile.HttpHeaders {
+		req.Header.Set(k, v)
+	}
+
+	req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION+" ("+runtime.GOOS+")")
+	req.Header.Set("Content-Type", "text/plain")
+	req.Header.Set("Connection", "Upgrade")
+	req.Header.Set("Upgrade", "tcp")
+	req.Host = cli.addr
+
+	dial, err := cli.dial()
+	// When we set up a TCP connection for hijack, there could be long periods
+	// of inactivity (a long running command with no output) that in certain
+	// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
+	// state. Setting TCP KeepAlive on the socket connection will prohibit
+	// ECONNTIMEOUT unless the socket connection truly is broken
+	if tcpConn, ok := dial.(*net.TCPConn); ok {
+		tcpConn.SetKeepAlive(true)
+		tcpConn.SetKeepAlivePeriod(30 * time.Second)
+	}
+	if err != nil {
+		if strings.Contains(err.Error(), "connection refused") {
+			return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
+		}
+		return err
+	}
+	clientconn := httputil.NewClientConn(dial, nil)
+	defer clientconn.Close()
+
+	// Server hijacks the connection, error 'connection closed' expected
+	clientconn.Do(req)
+
+	rwc, br := clientconn.Hijack()
+	defer rwc.Close()
+
+	if started != nil {
+		started <- rwc
+	}
+
+	var receiveStdout chan error
+
+	var oldState *term.State
+
+	if in != nil && setRawTerminal && cli.isTerminalIn && os.Getenv("NORAW") == "" {
+		oldState, err = term.SetRawTerminal(cli.inFd)
+		if err != nil {
+			return err
+		}
+		defer term.RestoreTerminal(cli.inFd, oldState)
+	}
+
+	if stdout != nil || stderr != nil {
+		receiveStdout = promise.Go(func() (err error) {
+			defer func() {
+				if in != nil {
+					if setRawTerminal && cli.isTerminalIn {
+						term.RestoreTerminal(cli.inFd, oldState)
+					}
+					// For some reason this Close call blocks on darwin..
+					// As the client exists right after, simply discard the close
+					// until we find a better solution.
+					if runtime.GOOS != "darwin" {
+						in.Close()
+					}
+				}
+			}()
+
+			// When TTY is ON, use regular copy
+			if setRawTerminal && stdout != nil {
+				_, err = io.Copy(stdout, br)
+			} else {
+				_, err = stdcopy.StdCopy(stdout, stderr, br)
+			}
+			logrus.Debugf("[hijack] End of stdout")
+			return err
+		})
+	}
+
+	sendStdin := promise.Go(func() error {
+		if in != nil {
+			io.Copy(rwc, in)
+			logrus.Debugf("[hijack] End of stdin")
+		}
+
+		if conn, ok := rwc.(interface {
+			CloseWrite() error
+		}); ok {
+			if err := conn.CloseWrite(); err != nil {
+				logrus.Debugf("Couldn't send EOF: %s", err)
+			}
+		}
+		// Discard errors due to pipe interruption
+		return nil
+	})
+
+	if stdout != nil || stderr != nil {
+		if err := <-receiveStdout; err != nil {
+			logrus.Debugf("Error receiveStdout: %s", err)
+			return err
+		}
+	}
+
+	if !cli.isTerminalIn {
+		if err := <-sendStdin; err != nil {
+			logrus.Debugf("Error sendStdin: %s", err)
+			return err
+		}
+	}
+	return nil
+}

+ 73 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/history.go

@@ -0,0 +1,73 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"text/tabwriter"
+	"time"
+
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/pkg/stringutils"
+	"github.com/docker/docker/pkg/units"
+)
+
+// CmdHistory shows the history of an image.
+//
+// Usage: docker history [OPTIONS] IMAGE
+func (cli *DockerCli) CmdHistory(args ...string) error {
+	cmd := cli.Subcmd("history", "IMAGE", "Show the history of an image", true)
+	human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format")
+	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
+	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
+	cmd.Require(flag.Exact, 1)
+	cmd.ParseFlags(args, true)
+
+	rdr, _, _, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	history := []types.ImageHistory{}
+	if err := json.NewDecoder(rdr).Decode(&history); err != nil {
+		return err
+	}
+
+	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
+	if !*quiet {
+		fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT")
+	}
+
+	for _, entry := range history {
+		if *noTrunc {
+			fmt.Fprintf(w, entry.ID)
+		} else {
+			fmt.Fprintf(w, stringid.TruncateID(entry.ID))
+		}
+		if !*quiet {
+			if *human {
+				fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))))
+			} else {
+				fmt.Fprintf(w, "\t%s\t", time.Unix(entry.Created, 0).Format(time.RFC3339))
+			}
+
+			if *noTrunc {
+				fmt.Fprintf(w, "%s\t", entry.CreatedBy)
+			} else {
+				fmt.Fprintf(w, "%s\t", stringutils.Truncate(entry.CreatedBy, 45))
+			}
+
+			if *human {
+				fmt.Fprintf(w, "%s\t", units.HumanSize(float64(entry.Size)))
+			} else {
+				fmt.Fprintf(w, "%d\t", entry.Size)
+			}
+
+			fmt.Fprintf(w, "%s", entry.Comment)
+		}
+		fmt.Fprintf(w, "\n")
+	}
+	w.Flush()
+	return nil
+}

+ 126 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/images.go

@@ -0,0 +1,126 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+	"text/tabwriter"
+	"time"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/opts"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/pkg/parsers/filters"
+	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/pkg/units"
+	"github.com/docker/docker/utils"
+)
+
+// CmdImages lists the images in a specified repository, or all top-level images if no repository is specified.
+//
+// Usage: docker images [OPTIONS] [REPOSITORY]
+func (cli *DockerCli) CmdImages(args ...string) error {
+	cmd := cli.Subcmd("images", "[REPOSITORY]", "List images", true)
+	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
+	all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (default hides intermediate images)")
+	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
+	showDigests := cmd.Bool([]string{"-digests"}, false, "Show digests")
+
+	flFilter := opts.NewListOpts(nil)
+	cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
+	cmd.Require(flag.Max, 1)
+	cmd.ParseFlags(args, true)
+
+	// Consolidate all filter flags, and sanity check them early.
+	// They'll get process in the daemon/server.
+	imageFilterArgs := filters.Args{}
+	for _, f := range flFilter.GetAll() {
+		var err error
+		imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs)
+		if err != nil {
+			return err
+		}
+	}
+
+	matchName := cmd.Arg(0)
+	v := url.Values{}
+	if len(imageFilterArgs) > 0 {
+		filterJSON, err := filters.ToParam(imageFilterArgs)
+		if err != nil {
+			return err
+		}
+		v.Set("filters", filterJSON)
+	}
+
+	if cmd.NArg() == 1 {
+		// FIXME rename this parameter, to not be confused with the filters flag
+		v.Set("filter", matchName)
+	}
+	if *all {
+		v.Set("all", "1")
+	}
+
+	rdr, _, _, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil)
+	if err != nil {
+		return err
+	}
+
+	images := []types.Image{}
+	if err := json.NewDecoder(rdr).Decode(&images); err != nil {
+		return err
+	}
+
+	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
+	if !*quiet {
+		if *showDigests {
+			fmt.Fprintln(w, "REPOSITORY\tTAG\tDIGEST\tIMAGE ID\tCREATED\tVIRTUAL SIZE")
+		} else {
+			fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE")
+		}
+	}
+
+	for _, image := range images {
+		ID := image.ID
+		if !*noTrunc {
+			ID = stringid.TruncateID(ID)
+		}
+
+		repoTags := image.RepoTags
+		repoDigests := image.RepoDigests
+
+		if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" {
+			// dangling image - clear out either repoTags or repoDigsts so we only show it once below
+			repoDigests = []string{}
+		}
+
+		// combine the tags and digests lists
+		tagsAndDigests := append(repoTags, repoDigests...)
+		for _, repoAndRef := range tagsAndDigests {
+			repo, ref := parsers.ParseRepositoryTag(repoAndRef)
+			// default tag and digest to none - if there's a value, it'll be set below
+			tag := "<none>"
+			digest := "<none>"
+			if utils.DigestReference(ref) {
+				digest = ref
+			} else {
+				tag = ref
+			}
+
+			if !*quiet {
+				if *showDigests {
+					fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize)))
+				} else {
+					fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize)))
+				}
+			} else {
+				fmt.Fprintln(w, ID)
+			}
+		}
+	}
+
+	if !*quiet {
+		w.Flush()
+	}
+	return nil
+}

+ 64 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/import.go

@@ -0,0 +1,64 @@
+package client
+
+import (
+	"fmt"
+	"io"
+	"net/url"
+
+	"github.com/docker/docker/opts"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/registry"
+)
+
+// CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image.
+//
+// The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file. If the URL is '-', then the tar file is read from STDIN.
+//
+// Usage: docker import [OPTIONS] URL [REPOSITORY[:TAG]]
+func (cli *DockerCli) CmdImport(args ...string) error {
+	cmd := cli.Subcmd("import", "URL|- [REPOSITORY[:TAG]]", "Create an empty filesystem image and import the contents of the\ntarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then\noptionally tag it.", true)
+	flChanges := opts.NewListOpts(nil)
+	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		v          = url.Values{}
+		src        = cmd.Arg(0)
+		repository = cmd.Arg(1)
+	)
+
+	v.Set("fromSrc", src)
+	v.Set("repo", repository)
+	for _, change := range flChanges.GetAll() {
+		v.Add("changes", change)
+	}
+	if cmd.NArg() == 3 {
+		fmt.Fprintf(cli.err, "[DEPRECATED] The format 'URL|- [REPOSITORY [TAG]]' has been deprecated. Please use URL|- [REPOSITORY[:TAG]]\n")
+		v.Set("tag", cmd.Arg(2))
+	}
+
+	if repository != "" {
+		//Check if the given image name can be resolved
+		repo, _ := parsers.ParseRepositoryTag(repository)
+		if err := registry.ValidateRepositoryName(repo); err != nil {
+			return err
+		}
+	}
+
+	var in io.Reader
+
+	if src == "-" {
+		in = cli.in
+	}
+
+	sopts := &streamOpts{
+		rawTerminal: true,
+		in:          in,
+		out:         cli.out,
+	}
+
+	return cli.stream("POST", "/images/create?"+v.Encode(), sopts)
+}

+ 91 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/info.go

@@ -0,0 +1,91 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/pkg/ioutils"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/units"
+)
+
+// CmdInfo displays system-wide information.
+//
+// Usage: docker info
+func (cli *DockerCli) CmdInfo(args ...string) error {
+	cmd := cli.Subcmd("info", "", "Display system-wide information", true)
+	cmd.Require(flag.Exact, 0)
+	cmd.ParseFlags(args, true)
+
+	rdr, _, _, err := cli.call("GET", "/info", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	info := &types.Info{}
+	if err := json.NewDecoder(rdr).Decode(info); err != nil {
+		return fmt.Errorf("Error reading remote info: %v", err)
+	}
+
+	fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers)
+	fmt.Fprintf(cli.out, "Images: %d\n", info.Images)
+	ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver)
+	if info.DriverStatus != nil {
+		for _, pair := range info.DriverStatus {
+			fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1])
+		}
+	}
+	ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver)
+	ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
+	ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion)
+	ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem)
+	fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU)
+	fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal)))
+	ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name)
+	ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID)
+
+	if info.Debug {
+		fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug)
+		fmt.Fprintf(cli.out, "File Descriptors: %d\n", info.NFd)
+		fmt.Fprintf(cli.out, "Goroutines: %d\n", info.NGoroutines)
+		fmt.Fprintf(cli.out, "System Time: %s\n", info.SystemTime)
+		fmt.Fprintf(cli.out, "EventsListeners: %d\n", info.NEventsListener)
+		fmt.Fprintf(cli.out, "Init SHA1: %s\n", info.InitSha1)
+		fmt.Fprintf(cli.out, "Init Path: %s\n", info.InitPath)
+		fmt.Fprintf(cli.out, "Docker Root Dir: %s\n", info.DockerRootDir)
+	}
+
+	ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HttpProxy)
+	ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HttpsProxy)
+	ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy)
+
+	if info.IndexServerAddress != "" {
+		u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username
+		if len(u) > 0 {
+			fmt.Fprintf(cli.out, "Username: %v\n", u)
+			fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress)
+		}
+	}
+	if !info.MemoryLimit {
+		fmt.Fprintf(cli.err, "WARNING: No memory limit support\n")
+	}
+	if !info.SwapLimit {
+		fmt.Fprintf(cli.err, "WARNING: No swap limit support\n")
+	}
+	if !info.IPv4Forwarding {
+		fmt.Fprintf(cli.err, "WARNING: IPv4 forwarding is disabled.\n")
+	}
+	if info.Labels != nil {
+		fmt.Fprintln(cli.out, "Labels:")
+		for _, attribute := range info.Labels {
+			fmt.Fprintf(cli.out, " %s\n", attribute)
+		}
+	}
+
+	if info.ExperimentalBuild {
+		fmt.Fprintf(cli.out, "Experimental: true\n")
+	}
+
+	return nil
+}

+ 124 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/inspect.go

@@ -0,0 +1,124 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"strings"
+	"text/template"
+
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdInspect displays low-level information on one or more containers or images.
+//
+// Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]
+func (cli *DockerCli) CmdInspect(args ...string) error {
+	cmd := cli.Subcmd("inspect", "CONTAINER|IMAGE [CONTAINER|IMAGE...]", "Return low-level information on a container or image", true)
+	tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var tmpl *template.Template
+	if *tmplStr != "" {
+		var err error
+		if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
+			return StatusError{StatusCode: 64,
+				Status: "Template parsing error: " + err.Error()}
+		}
+	}
+
+	indented := new(bytes.Buffer)
+	indented.WriteString("[\n")
+	status := 0
+	isImage := false
+
+	for _, name := range cmd.Args() {
+		obj, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
+		if err != nil {
+			obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
+			isImage = true
+			if err != nil {
+				if strings.Contains(err.Error(), "No such") {
+					fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
+				} else {
+					fmt.Fprintf(cli.err, "%s", err)
+				}
+				status = 1
+				continue
+			}
+		}
+
+		if tmpl == nil {
+			if err = json.Indent(indented, obj, "", "    "); err != nil {
+				fmt.Fprintf(cli.err, "%s\n", err)
+				status = 1
+				continue
+			}
+		} else {
+			rdr := bytes.NewReader(obj)
+			dec := json.NewDecoder(rdr)
+
+			if isImage {
+				inspPtr := types.ImageInspect{}
+				if err := dec.Decode(&inspPtr); err != nil {
+					fmt.Fprintf(cli.err, "%s\n", err)
+					status = 1
+					continue
+				}
+				if err := tmpl.Execute(cli.out, inspPtr); err != nil {
+					rdr.Seek(0, 0)
+					var raw interface{}
+					if err := dec.Decode(&raw); err != nil {
+						return err
+					}
+					if err = tmpl.Execute(cli.out, raw); err != nil {
+						return err
+					}
+				}
+			} else {
+				inspPtr := types.ContainerJSON{}
+				if err := dec.Decode(&inspPtr); err != nil {
+					fmt.Fprintf(cli.err, "%s\n", err)
+					status = 1
+					continue
+				}
+				if err := tmpl.Execute(cli.out, inspPtr); err != nil {
+					rdr.Seek(0, 0)
+					var raw interface{}
+					if err := dec.Decode(&raw); err != nil {
+						return err
+					}
+					if err = tmpl.Execute(cli.out, raw); err != nil {
+						return err
+					}
+				}
+			}
+			cli.out.Write([]byte{'\n'})
+		}
+		indented.WriteString(",")
+	}
+
+	if indented.Len() > 1 {
+		// Remove trailing ','
+		indented.Truncate(indented.Len() - 1)
+	}
+	indented.WriteString("]\n")
+
+	if tmpl == nil {
+		// Note that we will always write "[]" when "-f" isn't specified,
+		// to make sure the output would always be array, see
+		// https://github.com/docker/docker/pull/9500#issuecomment-65846734
+		if _, err := io.Copy(cli.out, indented); err != nil {
+			return err
+		}
+	}
+
+	if status != 0 {
+		return StatusError{StatusCode: status}
+	}
+	return nil
+}

+ 32 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/kill.go

@@ -0,0 +1,32 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdKill kills one or more running container using SIGKILL or a specified signal.
+//
+// Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdKill(args ...string) error {
+	cmd := cli.Subcmd("kill", "CONTAINER [CONTAINER...]", "Kill a running container using SIGKILL or a specified signal", true)
+	signal := cmd.String([]string{"s", "-signal"}, "KILL", "Signal to send to the container")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", name, *signal), nil, nil)); err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%s\n", name)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to kill containers: %v", errNames)
+	}
+	return nil
+}

+ 41 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/load.go

@@ -0,0 +1,41 @@
+package client
+
+import (
+	"io"
+	"os"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdLoad loads an image from a tar archive.
+//
+// The tar archive is read from STDIN by default, or from a tar archive file.
+//
+// Usage: docker load [OPTIONS]
+func (cli *DockerCli) CmdLoad(args ...string) error {
+	cmd := cli.Subcmd("load", "", "Load an image from a tar archive on STDIN", true)
+	infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN")
+	cmd.Require(flag.Exact, 0)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		input io.Reader = cli.in
+		err   error
+	)
+	if *infile != "" {
+		input, err = os.Open(*infile)
+		if err != nil {
+			return err
+		}
+	}
+	sopts := &streamOpts{
+		rawTerminal: true,
+		in:          input,
+		out:         cli.out,
+	}
+	if err := cli.stream("POST", "/images/load", sopts); err != nil {
+		return err
+	}
+	return nil
+}

+ 144 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/login.go

@@ -0,0 +1,144 @@
+package client
+
+import (
+	"bufio"
+	"encoding/json"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/cliconfig"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/term"
+	"github.com/docker/docker/registry"
+)
+
+// CmdLogin logs in or registers a user to a Docker registry service.
+//
+// If no server is specified, the user will be logged into or registered to the registry's index server.
+//
+// Usage: docker login SERVER
+func (cli *DockerCli) CmdLogin(args ...string) error {
+	cmd := cli.Subcmd("login", "[SERVER]", "Register or log in to a Docker registry server, if no server is\nspecified \""+registry.IndexServerAddress()+"\" is the default.", true)
+	cmd.Require(flag.Max, 1)
+
+	var username, password, email string
+
+	cmd.StringVar(&username, []string{"u", "-username"}, "", "Username")
+	cmd.StringVar(&password, []string{"p", "-password"}, "", "Password")
+	cmd.StringVar(&email, []string{"e", "-email"}, "", "Email")
+
+	cmd.ParseFlags(args, true)
+
+	serverAddress := registry.IndexServerAddress()
+	if len(cmd.Args()) > 0 {
+		serverAddress = cmd.Arg(0)
+	}
+
+	promptDefault := func(prompt string, configDefault string) {
+		if configDefault == "" {
+			fmt.Fprintf(cli.out, "%s: ", prompt)
+		} else {
+			fmt.Fprintf(cli.out, "%s (%s): ", prompt, configDefault)
+		}
+	}
+
+	readInput := func(in io.Reader, out io.Writer) string {
+		reader := bufio.NewReader(in)
+		line, _, err := reader.ReadLine()
+		if err != nil {
+			fmt.Fprintln(out, err.Error())
+			os.Exit(1)
+		}
+		return string(line)
+	}
+
+	authconfig, ok := cli.configFile.AuthConfigs[serverAddress]
+	if !ok {
+		authconfig = cliconfig.AuthConfig{}
+	}
+
+	if username == "" {
+		promptDefault("Username", authconfig.Username)
+		username = readInput(cli.in, cli.out)
+		username = strings.Trim(username, " ")
+		if username == "" {
+			username = authconfig.Username
+		}
+	}
+	// Assume that a different username means they may not want to use
+	// the password or email from the config file, so prompt them
+	if username != authconfig.Username {
+		if password == "" {
+			oldState, err := term.SaveState(cli.inFd)
+			if err != nil {
+				return err
+			}
+			fmt.Fprintf(cli.out, "Password: ")
+			term.DisableEcho(cli.inFd, oldState)
+
+			password = readInput(cli.in, cli.out)
+			fmt.Fprint(cli.out, "\n")
+
+			term.RestoreTerminal(cli.inFd, oldState)
+			if password == "" {
+				return fmt.Errorf("Error : Password Required")
+			}
+		}
+
+		if email == "" {
+			promptDefault("Email", authconfig.Email)
+			email = readInput(cli.in, cli.out)
+			if email == "" {
+				email = authconfig.Email
+			}
+		}
+	} else {
+		// However, if they don't override the username use the
+		// password or email from the cmd line if specified. IOW, allow
+		// then to change/override them.  And if not specified, just
+		// use what's in the config file
+		if password == "" {
+			password = authconfig.Password
+		}
+		if email == "" {
+			email = authconfig.Email
+		}
+	}
+	authconfig.Username = username
+	authconfig.Password = password
+	authconfig.Email = email
+	authconfig.ServerAddress = serverAddress
+	cli.configFile.AuthConfigs[serverAddress] = authconfig
+
+	stream, _, statusCode, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil)
+	if statusCode == 401 {
+		delete(cli.configFile.AuthConfigs, serverAddress)
+		if err2 := cli.configFile.Save(); err2 != nil {
+			fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2)
+		}
+		return err
+	}
+	if err != nil {
+		return err
+	}
+
+	var response types.AuthResponse
+	if err := json.NewDecoder(stream).Decode(&response); err != nil {
+		// Upon error, remove entry
+		delete(cli.configFile.AuthConfigs, serverAddress)
+		return err
+	}
+
+	if err := cli.configFile.Save(); err != nil {
+		return fmt.Errorf("Error saving config file: %v", err)
+	}
+	fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s\n", cli.configFile.Filename())
+
+	if response.Status != "" {
+		fmt.Fprintf(cli.out, "%s\n", response.Status)
+	}
+	return nil
+}

+ 36 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/logout.go

@@ -0,0 +1,36 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/registry"
+)
+
+// CmdLogout logs a user out from a Docker registry.
+//
+// If no server is specified, the user will be logged out from the registry's index server.
+//
+// Usage: docker logout [SERVER]
+func (cli *DockerCli) CmdLogout(args ...string) error {
+	cmd := cli.Subcmd("logout", "[SERVER]", "Log out from a Docker registry, if no server is\nspecified \""+registry.IndexServerAddress()+"\" is the default.", true)
+	cmd.Require(flag.Max, 1)
+
+	cmd.ParseFlags(args, true)
+	serverAddress := registry.IndexServerAddress()
+	if len(cmd.Args()) > 0 {
+		serverAddress = cmd.Arg(0)
+	}
+
+	if _, ok := cli.configFile.AuthConfigs[serverAddress]; !ok {
+		fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress)
+	} else {
+		fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress)
+		delete(cli.configFile.AuthConfigs, serverAddress)
+
+		if err := cli.configFile.Save(); err != nil {
+			return fmt.Errorf("Failed to save docker config: %v", err)
+		}
+	}
+	return nil
+}

+ 69 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/logs.go

@@ -0,0 +1,69 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+	"time"
+
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/timeutils"
+)
+
+// CmdLogs fetches the logs of a given container.
+//
+// docker logs [OPTIONS] CONTAINER
+func (cli *DockerCli) CmdLogs(args ...string) error {
+	var (
+		cmd    = cli.Subcmd("logs", "CONTAINER", "Fetch the logs of a container", true)
+		follow = cmd.Bool([]string{"f", "-follow"}, false, "Follow log output")
+		since  = cmd.String([]string{"-since"}, "", "Show logs since timestamp")
+		times  = cmd.Bool([]string{"t", "-timestamps"}, false, "Show timestamps")
+		tail   = cmd.String([]string{"-tail"}, "all", "Number of lines to show from the end of the logs")
+	)
+	cmd.Require(flag.Exact, 1)
+
+	cmd.ParseFlags(args, true)
+
+	name := cmd.Arg(0)
+
+	stream, _, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	var c types.ContainerJSON
+	if err := json.NewDecoder(stream).Decode(&c); err != nil {
+		return err
+	}
+
+	if logType := c.HostConfig.LogConfig.Type; logType != "json-file" {
+		return fmt.Errorf("\"logs\" command is supported only for \"json-file\" logging driver (got: %s)", logType)
+	}
+
+	v := url.Values{}
+	v.Set("stdout", "1")
+	v.Set("stderr", "1")
+
+	if *since != "" {
+		v.Set("since", timeutils.GetTimestamp(*since, time.Now()))
+	}
+
+	if *times {
+		v.Set("timestamps", "1")
+	}
+
+	if *follow {
+		v.Set("follow", "1")
+	}
+	v.Set("tail", *tail)
+
+	sopts := &streamOpts{
+		rawTerminal: c.Config.Tty,
+		out:         cli.out,
+		err:         cli.err,
+	}
+
+	return cli.stream("GET", "/containers/"+name+"/logs?"+v.Encode(), sopts)
+}

+ 30 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/pause.go

@@ -0,0 +1,30 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdPause pauses all processes within one or more containers.
+//
+// Usage: docker pause CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdPause(args ...string) error {
+	cmd := cli.Subcmd("pause", "CONTAINER [CONTAINER...]", "Pause all processes within a container", true)
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/pause", name), nil, nil)); err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%s\n", name)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to pause containers: %v", errNames)
+	}
+	return nil
+}

+ 64 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/port.go

@@ -0,0 +1,64 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"strings"
+
+	"github.com/docker/docker/nat"
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdPort lists port mappings for a container.
+// If a private port is specified, it also shows the public-facing port that is NATed to the private port.
+//
+// Usage: docker port CONTAINER [PRIVATE_PORT[/PROTO]]
+func (cli *DockerCli) CmdPort(args ...string) error {
+	cmd := cli.Subcmd("port", "CONTAINER [PRIVATE_PORT[/PROTO]]", "List port mappings for the CONTAINER, or lookup the public-facing port that\nis NAT-ed to the PRIVATE_PORT", true)
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	stream, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	var c struct {
+		NetworkSettings struct {
+			Ports nat.PortMap
+		}
+	}
+
+	if err := json.NewDecoder(stream).Decode(&c); err != nil {
+		return err
+	}
+
+	if cmd.NArg() == 2 {
+		var (
+			port  = cmd.Arg(1)
+			proto = "tcp"
+			parts = strings.SplitN(port, "/", 2)
+		)
+
+		if len(parts) == 2 && len(parts[1]) != 0 {
+			port = parts[0]
+			proto = parts[1]
+		}
+		natPort := port + "/" + proto
+		if frontends, exists := c.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
+			for _, frontend := range frontends {
+				fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
+			}
+			return nil
+		}
+		return fmt.Errorf("Error: No public port '%s' published for %s", natPort, cmd.Arg(0))
+	}
+
+	for from, frontends := range c.NetworkSettings.Ports {
+		for _, frontend := range frontends {
+			fmt.Fprintf(cli.out, "%s -> %s:%s\n", from, frontend.HostIp, frontend.HostPort)
+		}
+	}
+
+	return nil
+}

+ 175 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/ps.go

@@ -0,0 +1,175 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+	"strconv"
+	"strings"
+	"text/tabwriter"
+	"time"
+
+	"github.com/docker/docker/api"
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/opts"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers/filters"
+	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/pkg/stringutils"
+	"github.com/docker/docker/pkg/units"
+)
+
+// CmdPs outputs a list of Docker containers.
+//
+// Usage: docker ps [OPTIONS]
+func (cli *DockerCli) CmdPs(args ...string) error {
+	var (
+		err error
+
+		psFilterArgs = filters.Args{}
+		v            = url.Values{}
+
+		cmd      = cli.Subcmd("ps", "", "List containers", true)
+		quiet    = cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
+		size     = cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes")
+		all      = cmd.Bool([]string{"a", "-all"}, false, "Show all containers (default shows just running)")
+		noTrunc  = cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
+		nLatest  = cmd.Bool([]string{"l", "-latest"}, false, "Show the latest created container, include non-running")
+		since    = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show created since Id or Name, include non-running")
+		before   = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name")
+		last     = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running")
+		flFilter = opts.NewListOpts(nil)
+	)
+	cmd.Require(flag.Exact, 0)
+
+	cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
+
+	cmd.ParseFlags(args, true)
+	if *last == -1 && *nLatest {
+		*last = 1
+	}
+
+	if *all {
+		v.Set("all", "1")
+	}
+
+	if *last != -1 {
+		v.Set("limit", strconv.Itoa(*last))
+	}
+
+	if *since != "" {
+		v.Set("since", *since)
+	}
+
+	if *before != "" {
+		v.Set("before", *before)
+	}
+
+	if *size {
+		v.Set("size", "1")
+	}
+
+	// Consolidate all filter flags, and sanity check them.
+	// They'll get processed in the daemon/server.
+	for _, f := range flFilter.GetAll() {
+		if psFilterArgs, err = filters.ParseFlag(f, psFilterArgs); err != nil {
+			return err
+		}
+	}
+
+	if len(psFilterArgs) > 0 {
+		filterJSON, err := filters.ToParam(psFilterArgs)
+		if err != nil {
+			return err
+		}
+
+		v.Set("filters", filterJSON)
+	}
+
+	rdr, _, _, err := cli.call("GET", "/containers/json?"+v.Encode(), nil, nil)
+	if err != nil {
+		return err
+	}
+
+	containers := []types.Container{}
+	if err := json.NewDecoder(rdr).Decode(&containers); err != nil {
+		return err
+	}
+
+	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
+	if !*quiet {
+		fmt.Fprint(w, "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES")
+
+		if *size {
+			fmt.Fprintln(w, "\tSIZE")
+		} else {
+			fmt.Fprint(w, "\n")
+		}
+	}
+
+	stripNamePrefix := func(ss []string) []string {
+		for i, s := range ss {
+			ss[i] = s[1:]
+		}
+
+		return ss
+	}
+
+	for _, container := range containers {
+		ID := container.ID
+
+		if !*noTrunc {
+			ID = stringid.TruncateID(ID)
+		}
+
+		if *quiet {
+			fmt.Fprintln(w, ID)
+
+			continue
+		}
+
+		var (
+			names   = stripNamePrefix(container.Names)
+			command = strconv.Quote(container.Command)
+		)
+
+		if !*noTrunc {
+			command = stringutils.Truncate(command, 20)
+
+			// only display the default name for the container with notrunc is passed
+			for _, name := range names {
+				if len(strings.Split(name, "/")) == 1 {
+					names = []string{name}
+					break
+				}
+			}
+		}
+
+		image := container.Image
+		if image == "" {
+			image = "<no image>"
+		}
+
+		fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", ID, image, command,
+			units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))),
+			container.Status, api.DisplayablePorts(container.Ports), strings.Join(names, ","))
+
+		if *size {
+			if container.SizeRootFs > 0 {
+				fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(container.SizeRw)), units.HumanSize(float64(container.SizeRootFs)))
+			} else {
+				fmt.Fprintf(w, "%s\n", units.HumanSize(float64(container.SizeRw)))
+			}
+
+			continue
+		}
+
+		fmt.Fprint(w, "\n")
+	}
+
+	if !*quiet {
+		w.Flush()
+	}
+
+	return nil
+}

+ 47 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/pull.go

@@ -0,0 +1,47 @@
+package client
+
+import (
+	"fmt"
+	"net/url"
+
+	"github.com/docker/docker/graph/tags"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/registry"
+	"github.com/docker/docker/utils"
+)
+
+// CmdPull pulls an image or a repository from the registry.
+//
+// Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST]
+func (cli *DockerCli) CmdPull(args ...string) error {
+	cmd := cli.Subcmd("pull", "NAME[:TAG|@DIGEST]", "Pull an image or a repository from the registry", true)
+	allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")
+	cmd.Require(flag.Exact, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		v         = url.Values{}
+		remote    = cmd.Arg(0)
+		newRemote = remote
+	)
+	taglessRemote, tag := parsers.ParseRepositoryTag(remote)
+	if tag == "" && !*allTags {
+		newRemote = utils.ImageReference(taglessRemote, tags.DEFAULTTAG)
+	}
+	if tag != "" && *allTags {
+		return fmt.Errorf("tag can't be used with --all-tags/-a")
+	}
+
+	v.Set("fromImage", newRemote)
+
+	// Resolve the Repository name from fqn to RepositoryInfo
+	repoInfo, err := registry.ParseRepositoryInfo(taglessRemote)
+	if err != nil {
+		return err
+	}
+
+	_, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull")
+	return err
+}

+ 49 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/push.go

@@ -0,0 +1,49 @@
+package client
+
+import (
+	"fmt"
+	"net/url"
+
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/registry"
+)
+
+// CmdPush pushes an image or repository to the registry.
+//
+// Usage: docker push NAME[:TAG]
+func (cli *DockerCli) CmdPush(args ...string) error {
+	cmd := cli.Subcmd("push", "NAME[:TAG]", "Push an image or a repository to the registry", true)
+	cmd.Require(flag.Exact, 1)
+
+	cmd.ParseFlags(args, true)
+
+	name := cmd.Arg(0)
+
+	remote, tag := parsers.ParseRepositoryTag(name)
+
+	// Resolve the Repository name from fqn to RepositoryInfo
+	repoInfo, err := registry.ParseRepositoryInfo(remote)
+	if err != nil {
+		return err
+	}
+	// Resolve the Auth config relevant for this server
+	authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index)
+	// If we're not using a custom registry, we know the restrictions
+	// applied to repository names and can warn the user in advance.
+	// Custom repositories can have different rules, and we must also
+	// allow pushing by image ID.
+	if repoInfo.Official {
+		username := authConfig.Username
+		if username == "" {
+			username = "<user>"
+		}
+		return fmt.Errorf("You cannot push a \"root\" repository. Please rename your repository to <user>/<repo> (ex: %s/%s)", username, repoInfo.LocalName)
+	}
+
+	v := url.Values{}
+	v.Set("tag", tag)
+
+	_, _, err = cli.clientRequestAttemptLogin("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, repoInfo.Index, "push")
+	return err
+}

+ 25 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/rename.go

@@ -0,0 +1,25 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdRename renames a container.
+//
+// Usage: docker rename OLD_NAME NEW_NAME
+func (cli *DockerCli) CmdRename(args ...string) error {
+	cmd := cli.Subcmd("rename", "OLD_NAME NEW_NAME", "Rename a container", true)
+	cmd.Require(flag.Exact, 2)
+	cmd.ParseFlags(args, true)
+
+	oldName := cmd.Arg(0)
+	newName := cmd.Arg(1)
+
+	if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/rename?name=%s", oldName, newName), nil, nil)); err != nil {
+		fmt.Fprintf(cli.err, "%s\n", err)
+		return fmt.Errorf("Error: failed to rename container named %s", oldName)
+	}
+	return nil
+}

+ 38 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/restart.go

@@ -0,0 +1,38 @@
+package client
+
+import (
+	"fmt"
+	"net/url"
+	"strconv"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdRestart restarts one or more running containers.
+//
+// Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdRestart(args ...string) error {
+	cmd := cli.Subcmd("restart", "CONTAINER [CONTAINER...]", "Restart a running container", true)
+	nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing the container")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	v := url.Values{}
+	v.Set("t", strconv.Itoa(*nSeconds))
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		_, _, err := readBody(cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil, nil))
+		if err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%s\n", name)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to restart containers: %v", errNames)
+	}
+	return nil
+}

+ 54 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/rm.go

@@ -0,0 +1,54 @@
+package client
+
+import (
+	"fmt"
+	"net/url"
+	"strings"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdRm removes one or more containers.
+//
+// Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdRm(args ...string) error {
+	cmd := cli.Subcmd("rm", "CONTAINER [CONTAINER...]", "Remove one or more containers", true)
+	v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated with the container")
+	link := cmd.Bool([]string{"l", "#link", "-link"}, false, "Remove the specified link")
+	force := cmd.Bool([]string{"f", "-force"}, false, "Force the removal of a running container (uses SIGKILL)")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	val := url.Values{}
+	if *v {
+		val.Set("v", "1")
+	}
+	if *link {
+		val.Set("link", "1")
+	}
+
+	if *force {
+		val.Set("force", "1")
+	}
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		if name == "" {
+			return fmt.Errorf("Container name cannot be empty")
+		}
+		name = strings.Trim(name, "/")
+
+		_, _, err := readBody(cli.call("DELETE", "/containers/"+name+"?"+val.Encode(), nil, nil))
+		if err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%s\n", name)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to remove containers: %v", errNames)
+	}
+	return nil
+}

+ 59 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/rmi.go

@@ -0,0 +1,59 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdRmi removes all images with the specified name(s).
+//
+// Usage: docker rmi [OPTIONS] IMAGE [IMAGE...]
+func (cli *DockerCli) CmdRmi(args ...string) error {
+	var (
+		cmd     = cli.Subcmd("rmi", "IMAGE [IMAGE...]", "Remove one or more images", true)
+		force   = cmd.Bool([]string{"f", "-force"}, false, "Force removal of the image")
+		noprune = cmd.Bool([]string{"-no-prune"}, false, "Do not delete untagged parents")
+	)
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	v := url.Values{}
+	if *force {
+		v.Set("force", "1")
+	}
+	if *noprune {
+		v.Set("noprune", "1")
+	}
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		rdr, _, _, err := cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, nil)
+		if err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			dels := []types.ImageDelete{}
+			if err := json.NewDecoder(rdr).Decode(&dels); err != nil {
+				fmt.Fprintf(cli.err, "%s\n", err)
+				errNames = append(errNames, name)
+				continue
+			}
+
+			for _, del := range dels {
+				if del.Deleted != "" {
+					fmt.Fprintf(cli.out, "Deleted: %s\n", del.Deleted)
+				} else {
+					fmt.Fprintf(cli.out, "Untagged: %s\n", del.Untagged)
+				}
+			}
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to remove images: %v", errNames)
+	}
+	return nil
+}

+ 247 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/run.go

@@ -0,0 +1,247 @@
+package client
+
+import (
+	"fmt"
+	"io"
+	"net/url"
+	"os"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/opts"
+	"github.com/docker/docker/pkg/promise"
+	"github.com/docker/docker/pkg/signal"
+	"github.com/docker/docker/runconfig"
+	"github.com/docker/libnetwork/resolvconf/dns"
+)
+
+func (cid *cidFile) Close() error {
+	cid.file.Close()
+
+	if !cid.written {
+		if err := os.Remove(cid.path); err != nil {
+			return fmt.Errorf("failed to remove the CID file '%s': %s \n", cid.path, err)
+		}
+	}
+
+	return nil
+}
+
+func (cid *cidFile) Write(id string) error {
+	if _, err := cid.file.Write([]byte(id)); err != nil {
+		return fmt.Errorf("Failed to write the container ID to the file: %s", err)
+	}
+	cid.written = true
+	return nil
+}
+
+// CmdRun runs a command in a new container.
+//
+// Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
+func (cli *DockerCli) CmdRun(args ...string) error {
+	cmd := cli.Subcmd("run", "IMAGE [COMMAND] [ARG...]", "Run a command in a new container", true)
+
+	// These are flags not stored in Config/HostConfig
+	var (
+		flAutoRemove = cmd.Bool([]string{"-rm"}, false, "Automatically remove the container when it exits")
+		flDetach     = cmd.Bool([]string{"d", "-detach"}, false, "Run container in background and print container ID")
+		flSigProxy   = cmd.Bool([]string{"-sig-proxy"}, true, "Proxy received signals to the process")
+		flName       = cmd.String([]string{"-name"}, "", "Assign a name to the container")
+		flAttach     *opts.ListOpts
+
+		ErrConflictAttachDetach               = fmt.Errorf("Conflicting options: -a and -d")
+		ErrConflictRestartPolicyAndAutoRemove = fmt.Errorf("Conflicting options: --restart and --rm")
+		ErrConflictDetachAutoRemove           = fmt.Errorf("Conflicting options: --rm and -d")
+	)
+
+	config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
+	// just in case the Parse does not exit
+	if err != nil {
+		cmd.ReportError(err.Error(), true)
+		os.Exit(1)
+	}
+
+	if len(hostConfig.Dns) > 0 {
+		// check the DNS settings passed via --dns against
+		// localhost regexp to warn if they are trying to
+		// set a DNS to a localhost address
+		for _, dnsIP := range hostConfig.Dns {
+			if dns.IsLocalhost(dnsIP) {
+				fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP)
+				break
+			}
+		}
+	}
+	if config.Image == "" {
+		cmd.Usage()
+		return nil
+	}
+
+	if !*flDetach {
+		if err := cli.CheckTtyInput(config.AttachStdin, config.Tty); err != nil {
+			return err
+		}
+	} else {
+		if fl := cmd.Lookup("-attach"); fl != nil {
+			flAttach = fl.Value.(*opts.ListOpts)
+			if flAttach.Len() != 0 {
+				return ErrConflictAttachDetach
+			}
+		}
+		if *flAutoRemove {
+			return ErrConflictDetachAutoRemove
+		}
+
+		config.AttachStdin = false
+		config.AttachStdout = false
+		config.AttachStderr = false
+		config.StdinOnce = false
+	}
+
+	// Disable flSigProxy when in TTY mode
+	sigProxy := *flSigProxy
+	if config.Tty {
+		sigProxy = false
+	}
+
+	createResponse, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName)
+	if err != nil {
+		return err
+	}
+	if sigProxy {
+		sigc := cli.forwardAllSignals(createResponse.ID)
+		defer signal.StopCatch(sigc)
+	}
+	var (
+		waitDisplayID chan struct{}
+		errCh         chan error
+	)
+	if !config.AttachStdout && !config.AttachStderr {
+		// Make this asynchronous to allow the client to write to stdin before having to read the ID
+		waitDisplayID = make(chan struct{})
+		go func() {
+			defer close(waitDisplayID)
+			fmt.Fprintf(cli.out, "%s\n", createResponse.ID)
+		}()
+	}
+	if *flAutoRemove && (hostConfig.RestartPolicy.IsAlways() || hostConfig.RestartPolicy.IsOnFailure()) {
+		return ErrConflictRestartPolicyAndAutoRemove
+	}
+	// We need to instantiate the chan because the select needs it. It can
+	// be closed but can't be uninitialized.
+	hijacked := make(chan io.Closer)
+	// Block the return until the chan gets closed
+	defer func() {
+		logrus.Debugf("End of CmdRun(), Waiting for hijack to finish.")
+		if _, ok := <-hijacked; ok {
+			fmt.Fprintln(cli.err, "Hijack did not finish (chan still open)")
+		}
+	}()
+	if config.AttachStdin || config.AttachStdout || config.AttachStderr {
+		var (
+			out, stderr io.Writer
+			in          io.ReadCloser
+			v           = url.Values{}
+		)
+		v.Set("stream", "1")
+		if config.AttachStdin {
+			v.Set("stdin", "1")
+			in = cli.in
+		}
+		if config.AttachStdout {
+			v.Set("stdout", "1")
+			out = cli.out
+		}
+		if config.AttachStderr {
+			v.Set("stderr", "1")
+			if config.Tty {
+				stderr = cli.out
+			} else {
+				stderr = cli.err
+			}
+		}
+		errCh = promise.Go(func() error {
+			return cli.hijack("POST", "/containers/"+createResponse.ID+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked, nil)
+		})
+	} else {
+		close(hijacked)
+	}
+	// Acknowledge the hijack before starting
+	select {
+	case closer := <-hijacked:
+		// Make sure that the hijack gets closed when returning (results
+		// in closing the hijack chan and freeing server's goroutines)
+		if closer != nil {
+			defer closer.Close()
+		}
+	case err := <-errCh:
+		if err != nil {
+			logrus.Debugf("Error hijack: %s", err)
+			return err
+		}
+	}
+
+	defer func() {
+		if *flAutoRemove {
+			if _, _, err = readBody(cli.call("DELETE", "/containers/"+createResponse.ID+"?v=1", nil, nil)); err != nil {
+				fmt.Fprintf(cli.err, "Error deleting container: %s\n", err)
+			}
+		}
+	}()
+
+	//start the container
+	if _, _, err = readBody(cli.call("POST", "/containers/"+createResponse.ID+"/start", nil, nil)); err != nil {
+		return err
+	}
+
+	if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminalOut {
+		if err := cli.monitorTtySize(createResponse.ID, false); err != nil {
+			fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
+		}
+	}
+
+	if errCh != nil {
+		if err := <-errCh; err != nil {
+			logrus.Debugf("Error hijack: %s", err)
+			return err
+		}
+	}
+
+	// Detached mode: wait for the id to be displayed and return.
+	if !config.AttachStdout && !config.AttachStderr {
+		// Detached mode
+		<-waitDisplayID
+		return nil
+	}
+
+	var status int
+
+	// Attached mode
+	if *flAutoRemove {
+		// Autoremove: wait for the container to finish, retrieve
+		// the exit code and remove the container
+		if _, _, err := readBody(cli.call("POST", "/containers/"+createResponse.ID+"/wait", nil, nil)); err != nil {
+			return err
+		}
+		if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
+			return err
+		}
+	} else {
+		// No Autoremove: Simply retrieve the exit code
+		if !config.Tty {
+			// In non-TTY mode, we can't detach, so we must wait for container exit
+			if status, err = waitForExit(cli, createResponse.ID); err != nil {
+				return err
+			}
+		} else {
+			// In TTY mode, there is a race: if the process dies too slowly, the state could
+			// be updated after the getExitCode call and result in the wrong exit code being reported
+			if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
+				return err
+			}
+		}
+	}
+	if status != 0 {
+		return StatusError{StatusCode: status}
+	}
+	return nil
+}

+ 57 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/save.go

@@ -0,0 +1,57 @@
+package client
+
+import (
+	"errors"
+	"io"
+	"net/url"
+	"os"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdSave saves one or more images to a tar archive.
+//
+// The tar archive is written to STDOUT by default, or written to a file.
+//
+// Usage: docker save [OPTIONS] IMAGE [IMAGE...]
+func (cli *DockerCli) CmdSave(args ...string) error {
+	cmd := cli.Subcmd("save", "IMAGE [IMAGE...]", "Save an image(s) to a tar archive (streamed to STDOUT by default)", true)
+	outfile := cmd.String([]string{"o", "-output"}, "", "Write to an file, instead of STDOUT")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		output io.Writer = cli.out
+		err    error
+	)
+	if *outfile != "" {
+		output, err = os.Create(*outfile)
+		if err != nil {
+			return err
+		}
+	} else if cli.isTerminalOut {
+		return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
+	}
+
+	sopts := &streamOpts{
+		rawTerminal: true,
+		out:         output,
+	}
+
+	if len(cmd.Args()) == 1 {
+		image := cmd.Arg(0)
+		if err := cli.stream("GET", "/images/"+image+"/get", sopts); err != nil {
+			return err
+		}
+	} else {
+		v := url.Values{}
+		for _, arg := range cmd.Args() {
+			v.Add("names", arg)
+		}
+		if err := cli.stream("GET", "/images/get?"+v.Encode(), sopts); err != nil {
+			return err
+		}
+	}
+	return nil
+}

+ 84 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/search.go

@@ -0,0 +1,84 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+	"sort"
+	"strings"
+	"text/tabwriter"
+
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/pkg/stringutils"
+	"github.com/docker/docker/registry"
+)
+
+// ByStars sorts search results in ascending order by number of stars.
+type ByStars []registry.SearchResult
+
+func (r ByStars) Len() int           { return len(r) }
+func (r ByStars) Swap(i, j int)      { r[i], r[j] = r[j], r[i] }
+func (r ByStars) Less(i, j int) bool { return r[i].StarCount < r[j].StarCount }
+
+// CmdSearch searches the Docker Hub for images.
+//
+// Usage: docker search [OPTIONS] TERM
+func (cli *DockerCli) CmdSearch(args ...string) error {
+	cmd := cli.Subcmd("search", "TERM", "Search the Docker Hub for images", true)
+	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
+	trusted := cmd.Bool([]string{"#t", "#trusted", "#-trusted"}, false, "Only show trusted builds")
+	automated := cmd.Bool([]string{"-automated"}, false, "Only show automated builds")
+	stars := cmd.Uint([]string{"s", "#stars", "-stars"}, 0, "Only displays with at least x stars")
+	cmd.Require(flag.Exact, 1)
+
+	cmd.ParseFlags(args, true)
+
+	name := cmd.Arg(0)
+	v := url.Values{}
+	v.Set("term", name)
+
+	// Resolve the Repository name from fqn to hostname + name
+	taglessRemote, _ := parsers.ParseRepositoryTag(name)
+	repoInfo, err := registry.ParseRepositoryInfo(taglessRemote)
+	if err != nil {
+		return err
+	}
+
+	rdr, _, err := cli.clientRequestAttemptLogin("GET", "/images/search?"+v.Encode(), nil, nil, repoInfo.Index, "search")
+	if err != nil {
+		return err
+	}
+
+	results := ByStars{}
+	if err := json.NewDecoder(rdr).Decode(&results); err != nil {
+		return err
+	}
+
+	sort.Sort(sort.Reverse(results))
+
+	w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0)
+	fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n")
+	for _, res := range results {
+		if ((*automated || *trusted) && (!res.IsTrusted && !res.IsAutomated)) || (int(*stars) > res.StarCount) {
+			continue
+		}
+		desc := strings.Replace(res.Description, "\n", " ", -1)
+		desc = strings.Replace(desc, "\r", " ", -1)
+		if !*noTrunc && len(desc) > 45 {
+			desc = stringutils.Truncate(desc, 42) + "..."
+		}
+		fmt.Fprintf(w, "%s\t%s\t%d\t", res.Name, desc, res.StarCount)
+		if res.IsOfficial {
+			fmt.Fprint(w, "[OK]")
+
+		}
+		fmt.Fprint(w, "\t")
+		if res.IsAutomated || res.IsTrusted {
+			fmt.Fprint(w, "[OK]")
+		}
+		fmt.Fprint(w, "\n")
+	}
+	w.Flush()
+	return nil
+}

+ 167 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/start.go

@@ -0,0 +1,167 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/url"
+	"os"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/promise"
+	"github.com/docker/docker/pkg/signal"
+)
+
+func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
+	sigc := make(chan os.Signal, 128)
+	signal.CatchAll(sigc)
+	go func() {
+		for s := range sigc {
+			if s == signal.SIGCHLD {
+				continue
+			}
+			var sig string
+			for sigStr, sigN := range signal.SignalMap {
+				if sigN == s {
+					sig = sigStr
+					break
+				}
+			}
+			if sig == "" {
+				fmt.Fprintf(cli.err, "Unsupported signal: %v. Discarding.\n", s)
+			}
+			if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, nil)); err != nil {
+				logrus.Debugf("Error sending signal: %s", err)
+			}
+		}
+	}()
+	return sigc
+}
+
+// CmdStart starts one or more stopped containers.
+//
+// Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdStart(args ...string) error {
+	var (
+		cErr chan error
+		tty  bool
+
+		cmd       = cli.Subcmd("start", "CONTAINER [CONTAINER...]", "Start one or more stopped containers", true)
+		attach    = cmd.Bool([]string{"a", "-attach"}, false, "Attach STDOUT/STDERR and forward signals")
+		openStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's STDIN")
+	)
+
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	if *attach || *openStdin {
+		if cmd.NArg() > 1 {
+			return fmt.Errorf("You cannot start and attach multiple containers at once.")
+		}
+
+		stream, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
+		if err != nil {
+			return err
+		}
+
+		var c types.ContainerJSON
+		if err := json.NewDecoder(stream).Decode(&c); err != nil {
+			return err
+		}
+
+		tty = c.Config.Tty
+
+		if !tty {
+			sigc := cli.forwardAllSignals(cmd.Arg(0))
+			defer signal.StopCatch(sigc)
+		}
+
+		var in io.ReadCloser
+
+		v := url.Values{}
+		v.Set("stream", "1")
+
+		if *openStdin && c.Config.OpenStdin {
+			v.Set("stdin", "1")
+			in = cli.in
+		}
+
+		v.Set("stdout", "1")
+		v.Set("stderr", "1")
+
+		hijacked := make(chan io.Closer)
+		// Block the return until the chan gets closed
+		defer func() {
+			logrus.Debugf("CmdStart() returned, defer waiting for hijack to finish.")
+			if _, ok := <-hijacked; ok {
+				fmt.Fprintln(cli.err, "Hijack did not finish (chan still open)")
+			}
+			cli.in.Close()
+		}()
+		cErr = promise.Go(func() error {
+			return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, hijacked, nil)
+		})
+
+		// Acknowledge the hijack before starting
+		select {
+		case closer := <-hijacked:
+			// Make sure that the hijack gets closed when returning (results
+			// in closing the hijack chan and freeing server's goroutines)
+			if closer != nil {
+				defer closer.Close()
+			}
+		case err := <-cErr:
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	var encounteredError error
+	var errNames []string
+	for _, name := range cmd.Args() {
+		_, _, err := readBody(cli.call("POST", "/containers/"+name+"/start", nil, nil))
+		if err != nil {
+			if !*attach && !*openStdin {
+				// attach and openStdin is false means it could be starting multiple containers
+				// when a container start failed, show the error message and start next
+				fmt.Fprintf(cli.err, "%s\n", err)
+				errNames = append(errNames, name)
+			} else {
+				encounteredError = err
+			}
+		} else {
+			if !*attach && !*openStdin {
+				fmt.Fprintf(cli.out, "%s\n", name)
+			}
+		}
+	}
+
+	if len(errNames) > 0 {
+		encounteredError = fmt.Errorf("Error: failed to start containers: %v", errNames)
+	}
+	if encounteredError != nil {
+		return encounteredError
+	}
+
+	if *openStdin || *attach {
+		if tty && cli.isTerminalOut {
+			if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
+				fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
+			}
+		}
+		if attchErr := <-cErr; attchErr != nil {
+			return attchErr
+		}
+		_, status, err := getExitCode(cli, cmd.Arg(0))
+		if err != nil {
+			return err
+		}
+		if status != 0 {
+			return StatusError{StatusCode: status}
+		}
+	}
+	return nil
+}

+ 198 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/stats.go

@@ -0,0 +1,198 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/url"
+	"sort"
+	"strings"
+	"sync"
+	"text/tabwriter"
+	"time"
+
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/units"
+)
+
+type containerStats struct {
+	Name             string
+	CPUPercentage    float64
+	Memory           float64
+	MemoryLimit      float64
+	MemoryPercentage float64
+	NetworkRx        float64
+	NetworkTx        float64
+	mu               sync.RWMutex
+	err              error
+}
+
+func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
+	v := url.Values{}
+	if streamStats {
+		v.Set("stream", "1")
+	} else {
+		v.Set("stream", "0")
+	}
+	stream, _, _, err := cli.call("GET", "/containers/"+s.Name+"/stats?"+v.Encode(), nil, nil)
+	if err != nil {
+		s.mu.Lock()
+		s.err = err
+		s.mu.Unlock()
+		return
+	}
+	defer stream.Close()
+	var (
+		previousCPU    uint64
+		previousSystem uint64
+		dec            = json.NewDecoder(stream)
+		u              = make(chan error, 1)
+	)
+	go func() {
+		for {
+			var v *types.Stats
+			if err := dec.Decode(&v); err != nil {
+				u <- err
+				return
+			}
+			var (
+				memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0
+				cpuPercent = 0.0
+			)
+			previousCPU = v.PreCpuStats.CpuUsage.TotalUsage
+			previousSystem = v.PreCpuStats.SystemUsage
+			cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
+			s.mu.Lock()
+			s.CPUPercentage = cpuPercent
+			s.Memory = float64(v.MemoryStats.Usage)
+			s.MemoryLimit = float64(v.MemoryStats.Limit)
+			s.MemoryPercentage = memPercent
+			s.NetworkRx = float64(v.Network.RxBytes)
+			s.NetworkTx = float64(v.Network.TxBytes)
+			s.mu.Unlock()
+			u <- nil
+			if !streamStats {
+				return
+			}
+		}
+	}()
+	for {
+		select {
+		case <-time.After(2 * time.Second):
+			// zero out the values if we have not received an update within
+			// the specified duration.
+			s.mu.Lock()
+			s.CPUPercentage = 0
+			s.Memory = 0
+			s.MemoryPercentage = 0
+			s.mu.Unlock()
+		case err := <-u:
+			if err != nil {
+				s.mu.Lock()
+				s.err = err
+				s.mu.Unlock()
+				return
+			}
+		}
+		if !streamStats {
+			return
+		}
+	}
+}
+
+func (s *containerStats) Display(w io.Writer) error {
+	s.mu.RLock()
+	defer s.mu.RUnlock()
+	if s.err != nil {
+		return s.err
+	}
+	fmt.Fprintf(w, "%s\t%.2f%%\t%s/%s\t%.2f%%\t%s/%s\n",
+		s.Name,
+		s.CPUPercentage,
+		units.HumanSize(s.Memory), units.HumanSize(s.MemoryLimit),
+		s.MemoryPercentage,
+		units.HumanSize(s.NetworkRx), units.HumanSize(s.NetworkTx))
+	return nil
+}
+
+// CmdStats displays a live stream of resource usage statistics for one or more containers.
+//
+// This shows real-time information on CPU usage, memory usage, and network I/O.
+//
+// Usage: docker stats CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdStats(args ...string) error {
+	cmd := cli.Subcmd("stats", "CONTAINER [CONTAINER...]", "Display a live stream of one or more containers' resource usage statistics", true)
+	noStream := cmd.Bool([]string{"-no-stream"}, false, "Disable streaming stats and only pull the first result")
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	names := cmd.Args()
+	sort.Strings(names)
+	var (
+		cStats []*containerStats
+		w      = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
+	)
+	printHeader := func() {
+		if !*noStream {
+			fmt.Fprint(cli.out, "\033[2J")
+			fmt.Fprint(cli.out, "\033[H")
+		}
+		io.WriteString(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O\n")
+	}
+	for _, n := range names {
+		s := &containerStats{Name: n}
+		cStats = append(cStats, s)
+		go s.Collect(cli, !*noStream)
+	}
+	// do a quick pause so that any failed connections for containers that do not exist are able to be
+	// evicted before we display the initial or default values.
+	time.Sleep(1500 * time.Millisecond)
+	var errs []string
+	for _, c := range cStats {
+		c.mu.Lock()
+		if c.err != nil {
+			errs = append(errs, fmt.Sprintf("%s: %v", c.Name, c.err))
+		}
+		c.mu.Unlock()
+	}
+	if len(errs) > 0 {
+		return fmt.Errorf("%s", strings.Join(errs, ", "))
+	}
+	for range time.Tick(500 * time.Millisecond) {
+		printHeader()
+		toRemove := []int{}
+		for i, s := range cStats {
+			if err := s.Display(w); err != nil && !*noStream {
+				toRemove = append(toRemove, i)
+			}
+		}
+		for j := len(toRemove) - 1; j >= 0; j-- {
+			i := toRemove[j]
+			cStats = append(cStats[:i], cStats[i+1:]...)
+		}
+		if len(cStats) == 0 {
+			return nil
+		}
+		w.Flush()
+		if *noStream {
+			break
+		}
+	}
+	return nil
+}
+
+func calculateCPUPercent(previousCPU, previousSystem uint64, v *types.Stats) float64 {
+	var (
+		cpuPercent = 0.0
+		// calculate the change for the cpu usage of the container in between readings
+		cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCPU)
+		// calculate the change for the entire system between readings
+		systemDelta = float64(v.CpuStats.SystemUsage - previousSystem)
+	)
+
+	if systemDelta > 0.0 && cpuDelta > 0.0 {
+		cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CpuStats.CpuUsage.PercpuUsage)) * 100.0
+	}
+	return cpuPercent
+}

+ 29 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/stats_unit_test.go

@@ -0,0 +1,29 @@
+package client
+
+import (
+	"bytes"
+	"sync"
+	"testing"
+)
+
+func TestDisplay(t *testing.T) {
+	c := &containerStats{
+		Name:             "app",
+		CPUPercentage:    30.0,
+		Memory:           100 * 1024 * 1024.0,
+		MemoryLimit:      2048 * 1024 * 1024.0,
+		MemoryPercentage: 100.0 / 2048.0 * 100.0,
+		NetworkRx:        100 * 1024 * 1024,
+		NetworkTx:        800 * 1024 * 1024,
+		mu:               sync.RWMutex{},
+	}
+	var b bytes.Buffer
+	if err := c.Display(&b); err != nil {
+		t.Fatalf("c.Display() gave error: %s", err)
+	}
+	got := b.String()
+	want := "app\t30.00%\t104.9 MB/2.147 GB\t4.88%\t104.9 MB/838.9 MB\n"
+	if got != want {
+		t.Fatalf("c.Display() = %q, want %q", got, want)
+	}
+}

+ 40 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/stop.go

@@ -0,0 +1,40 @@
+package client
+
+import (
+	"fmt"
+	"net/url"
+	"strconv"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdStop stops one or more running containers.
+//
+// A running container is stopped by first sending SIGTERM and then SIGKILL if the container fails to stop within a grace period (the default is 10 seconds).
+//
+// Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdStop(args ...string) error {
+	cmd := cli.Subcmd("stop", "CONTAINER [CONTAINER...]", "Stop a running container by sending SIGTERM and then SIGKILL after a\ngrace period", true)
+	nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing it")
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	v := url.Values{}
+	v.Set("t", strconv.Itoa(*nSeconds))
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		_, _, err := readBody(cli.call("POST", "/containers/"+name+"/stop?"+v.Encode(), nil, nil))
+		if err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%s\n", name)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to stop containers: %v", errNames)
+	}
+	return nil
+}

+ 41 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/tag.go

@@ -0,0 +1,41 @@
+package client
+
+import (
+	"net/url"
+
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/pkg/parsers"
+	"github.com/docker/docker/registry"
+)
+
+// CmdTag tags an image into a repository.
+//
+// Usage: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
+func (cli *DockerCli) CmdTag(args ...string) error {
+	cmd := cli.Subcmd("tag", "IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]", "Tag an image into a repository", true)
+	force := cmd.Bool([]string{"f", "#force", "-force"}, false, "Force")
+	cmd.Require(flag.Exact, 2)
+
+	cmd.ParseFlags(args, true)
+
+	var (
+		repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1))
+		v               = url.Values{}
+	)
+
+	//Check if the given image name can be resolved
+	if err := registry.ValidateRepositoryName(repository); err != nil {
+		return err
+	}
+	v.Set("repo", repository)
+	v.Set("tag", tag)
+
+	if *force {
+		v.Set("force", "1")
+	}
+
+	if _, _, err := readBody(cli.call("POST", "/images/"+cmd.Arg(0)+"/tag?"+v.Encode(), nil, nil)); err != nil {
+		return err
+	}
+	return nil
+}

+ 46 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/top.go

@@ -0,0 +1,46 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+	"strings"
+	"text/tabwriter"
+
+	"github.com/docker/docker/api/types"
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdTop displays the running processes of a container.
+//
+// Usage: docker top CONTAINER
+func (cli *DockerCli) CmdTop(args ...string) error {
+	cmd := cli.Subcmd("top", "CONTAINER [ps OPTIONS]", "Display the running processes of a container", true)
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	val := url.Values{}
+	if cmd.NArg() > 1 {
+		val.Set("ps_args", strings.Join(cmd.Args()[1:], " "))
+	}
+
+	stream, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, nil)
+	if err != nil {
+		return err
+	}
+
+	procList := types.ContainerProcessList{}
+	if err := json.NewDecoder(stream).Decode(&procList); err != nil {
+		return err
+	}
+
+	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
+	fmt.Fprintln(w, strings.Join(procList.Titles, "\t"))
+
+	for _, proc := range procList.Processes {
+		fmt.Fprintln(w, strings.Join(proc, "\t"))
+	}
+	w.Flush()
+	return nil
+}

+ 30 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/unpause.go

@@ -0,0 +1,30 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdUnpause unpauses all processes within a container, for one or more containers.
+//
+// Usage: docker unpause CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdUnpause(args ...string) error {
+	cmd := cli.Subcmd("unpause", "CONTAINER [CONTAINER...]", "Unpause all processes within a container", true)
+	cmd.Require(flag.Min, 1)
+	cmd.ParseFlags(args, true)
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/unpause", name), nil, nil)); err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%s\n", name)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to unpause containers: %v", errNames)
+	}
+	return nil
+}

+ 345 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/utils.go

@@ -0,0 +1,345 @@
+package client
+
+import (
+	"bytes"
+	"encoding/base64"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	gosignal "os/signal"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api"
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/autogen/dockerversion"
+	"github.com/docker/docker/cliconfig"
+	"github.com/docker/docker/pkg/jsonmessage"
+	"github.com/docker/docker/pkg/signal"
+	"github.com/docker/docker/pkg/stdcopy"
+	"github.com/docker/docker/pkg/term"
+	"github.com/docker/docker/registry"
+)
+
+var (
+	errConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
+)
+
+// HTTPClient creates a new HTTP client with the cli's client transport instance.
+func (cli *DockerCli) HTTPClient() *http.Client {
+	return &http.Client{Transport: cli.transport}
+}
+
+func (cli *DockerCli) encodeData(data interface{}) (*bytes.Buffer, error) {
+	params := bytes.NewBuffer(nil)
+	if data != nil {
+		if err := json.NewEncoder(params).Encode(data); err != nil {
+			return nil, err
+		}
+	}
+	return params, nil
+}
+
+func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
+	expectedPayload := (method == "POST" || method == "PUT")
+	if expectedPayload && in == nil {
+		in = bytes.NewReader([]byte{})
+	}
+	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), in)
+	if err != nil {
+		return nil, nil, -1, err
+	}
+
+	// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
+	// then the user can't change OUR headers
+	for k, v := range cli.configFile.HttpHeaders {
+		req.Header.Set(k, v)
+	}
+
+	req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION+" ("+runtime.GOOS+")")
+	req.URL.Host = cli.addr
+	req.URL.Scheme = cli.scheme
+
+	if headers != nil {
+		for k, v := range headers {
+			req.Header[k] = v
+		}
+	}
+
+	if expectedPayload && req.Header.Get("Content-Type") == "" {
+		req.Header.Set("Content-Type", "text/plain")
+	}
+
+	resp, err := cli.HTTPClient().Do(req)
+	statusCode := -1
+	if resp != nil {
+		statusCode = resp.StatusCode
+	}
+	if err != nil {
+		if strings.Contains(err.Error(), "connection refused") {
+			return nil, nil, statusCode, errConnectionRefused
+		}
+
+		if cli.tlsConfig == nil {
+			return nil, nil, statusCode, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
+		}
+		return nil, nil, statusCode, fmt.Errorf("An error occurred trying to connect: %v", err)
+	}
+
+	if statusCode < 200 || statusCode >= 400 {
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			return nil, nil, statusCode, err
+		}
+		if len(body) == 0 {
+			return nil, nil, statusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(statusCode), req.URL)
+		}
+		return nil, nil, statusCode, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body))
+	}
+
+	return resp.Body, resp.Header, statusCode, nil
+}
+
+func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reader, out io.Writer, index *registry.IndexInfo, cmdName string) (io.ReadCloser, int, error) {
+	cmdAttempt := func(authConfig cliconfig.AuthConfig) (io.ReadCloser, int, error) {
+		buf, err := json.Marshal(authConfig)
+		if err != nil {
+			return nil, -1, err
+		}
+		registryAuthHeader := []string{
+			base64.URLEncoding.EncodeToString(buf),
+		}
+
+		// begin the request
+		body, hdr, statusCode, err := cli.clientRequest(method, path, in, map[string][]string{
+			"X-Registry-Auth": registryAuthHeader,
+		})
+		if err == nil && out != nil {
+			// If we are streaming output, complete the stream since
+			// errors may not appear until later.
+			err = cli.streamBody(body, hdr.Get("Content-Type"), true, out, nil)
+		}
+		if err != nil {
+			// Since errors in a stream appear after status 200 has been written,
+			// we may need to change the status code.
+			if strings.Contains(err.Error(), "Authentication is required") ||
+				strings.Contains(err.Error(), "Status 401") ||
+				strings.Contains(err.Error(), "status code 401") {
+				statusCode = http.StatusUnauthorized
+			}
+		}
+		return body, statusCode, err
+	}
+
+	// Resolve the Auth config relevant for this server
+	authConfig := registry.ResolveAuthConfig(cli.configFile, index)
+	body, statusCode, err := cmdAttempt(authConfig)
+	if statusCode == http.StatusUnauthorized {
+		fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
+		if err = cli.CmdLogin(index.GetAuthConfigKey()); err != nil {
+			return nil, -1, err
+		}
+		authConfig = registry.ResolveAuthConfig(cli.configFile, index)
+		return cmdAttempt(authConfig)
+	}
+	return body, statusCode, err
+}
+
+func (cli *DockerCli) call(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
+	params, err := cli.encodeData(data)
+	if err != nil {
+		return nil, nil, -1, err
+	}
+
+	if data != nil {
+		if headers == nil {
+			headers = make(map[string][]string)
+		}
+		headers["Content-Type"] = []string{"application/json"}
+	}
+
+	body, hdr, statusCode, err := cli.clientRequest(method, path, params, headers)
+	return body, hdr, statusCode, err
+}
+
+type streamOpts struct {
+	rawTerminal bool
+	in          io.Reader
+	out         io.Writer
+	err         io.Writer
+	headers     map[string][]string
+}
+
+func (cli *DockerCli) stream(method, path string, opts *streamOpts) error {
+	body, hdr, _, err := cli.clientRequest(method, path, opts.in, opts.headers)
+	if err != nil {
+		return err
+	}
+	return cli.streamBody(body, hdr.Get("Content-Type"), opts.rawTerminal, opts.out, opts.err)
+}
+
+func (cli *DockerCli) streamBody(body io.ReadCloser, contentType string, rawTerminal bool, stdout, stderr io.Writer) error {
+	defer body.Close()
+
+	if api.MatchesContentType(contentType, "application/json") {
+		return jsonmessage.DisplayJSONMessagesStream(body, stdout, cli.outFd, cli.isTerminalOut)
+	}
+	if stdout != nil || stderr != nil {
+		// When TTY is ON, use regular copy
+		var err error
+		if rawTerminal {
+			_, err = io.Copy(stdout, body)
+		} else {
+			_, err = stdcopy.StdCopy(stdout, stderr, body)
+		}
+		logrus.Debugf("[stream] End of stdout")
+		return err
+	}
+	return nil
+}
+
+func (cli *DockerCli) resizeTty(id string, isExec bool) {
+	height, width := cli.getTtySize()
+	if height == 0 && width == 0 {
+		return
+	}
+	v := url.Values{}
+	v.Set("h", strconv.Itoa(height))
+	v.Set("w", strconv.Itoa(width))
+
+	path := ""
+	if !isExec {
+		path = "/containers/" + id + "/resize?"
+	} else {
+		path = "/exec/" + id + "/resize?"
+	}
+
+	if _, _, err := readBody(cli.call("POST", path+v.Encode(), nil, nil)); err != nil {
+		logrus.Debugf("Error resize: %s", err)
+	}
+}
+
+func waitForExit(cli *DockerCli, containerID string) (int, error) {
+	stream, _, _, err := cli.call("POST", "/containers/"+containerID+"/wait", nil, nil)
+	if err != nil {
+		return -1, err
+	}
+
+	var res types.ContainerWaitResponse
+	if err := json.NewDecoder(stream).Decode(&res); err != nil {
+		return -1, err
+	}
+
+	return res.StatusCode, nil
+}
+
+// getExitCode perform an inspect on the container. It returns
+// the running state and the exit code.
+func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
+	stream, _, _, err := cli.call("GET", "/containers/"+containerID+"/json", nil, nil)
+	if err != nil {
+		// If we can't connect, then the daemon probably died.
+		if err != errConnectionRefused {
+			return false, -1, err
+		}
+		return false, -1, nil
+	}
+
+	var c types.ContainerJSON
+	if err := json.NewDecoder(stream).Decode(&c); err != nil {
+		return false, -1, err
+	}
+
+	return c.State.Running, c.State.ExitCode, nil
+}
+
+// getExecExitCode perform an inspect on the exec command. It returns
+// the running state and the exit code.
+func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
+	stream, _, _, err := cli.call("GET", "/exec/"+execID+"/json", nil, nil)
+	if err != nil {
+		// If we can't connect, then the daemon probably died.
+		if err != errConnectionRefused {
+			return false, -1, err
+		}
+		return false, -1, nil
+	}
+
+	//TODO: Should we reconsider having a type in api/types?
+	//this is a response to exex/id/json not container
+	var c struct {
+		Running  bool
+		ExitCode int
+	}
+
+	if err := json.NewDecoder(stream).Decode(&c); err != nil {
+		return false, -1, err
+	}
+
+	return c.Running, c.ExitCode, nil
+}
+
+func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
+	cli.resizeTty(id, isExec)
+
+	if runtime.GOOS == "windows" {
+		go func() {
+			prevH, prevW := cli.getTtySize()
+			for {
+				time.Sleep(time.Millisecond * 250)
+				h, w := cli.getTtySize()
+
+				if prevW != w || prevH != h {
+					cli.resizeTty(id, isExec)
+				}
+				prevH = h
+				prevW = w
+			}
+		}()
+	} else {
+		sigchan := make(chan os.Signal, 1)
+		gosignal.Notify(sigchan, signal.SIGWINCH)
+		go func() {
+			for range sigchan {
+				cli.resizeTty(id, isExec)
+			}
+		}()
+	}
+	return nil
+}
+
+func (cli *DockerCli) getTtySize() (int, int) {
+	if !cli.isTerminalOut {
+		return 0, 0
+	}
+	ws, err := term.GetWinsize(cli.outFd)
+	if err != nil {
+		logrus.Debugf("Error getting size: %s", err)
+		if ws == nil {
+			return 0, 0
+		}
+	}
+	return int(ws.Height), int(ws.Width)
+}
+
+func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) {
+	if stream != nil {
+		defer stream.Close()
+	}
+	if err != nil {
+		return nil, statusCode, err
+	}
+	body, err := ioutil.ReadAll(stream)
+	if err != nil {
+		return nil, -1, err
+	}
+	return body, statusCode, nil
+}

+ 61 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/version.go

@@ -0,0 +1,61 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"runtime"
+
+	"github.com/docker/docker/api"
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/autogen/dockerversion"
+	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/utils"
+)
+
+// CmdVersion shows Docker version information.
+//
+// Available version information is shown for: client Docker version, client API version, client Go version, client Git commit, client OS/Arch, server Docker version, server API version, server Go version, server Git commit, and server OS/Arch.
+//
+// Usage: docker version
+func (cli *DockerCli) CmdVersion(args ...string) error {
+	cmd := cli.Subcmd("version", "", "Show the Docker version information.", true)
+	cmd.Require(flag.Exact, 0)
+
+	cmd.ParseFlags(args, true)
+
+	if dockerversion.VERSION != "" {
+		fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
+	}
+	fmt.Fprintf(cli.out, "Client API version: %s\n", api.APIVERSION)
+	fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version())
+	if dockerversion.GITCOMMIT != "" {
+		fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
+	}
+	fmt.Fprintf(cli.out, "OS/Arch (client): %s/%s\n", runtime.GOOS, runtime.GOARCH)
+	if utils.ExperimentalBuild() {
+		fmt.Fprintf(cli.out, "Experimental (client): true\n")
+	}
+
+	stream, _, _, err := cli.call("GET", "/version", nil, nil)
+	if err != nil {
+		return err
+	}
+
+	var v types.Version
+	if err := json.NewDecoder(stream).Decode(&v); err != nil {
+		fmt.Fprintf(cli.err, "Error reading remote version: %s\n", err)
+		return err
+	}
+
+	fmt.Fprintf(cli.out, "Server version: %s\n", v.Version)
+	if v.ApiVersion != "" {
+		fmt.Fprintf(cli.out, "Server API version: %s\n", v.ApiVersion)
+	}
+	fmt.Fprintf(cli.out, "Go version (server): %s\n", v.GoVersion)
+	fmt.Fprintf(cli.out, "Git commit (server): %s\n", v.GitCommit)
+	fmt.Fprintf(cli.out, "OS/Arch (server): %s/%s\n", v.Os, v.Arch)
+	if v.Experimental {
+		fmt.Fprintf(cli.out, "Experimental (server): true\n")
+	}
+	return nil
+}

+ 34 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/api/client/wait.go

@@ -0,0 +1,34 @@
+package client
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdWait blocks until a container stops, then prints its exit code.
+//
+// If more than one container is specified, this will wait synchronously on each container.
+//
+// Usage: docker wait CONTAINER [CONTAINER...]
+func (cli *DockerCli) CmdWait(args ...string) error {
+	cmd := cli.Subcmd("wait", "CONTAINER [CONTAINER...]", "Block until a container stops, then print its exit code.", true)
+	cmd.Require(flag.Min, 1)
+
+	cmd.ParseFlags(args, true)
+
+	var errNames []string
+	for _, name := range cmd.Args() {
+		status, err := waitForExit(cli, name)
+		if err != nil {
+			fmt.Fprintf(cli.err, "%s\n", err)
+			errNames = append(errNames, name)
+		} else {
+			fmt.Fprintf(cli.out, "%d\n", status)
+		}
+	}
+	if len(errNames) > 0 {
+		return fmt.Errorf("Error: failed to wait containers: %v", errNames)
+	}
+	return nil
+}

+ 14 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/ioutils/fmt.go

@@ -0,0 +1,14 @@
+package ioutils
+
+import (
+	"fmt"
+	"io"
+)
+
+// FprintfIfNotEmpty prints the string value if it's not empty
+func FprintfIfNotEmpty(w io.Writer, format, value string) (int, error) {
+	if value != "" {
+		return fmt.Fprintf(w, format, value)
+	}
+	return 0, nil
+}

+ 17 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/ioutils/fmt_test.go

@@ -0,0 +1,17 @@
+package ioutils
+
+import "testing"
+
+func TestFprintfIfNotEmpty(t *testing.T) {
+	wc := NewWriteCounter(&NopWriter{})
+	n, _ := FprintfIfNotEmpty(wc, "foo%s", "")
+
+	if wc.Count != 0 || n != 0 {
+		t.Errorf("Wrong count: %v vs. %v vs. 0", wc.Count, n)
+	}
+
+	n, _ = FprintfIfNotEmpty(wc, "foo%s", "bar")
+	if wc.Count != 6 || n != 6 {
+		t.Errorf("Wrong count: %v vs. %v vs. 6", wc.Count, n)
+	}
+}

+ 1 - 2
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/ioutils/readers_test.go

@@ -43,10 +43,9 @@ func TestReaderErrWrapperReadOnError(t *testing.T) {
 }
 }
 
 
 func TestReaderErrWrapperRead(t *testing.T) {
 func TestReaderErrWrapperRead(t *testing.T) {
-	called := false
 	reader := strings.NewReader("a string reader.")
 	reader := strings.NewReader("a string reader.")
 	wrapper := NewReaderErrWrapper(reader, func() {
 	wrapper := NewReaderErrWrapper(reader, func() {
-		called = true // Should not be called
+		t.Fatalf("readErrWrapper should not have called the anonymous function on failure")
 	})
 	})
 	// Read 20 byte (should be ok with the string above)
 	// Read 20 byte (should be ok with the string above)
 	num, err := wrapper.Read(make([]byte, 20))
 	num, err := wrapper.Read(make([]byte, 20))

+ 22 - 7
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/flag.go

@@ -289,7 +289,8 @@ type FlagSet struct {
 	// Usage is the function called when an error occurs while parsing flags.
 	// Usage is the function called when an error occurs while parsing flags.
 	// The field is a function (not a method) that may be changed to point to
 	// The field is a function (not a method) that may be changed to point to
 	// a custom error handler.
 	// a custom error handler.
-	Usage func()
+	Usage      func()
+	ShortUsage func()
 
 
 	name             string
 	name             string
 	parsed           bool
 	parsed           bool
@@ -511,6 +512,12 @@ func (f *FlagSet) PrintDefaults() {
 	if runtime.GOOS != "windows" && home == "/" {
 	if runtime.GOOS != "windows" && home == "/" {
 		home = ""
 		home = ""
 	}
 	}
+
+	// Add a blank line between cmd description and list of options
+	if f.FlagCount() > 0 {
+		fmt.Fprintln(writer, "")
+	}
+
 	f.VisitAll(func(flag *Flag) {
 	f.VisitAll(func(flag *Flag) {
 		format := "  -%s=%s"
 		format := "  -%s=%s"
 		names := []string{}
 		names := []string{}
@@ -560,10 +567,16 @@ func defaultUsage(f *FlagSet) {
 // Usage prints to standard error a usage message documenting all defined command-line flags.
 // Usage prints to standard error a usage message documenting all defined command-line flags.
 // The function is a variable that may be changed to point to a custom function.
 // The function is a variable that may be changed to point to a custom function.
 var Usage = func() {
 var Usage = func() {
-	fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0])
+	fmt.Fprintf(CommandLine.Out(), "Usage of %s:\n", os.Args[0])
 	PrintDefaults()
 	PrintDefaults()
 }
 }
 
 
+// Usage prints to standard error a usage message documenting the standard command layout
+// The function is a variable that may be changed to point to a custom function.
+var ShortUsage = func() {
+	fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0])
+}
+
 // FlagCount returns the number of flags that have been defined.
 // FlagCount returns the number of flags that have been defined.
 func (f *FlagSet) FlagCount() int { return len(sortFlags(f.formal)) }
 func (f *FlagSet) FlagCount() int { return len(sortFlags(f.formal)) }
 
 
@@ -1067,12 +1080,15 @@ func (cmd *FlagSet) ParseFlags(args []string, withHelp bool) error {
 		return err
 		return err
 	}
 	}
 	if help != nil && *help {
 	if help != nil && *help {
+		cmd.SetOutput(os.Stdout)
 		cmd.Usage()
 		cmd.Usage()
-		// just in case Usage does not exit
 		os.Exit(0)
 		os.Exit(0)
 	}
 	}
 	if str := cmd.CheckArgs(); str != "" {
 	if str := cmd.CheckArgs(); str != "" {
+		cmd.SetOutput(os.Stderr)
 		cmd.ReportError(str, withHelp)
 		cmd.ReportError(str, withHelp)
+		cmd.ShortUsage()
+		os.Exit(1)
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -1080,13 +1096,12 @@ func (cmd *FlagSet) ParseFlags(args []string, withHelp bool) error {
 func (cmd *FlagSet) ReportError(str string, withHelp bool) {
 func (cmd *FlagSet) ReportError(str string, withHelp bool) {
 	if withHelp {
 	if withHelp {
 		if os.Args[0] == cmd.Name() {
 		if os.Args[0] == cmd.Name() {
-			str += ". See '" + os.Args[0] + " --help'"
+			str += ".\nSee '" + os.Args[0] + " --help'"
 		} else {
 		} else {
-			str += ". See '" + os.Args[0] + " " + cmd.Name() + " --help'"
+			str += ".\nSee '" + os.Args[0] + " " + cmd.Name() + " --help'"
 		}
 		}
 	}
 	}
-	fmt.Fprintf(cmd.Out(), "docker: %s\n", str)
-	os.Exit(1)
+	fmt.Fprintf(cmd.Out(), "docker: %s.\n", str)
 }
 }
 
 
 // Parsed reports whether f.Parse has been called.
 // Parsed reports whether f.Parse has been called.

+ 18 - 5
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/plugins/client.go

@@ -31,6 +31,10 @@ type Client struct {
 }
 }
 
 
 func (c *Client) Call(serviceMethod string, args interface{}, ret interface{}) error {
 func (c *Client) Call(serviceMethod string, args interface{}, ret interface{}) error {
+	return c.callWithRetry(serviceMethod, args, ret, true)
+}
+
+func (c *Client) callWithRetry(serviceMethod string, args interface{}, ret interface{}, retry bool) error {
 	var buf bytes.Buffer
 	var buf bytes.Buffer
 	if err := json.NewEncoder(&buf).Encode(args); err != nil {
 	if err := json.NewEncoder(&buf).Encode(args); err != nil {
 		return err
 		return err
@@ -50,20 +54,25 @@ func (c *Client) Call(serviceMethod string, args interface{}, ret interface{}) e
 	for {
 	for {
 		resp, err := c.http.Do(req)
 		resp, err := c.http.Do(req)
 		if err != nil {
 		if err != nil {
+			if !retry {
+				return err
+			}
+
 			timeOff := backoff(retries)
 			timeOff := backoff(retries)
-			if timeOff+time.Since(start) > defaultTimeOut {
+			if abort(start, timeOff) {
 				return err
 				return err
 			}
 			}
 			retries++
 			retries++
-			logrus.Warn("Unable to connect to plugin: %s, retrying in %ds\n", c.addr, timeOff)
+			logrus.Warnf("Unable to connect to plugin: %s, retrying in %v", c.addr, timeOff)
 			time.Sleep(timeOff)
 			time.Sleep(timeOff)
 			continue
 			continue
 		}
 		}
 
 
+		defer resp.Body.Close()
 		if resp.StatusCode != http.StatusOK {
 		if resp.StatusCode != http.StatusOK {
 			remoteErr, err := ioutil.ReadAll(resp.Body)
 			remoteErr, err := ioutil.ReadAll(resp.Body)
 			if err != nil {
 			if err != nil {
-				return nil
+				return fmt.Errorf("Plugin Error: %s", err)
 			}
 			}
 			return fmt.Errorf("Plugin Error: %s", remoteErr)
 			return fmt.Errorf("Plugin Error: %s", remoteErr)
 		}
 		}
@@ -73,7 +82,7 @@ func (c *Client) Call(serviceMethod string, args interface{}, ret interface{}) e
 }
 }
 
 
 func backoff(retries int) time.Duration {
 func backoff(retries int) time.Duration {
-	b, max := float64(1), float64(defaultTimeOut)
+	b, max := 1, defaultTimeOut
 	for b < max && retries > 0 {
 	for b < max && retries > 0 {
 		b *= 2
 		b *= 2
 		retries--
 		retries--
@@ -81,7 +90,11 @@ func backoff(retries int) time.Duration {
 	if b > max {
 	if b > max {
 		b = max
 		b = max
 	}
 	}
-	return time.Duration(b)
+	return time.Duration(b) * time.Second
+}
+
+func abort(start time.Time, timeOff time.Duration) bool {
+	return timeOff+time.Since(start) > time.Duration(defaultTimeOut)*time.Second
 }
 }
 
 
 func configureTCPTransport(tr *http.Transport, proto, addr string) {
 func configureTCPTransport(tr *http.Transport, proto, addr string) {

+ 43 - 1
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/plugins/client_test.go

@@ -6,6 +6,7 @@ import (
 	"net/http/httptest"
 	"net/http/httptest"
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
+	"time"
 )
 )
 
 
 var (
 var (
@@ -27,7 +28,7 @@ func teardownRemotePluginServer() {
 
 
 func TestFailedConnection(t *testing.T) {
 func TestFailedConnection(t *testing.T) {
 	c := NewClient("tcp://127.0.0.1:1")
 	c := NewClient("tcp://127.0.0.1:1")
-	err := c.Call("Service.Method", nil, nil)
+	err := c.callWithRetry("Service.Method", nil, nil, false)
 	if err == nil {
 	if err == nil {
 		t.Fatal("Unexpected successful connection")
 		t.Fatal("Unexpected successful connection")
 	}
 	}
@@ -61,3 +62,44 @@ func TestEchoInputOutput(t *testing.T) {
 		t.Fatalf("Expected %v, was %v\n", m, output)
 		t.Fatalf("Expected %v, was %v\n", m, output)
 	}
 	}
 }
 }
+
+func TestBackoff(t *testing.T) {
+	cases := []struct {
+		retries    int
+		expTimeOff time.Duration
+	}{
+		{0, time.Duration(1)},
+		{1, time.Duration(2)},
+		{2, time.Duration(4)},
+		{4, time.Duration(16)},
+		{6, time.Duration(30)},
+		{10, time.Duration(30)},
+	}
+
+	for _, c := range cases {
+		s := c.expTimeOff * time.Second
+		if d := backoff(c.retries); d != s {
+			t.Fatalf("Retry %v, expected %v, was %v\n", c.retries, s, d)
+		}
+	}
+}
+
+func TestAbortRetry(t *testing.T) {
+	cases := []struct {
+		timeOff  time.Duration
+		expAbort bool
+	}{
+		{time.Duration(1), false},
+		{time.Duration(2), false},
+		{time.Duration(10), false},
+		{time.Duration(30), true},
+		{time.Duration(40), true},
+	}
+
+	for _, c := range cases {
+		s := c.timeOff * time.Second
+		if a := abort(time.Now(), s); a != c.expAbort {
+			t.Fatalf("Duration %v, expected %v, was %v\n", c.timeOff, s, a)
+		}
+	}
+}

+ 1 - 5
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/plugins/discovery_test.go

@@ -5,7 +5,6 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"net"
 	"net"
 	"os"
 	"os"
-	"path"
 	"path/filepath"
 	"path/filepath"
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
@@ -66,6 +65,7 @@ func TestFileSpecPlugin(t *testing.T) {
 	if err != nil {
 	if err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
+	defer os.RemoveAll(tmpdir)
 
 
 	cases := []struct {
 	cases := []struct {
 		path string
 		path string
@@ -79,9 +79,6 @@ func TestFileSpecPlugin(t *testing.T) {
 	}
 	}
 
 
 	for _, c := range cases {
 	for _, c := range cases {
-		if err = os.MkdirAll(path.Dir(c.path), 0755); err != nil {
-			t.Fatal(err)
-		}
 		if err = ioutil.WriteFile(c.path, []byte(c.addr), 0644); err != nil {
 		if err = ioutil.WriteFile(c.path, []byte(c.addr), 0644); err != nil {
 			t.Fatal(err)
 			t.Fatal(err)
 		}
 		}
@@ -103,6 +100,5 @@ func TestFileSpecPlugin(t *testing.T) {
 		if p.Addr != c.addr {
 		if p.Addr != c.addr {
 			t.Fatalf("Expected plugin addr `%s`, got %s\n", c.addr, p.Addr)
 			t.Fatalf("Expected plugin addr `%s`, got %s\n", c.addr, p.Addr)
 		}
 		}
-		os.Remove(c.path)
 	}
 	}
 }
 }

+ 3 - 2
libnetwork/client/client.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
+	"net/http"
 	"reflect"
 	"reflect"
 	"strings"
 	"strings"
 
 
@@ -11,7 +12,7 @@ import (
 )
 )
 
 
 // CallFunc provides environment specific call utility to invoke backend functions from UI
 // CallFunc provides environment specific call utility to invoke backend functions from UI
-type CallFunc func(string, string, interface{}, map[string][]string) (io.ReadCloser, int, error)
+type CallFunc func(string, string, interface{}, map[string][]string) (io.ReadCloser, http.Header, int, error)
 
 
 // NetworkCli is the UI object for network subcmds
 // NetworkCli is the UI object for network subcmds
 type NetworkCli struct {
 type NetworkCli struct {
@@ -96,7 +97,7 @@ func (cli *NetworkCli) Subcmd(chain, name, signature, description string, exitOn
 	return flags
 	return flags
 }
 }
 
 
-func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, error) {
+func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) {
 	if stream != nil {
 	if stream != nil {
 		defer stream.Close()
 		defer stream.Close()
 	}
 	}

+ 7 - 4
libnetwork/client/client_test.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
+	"net/http"
 	"os"
 	"os"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
@@ -24,7 +25,7 @@ func TestMain(m *testing.M) {
 	os.Exit(m.Run())
 	os.Exit(m.Run())
 }
 }
 
 
-var callbackFunc func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error)
+var callbackFunc func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error)
 var mockNwJSON, mockNwListJSON, mockServiceJSON, mockServiceListJSON []byte
 var mockNwJSON, mockNwListJSON, mockServiceJSON, mockServiceListJSON []byte
 var mockNwName = "test"
 var mockNwName = "test"
 var mockNwID = "2a3456789"
 var mockNwID = "2a3456789"
@@ -45,7 +46,9 @@ func setupMockHTTPCallback() {
 	srvList = append(srvList, ep)
 	srvList = append(srvList, ep)
 	mockServiceListJSON, _ = json.Marshal(srvList)
 	mockServiceListJSON, _ = json.Marshal(srvList)
 
 
-	callbackFunc = func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+	dummyHTTPHdr := http.Header{}
+
+	callbackFunc = func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
 		var rsp string
 		var rsp string
 		switch method {
 		switch method {
 		case "GET":
 		case "GET":
@@ -74,7 +77,7 @@ func setupMockHTTPCallback() {
 			} else if strings.HasSuffix(path, "services/"+mockServiceID) {
 			} else if strings.HasSuffix(path, "services/"+mockServiceID) {
 				rsp = string(mockServiceJSON)
 				rsp = string(mockServiceJSON)
 			} else if strings.Contains(path, "containers") {
 			} else if strings.Contains(path, "containers") {
-				return nopCloser{bytes.NewBufferString("")}, 400, fmt.Errorf("Bad Request")
+				return nopCloser{bytes.NewBufferString("")}, dummyHTTPHdr, 400, fmt.Errorf("Bad Request")
 			}
 			}
 		case "POST":
 		case "POST":
 			var data []byte
 			var data []byte
@@ -90,7 +93,7 @@ func setupMockHTTPCallback() {
 		case "DELETE":
 		case "DELETE":
 			rsp = ""
 			rsp = ""
 		}
 		}
-		return nopCloser{bytes.NewBufferString(rsp)}, 200, nil
+		return nopCloser{bytes.NewBufferString(rsp)}, dummyHTTPHdr, 200, nil
 	}
 	}
 }
 }
 
 

+ 7 - 7
libnetwork/cmd/dnet/dnet.go

@@ -218,16 +218,16 @@ func newDnetConnection(val string) (*dnetConnection, error) {
 	return &dnetConnection{protoAddrParts[0], protoAddrParts[1]}, nil
 	return &dnetConnection{protoAddrParts[0], protoAddrParts[1]}, nil
 }
 }
 
 
-func (d *dnetConnection) httpCall(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+func (d *dnetConnection) httpCall(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
 	var in io.Reader
 	var in io.Reader
 	in, err := encodeData(data)
 	in, err := encodeData(data)
 	if err != nil {
 	if err != nil {
-		return nil, -1, err
+		return nil, nil, -1, err
 	}
 	}
 
 
 	req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in)
 	req, err := http.NewRequest(method, fmt.Sprintf("%s", path), in)
 	if err != nil {
 	if err != nil {
-		return nil, -1, err
+		return nil, nil, -1, err
 	}
 	}
 
 
 	setupRequestHeaders(method, data, req, headers)
 	setupRequestHeaders(method, data, req, headers)
@@ -242,18 +242,18 @@ func (d *dnetConnection) httpCall(method, path string, data interface{}, headers
 		statusCode = resp.StatusCode
 		statusCode = resp.StatusCode
 	}
 	}
 	if err != nil {
 	if err != nil {
-		return nil, statusCode, fmt.Errorf("error when trying to connect: %v", err)
+		return nil, nil, statusCode, fmt.Errorf("error when trying to connect: %v", err)
 	}
 	}
 
 
 	if statusCode < 200 || statusCode >= 400 {
 	if statusCode < 200 || statusCode >= 400 {
 		body, err := ioutil.ReadAll(resp.Body)
 		body, err := ioutil.ReadAll(resp.Body)
 		if err != nil {
 		if err != nil {
-			return nil, statusCode, err
+			return nil, nil, statusCode, err
 		}
 		}
-		return nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body))
+		return nil, nil, statusCode, fmt.Errorf("error : %s", bytes.TrimSpace(body))
 	}
 	}
 
 
-	return resp.Body, statusCode, nil
+	return resp.Body, resp.Header, statusCode, nil
 }
 }
 
 
 func setupRequestHeaders(method string, data interface{}, req *http.Request, headers map[string][]string) {
 func setupRequestHeaders(method string, data interface{}, req *http.Request, headers map[string][]string) {