diff --git a/vendor/github.com/containers/image/copy/compression.go b/vendor/github.com/containers/image/copy/compression.go
new file mode 100644
index 00000000..820c7e99
--- /dev/null
+++ b/vendor/github.com/containers/image/copy/compression.go
@@ -0,0 +1,61 @@
+package copy
+
+import (
+	"bytes"
+	"compress/bzip2"
+	"compress/gzip"
+	"errors"
+	"io"
+
+	"github.com/Sirupsen/logrus"
+)
+
+// decompressorFunc, given a compressed stream, returns the decompressed stream.
+type decompressorFunc func(io.Reader) (io.Reader, error)
+
+func gzipDecompressor(r io.Reader) (io.Reader, error) {
+	return gzip.NewReader(r)
+}
+func bzip2Decompressor(r io.Reader) (io.Reader, error) {
+	return bzip2.NewReader(r), nil
+}
+func xzDecompressor(r io.Reader) (io.Reader, error) {
+	return nil, errors.New("Decompressing xz streams is not supported")
+}
+
+// compressionAlgos is an internal implementation detail of detectCompression
+var compressionAlgos = map[string]struct {
+	prefix       []byte
+	decompressor decompressorFunc
+}{
+	"gzip":  {[]byte{0x1F, 0x8B, 0x08}, gzipDecompressor},                 // gzip (RFC 1952)
+	"bzip2": {[]byte{0x42, 0x5A, 0x68}, bzip2Decompressor},                // bzip2 (decompress.c:BZ2_decompress)
+	"xz":    {[]byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, xzDecompressor}, // xz (/usr/share/doc/xz/xz-file-format.txt)
+}
+
+// detectCompression returns a decompressorFunc if the input is recognized as a compressed format, nil otherwise.
+// Because it consumes the start of input, other consumers must use the returned io.Reader instead to also read from the beginning.
+func detectCompression(input io.Reader) (decompressorFunc, io.Reader, error) {
+	buffer := [8]byte{}
+
+	n, err := io.ReadAtLeast(input, buffer[:], len(buffer))
+	if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
+		// This is a “real” error. We could just ignore it this time, process the data we have, and hope that the source will report the same error again.
+		// Instead, fail immediately with the original error cause instead of a possibly secondary/misleading error returned later.
+		return nil, nil, err
+	}
+
+	var decompressor decompressorFunc
+	for name, algo := range compressionAlgos {
+		if bytes.HasPrefix(buffer[:n], algo.prefix) {
+			logrus.Debugf("Detected compression format %s", name)
+			decompressor = algo.decompressor
+			break
+		}
+	}
+	if decompressor == nil {
+		logrus.Debugf("No compression detected")
+	}
+
+	return decompressor, io.MultiReader(bytes.NewReader(buffer[:n]), input), nil
+}
diff --git a/vendor/github.com/containers/image/copy/copy.go b/vendor/github.com/containers/image/copy/copy.go
index 647e97b4..e3aabd75 100644
--- a/vendor/github.com/containers/image/copy/copy.go
+++ b/vendor/github.com/containers/image/copy/copy.go
@@ -18,11 +18,17 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/containers/image/image"
+	"github.com/containers/image/manifest"
 	"github.com/containers/image/signature"
 	"github.com/containers/image/transports"
 	"github.com/containers/image/types"
 )
 
+// preferredManifestMIMETypes lists manifest MIME types in order of our preference, if we can't use the original manifest and need to convert.
+// Prefer v2s2 to v2s1 because v2s2 does not need to be changed when uploading to a different location.
+// Include v2s1 signed but not v2s1 unsigned, because docker/distribution requires a signature even if the unsigned MIME type is used.
+var preferredManifestMIMETypes = []string{manifest.DockerV2Schema2MediaType, manifest.DockerV2Schema1SignedMediaType}
+
 // supportedDigests lists the supported blob digest types.
 var supportedDigests = map[string]func() hash.Hash{
 	"sha256": sha256.New,
@@ -104,8 +110,9 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
 		return fmt.Errorf("Error initializing destination %s: %v", transports.ImageName(destRef), err)
 	}
 	defer dest.Close()
+	destSupportedManifestMIMETypes := dest.SupportedManifestMIMETypes()
 
-	rawSource, err := srcRef.NewImageSource(ctx, dest.SupportedManifestMIMETypes())
+	rawSource, err := srcRef.NewImageSource(ctx, destSupportedManifestMIMETypes)
 	if err != nil {
 		return fmt.Errorf("Error initializing source %s: %v", transports.ImageName(srcRef), err)
 	}
@@ -148,49 +155,27 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
 			return fmt.Errorf("Can not copy signatures: %v", err)
 		}
 	}
+
 	canModifyManifest := len(sigs) == 0
-
-	srcConfigInfo := src.ConfigInfo()
-	if srcConfigInfo.Digest != "" {
-		writeReport("Uploading blob %s\n", srcConfigInfo.Digest)
-		destConfigInfo, err := copyBlob(dest, rawSource, srcConfigInfo, false, reportWriter)
-		if err != nil {
-			return err
-		}
-		if destConfigInfo.Digest != srcConfigInfo.Digest {
-			return fmt.Errorf("Internal error: copying uncompressed config blob %s changed digest to %s", srcConfigInfo.Digest, destConfigInfo.Digest)
-		}
-	}
-
-	srcLayerInfos := src.LayerInfos()
-	destLayerInfos := []types.BlobInfo{}
-	copiedLayers := map[string]types.BlobInfo{}
-	for _, srcLayer := range srcLayerInfos {
-		destLayer, ok := copiedLayers[srcLayer.Digest]
-		if !ok {
-			writeReport("Uploading blob %s\n", srcLayer.Digest)
-			destLayer, err = copyBlob(dest, rawSource, srcLayer, canModifyManifest, reportWriter)
-			if err != nil {
-				return err
-			}
-			copiedLayers[srcLayer.Digest] = destLayer
-		}
-		destLayerInfos = append(destLayerInfos, destLayer)
-	}
-
 	manifestUpdates := types.ManifestUpdateOptions{}
-	if layerDigestsDiffer(srcLayerInfos, destLayerInfos) {
-		manifestUpdates.LayerInfos = destLayerInfos
+
+	if err := determineManifestConversion(&manifestUpdates, src, destSupportedManifestMIMETypes, canModifyManifest); err != nil {
+		return err
+	}
+
+	if err := copyLayers(&manifestUpdates, dest, src, rawSource, canModifyManifest, reportWriter); err != nil {
+		return err
 	}
 
 	pendingImage := src
-	if !reflect.DeepEqual(manifestUpdates, types.ManifestUpdateOptions{}) {
+	if !reflect.DeepEqual(manifestUpdates, types.ManifestUpdateOptions{InformationOnly: manifestUpdates.InformationOnly}) {
 		if !canModifyManifest {
 			return fmt.Errorf("Internal error: copy needs an updated manifest but that was known to be forbidden")
 		}
+		manifestUpdates.InformationOnly.Destination = dest
 		pendingImage, err = src.UpdatedImage(manifestUpdates)
 		if err != nil {
-			return fmt.Errorf("Error creating an updated manifest: %v", err)
+			return fmt.Errorf("Error creating an updated image manifest: %v", err)
 		}
 	}
 	manifest, _, err := pendingImage.Manifest()
@@ -198,6 +183,10 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
 		return fmt.Errorf("Error reading manifest: %v", err)
 	}
 
+	if err := copyConfig(dest, pendingImage, reportWriter); err != nil {
+		return err
+	}
+
 	if options != nil && options.SignBy != "" {
 		mech, err := signature.NewGPGSigningMechanism()
 		if err != nil {
@@ -216,7 +205,7 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
 		sigs = append(sigs, newSig)
 	}
 
-	writeReport("Uploading manifest to image destination\n")
+	writeReport("Writing manifest to image destination\n")
 	if err := dest.PutManifest(manifest); err != nil {
 		return fmt.Errorf("Error writing manifest: %v", err)
 	}
@@ -233,6 +222,45 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
 	return nil
 }
 
+// copyLayers copies layers from src/rawSource to dest, using and updating manifestUpdates if necessary and canModifyManifest.
+// If src.UpdatedImageNeedsLayerDiffIDs(manifestUpdates) will be true, it needs to be true by the time this function is called.
+func copyLayers(manifestUpdates *types.ManifestUpdateOptions, dest types.ImageDestination, src types.Image, rawSource types.ImageSource,
+	canModifyManifest bool, reportWriter io.Writer) error {
+	type copiedLayer struct {
+		blobInfo types.BlobInfo
+		diffID   string
+	}
+
+	diffIDsAreNeeded := src.UpdatedImageNeedsLayerDiffIDs(*manifestUpdates)
+
+	srcInfos := src.LayerInfos()
+	destInfos := []types.BlobInfo{}
+	diffIDs := []string{}
+	copiedLayers := map[string]copiedLayer{}
+	for _, srcLayer := range srcInfos {
+		cl, ok := copiedLayers[srcLayer.Digest]
+		if !ok {
+			fmt.Fprintf(reportWriter, "Copying blob %s\n", srcLayer.Digest)
+			destInfo, diffID, err := copyLayer(dest, rawSource, srcLayer, diffIDsAreNeeded, canModifyManifest, reportWriter)
+			if err != nil {
+				return err
+			}
+			cl = copiedLayer{blobInfo: destInfo, diffID: diffID}
+			copiedLayers[srcLayer.Digest] = cl
+		}
+		destInfos = append(destInfos, cl.blobInfo)
+		diffIDs = append(diffIDs, cl.diffID)
+	}
+	manifestUpdates.InformationOnly.LayerInfos = destInfos
+	if diffIDsAreNeeded {
+		manifestUpdates.InformationOnly.LayerDiffIDs = diffIDs
+	}
+	if layerDigestsDiffer(srcInfos, destInfos) {
+		manifestUpdates.LayerInfos = destInfos
+	}
+	return nil
+}
+
 // layerDigestsDiffer return true iff the digests in a and b differ (ignoring sizes and possible other fields)
 func layerDigestsDiffer(a, b []types.BlobInfo) bool {
 	if len(a) != len(b) {
@@ -246,15 +274,136 @@ func layerDigestsDiffer(a, b []types.BlobInfo) bool {
 	return false
 }
 
-// copyBlob copies a blob with srcInfo (with known Digest and possibly known Size) in src to dest, perhaps compressing it if canCompress,
-// and returns a complete blobInfo of the copied blob.
-func copyBlob(dest types.ImageDestination, src types.ImageSource, srcInfo types.BlobInfo, canCompress bool, reportWriter io.Writer) (types.BlobInfo, error) {
+// copyConfig copies config.json, if any, from src to dest.
+func copyConfig(dest types.ImageDestination, src types.Image, reportWriter io.Writer) error {
+	srcInfo := src.ConfigInfo()
+	if srcInfo.Digest != "" {
+		fmt.Fprintf(reportWriter, "Copying config %s\n", srcInfo.Digest)
+		configBlob, err := src.ConfigBlob()
+		if err != nil {
+			return fmt.Errorf("Error reading config blob %s: %v", srcInfo.Digest, err)
+		}
+		destInfo, err := copyBlobFromStream(dest, bytes.NewReader(configBlob), srcInfo, nil, false, reportWriter)
+		if err != nil {
+			return err
+		}
+		if destInfo.Digest != srcInfo.Digest {
+			return fmt.Errorf("Internal error: copying uncompressed config blob %s changed digest to %s", srcInfo.Digest, destInfo.Digest)
+		}
+	}
+	return nil
+}
+
+// diffIDResult contains both a digest value and an error from diffIDComputationGoroutine.
+// We could also send the error through the pipeReader, but this more cleanly separates the copying of the layer and the DiffID computation.
+type diffIDResult struct {
+	digest string
+	err    error
+}
+
+// copyLayer copies a layer with srcInfo (with known Digest and possibly known Size) in src to dest, perhaps compressing it if canCompress,
+// and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded
+func copyLayer(dest types.ImageDestination, src types.ImageSource, srcInfo types.BlobInfo,
+	diffIDIsNeeded bool, canCompress bool, reportWriter io.Writer) (types.BlobInfo, string, error) {
 	srcStream, srcBlobSize, err := src.GetBlob(srcInfo.Digest) // We currently completely ignore srcInfo.Size throughout.
 	if err != nil {
-		return types.BlobInfo{}, fmt.Errorf("Error reading blob %s: %v", srcInfo.Digest, err)
+		return types.BlobInfo{}, "", fmt.Errorf("Error reading blob %s: %v", srcInfo.Digest, err)
 	}
 	defer srcStream.Close()
 
+	blobInfo, diffIDChan, err := copyLayerFromStream(dest, srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize},
+		diffIDIsNeeded, canCompress, reportWriter)
+	if err != nil {
+		return types.BlobInfo{}, "", err
+	}
+	var diffIDResult diffIDResult // = {digest:""}
+	if diffIDIsNeeded {
+		diffIDResult = <-diffIDChan
+		if diffIDResult.err != nil {
+			return types.BlobInfo{}, "", fmt.Errorf("Error computing layer DiffID: %v", diffIDResult.err)
+		}
+		logrus.Debugf("Computed DiffID %s for layer %s", diffIDResult.digest, srcInfo.Digest)
+	}
+	return blobInfo, diffIDResult.digest, nil
+}
+
+// copyLayerFromStream is an implementation detail of copyLayer; mostly providing a separate “defer” scope.
+// it copies a blob with srcInfo (with known Digest and possibly known Size) from srcStream to dest,
+// perhaps compressing the stream if canCompress,
+// and returns a complete blobInfo of the copied blob and perhaps a <-chan diffIDResult if diffIDIsNeeded, to be read by the caller.
+func copyLayerFromStream(dest types.ImageDestination, srcStream io.Reader, srcInfo types.BlobInfo,
+	diffIDIsNeeded bool, canCompress bool, reportWriter io.Writer) (types.BlobInfo, <-chan diffIDResult, error) {
+	var getDiffIDRecorder func(decompressorFunc) io.Writer // = nil
+	var diffIDChan chan diffIDResult
+
+	err := errors.New("Internal error: unexpected panic in copyLayer") // For pipeWriter.CloseWithError below
+	if diffIDIsNeeded {
+		diffIDChan = make(chan diffIDResult, 1) // Buffered, so that sending a value after this or our caller has failed and exited does not block.
+		pipeReader, pipeWriter := io.Pipe()
+		defer func() { // Note that this is not the same as {defer pipeWriter.CloseWithError(err)}; we need err to be evaluated lazily.
+			pipeWriter.CloseWithError(err) // CloseWithError(nil) is equivalent to Close()
+		}()
+
+		getDiffIDRecorder = func(decompressor decompressorFunc) io.Writer {
+			// If this fails, e.g. because we have exited and due to pipeWriter.CloseWithError() above further
+			// reading from the pipe has failed, we don’t really care.
+			// We only read from diffIDChan if the rest of the flow has succeeded, and when we do read from it,
+			// the return value includes an error indication, which we do check.
+			//
+			// If this gets never called, pipeReader will not be used anywhere, but pipeWriter will only be
+			// closed above, so we are happy enough with both pipeReader and pipeWriter to just get collected by GC.
+			go diffIDComputationGoroutine(diffIDChan, pipeReader, decompressor) // Closes pipeReader
+			return pipeWriter
+		}
+	}
+	blobInfo, err := copyBlobFromStream(dest, srcStream, srcInfo,
+		getDiffIDRecorder, canCompress, reportWriter) // Sets err to nil on success
+	return blobInfo, diffIDChan, err
+	// We need the defer … pipeWriter.CloseWithError() to happen HERE so that the caller can block on reading from diffIDChan
+}
+
+// diffIDComputationGoroutine reads all input from layerStream, uncompresses using decompressor if necessary, and sends its digest, and status, if any, to dest.
+func diffIDComputationGoroutine(dest chan<- diffIDResult, layerStream io.ReadCloser, decompressor decompressorFunc) {
+	result := diffIDResult{
+		digest: "",
+		err:    errors.New("Internal error: unexpected panic in diffIDComputationGoroutine"),
+	}
+	defer func() { dest <- result }()
+	defer layerStream.Close() // We do not care to bother the other end of the pipe with other failures; we send them to dest instead.
+
+	result.digest, result.err = computeDiffID(layerStream, decompressor)
+}
+
+// computeDiffID reads all input from layerStream, uncompresses it using decompressor if necessary, and returns its digest.
+func computeDiffID(stream io.Reader, decompressor decompressorFunc) (string, error) {
+	if decompressor != nil {
+		s, err := decompressor(stream)
+		if err != nil {
+			return "", err
+		}
+		stream = s
+	}
+
+	h := sha256.New()
+	_, err := io.Copy(h, stream)
+	if err != nil {
+		return "", err
+	}
+	hash := h.Sum(nil)
+	return "sha256:" + hex.EncodeToString(hash[:]), nil
+}
+
+// copyBlobFromStream copies a blob with srcInfo (with known Digest and possibly known Size) from srcStream to dest,
+// perhaps sending a copy to an io.Writer if getOriginalLayerCopyWriter != nil,
+// perhaps compressing it if canCompress,
+// and returns a complete blobInfo of the copied blob.
+func copyBlobFromStream(dest types.ImageDestination, srcStream io.Reader, srcInfo types.BlobInfo,
+	getOriginalLayerCopyWriter func(decompressor decompressorFunc) io.Writer, canCompress bool,
+	reportWriter io.Writer) (types.BlobInfo, error) {
+	// The copying happens through a pipeline of connected io.Readers.
+	// === Input: srcStream
+
+	// === Process input through digestingReader to validate against the expected digest.
 	// Be paranoid; in case PutBlob somehow managed to ignore an error from digestingReader,
 	// use a separate validation failure indicator.
 	// Note that we don't use a stronger "validationSucceeded" indicator, because
@@ -265,11 +414,16 @@ func copyBlob(dest types.ImageDestination, src types.ImageSource, srcInfo types.
 		return types.BlobInfo{}, fmt.Errorf("Error preparing to verify blob %s: %v", srcInfo.Digest, err)
 	}
 	var destStream io.Reader = digestingReader
-	isCompressed, destStream, err := isStreamCompressed(destStream) // We could skip this in some cases, but let's keep the code path uniform
+
+	// === Detect compression of the input stream.
+	// This requires us to “peek ahead” into the stream to read the initial part, which requires us to chain through another io.Reader returned by detectCompression.
+	decompressor, destStream, err := detectCompression(destStream) // We could skip this in some cases, but let's keep the code path uniform
 	if err != nil {
 		return types.BlobInfo{}, fmt.Errorf("Error reading blob %s: %v", srcInfo.Digest, err)
 	}
+	isCompressed := decompressor != nil
 
+	// === Report progress using a pb.Reader.
 	bar := pb.New(int(srcInfo.Size)).SetUnits(pb.U_BYTES)
 	bar.Output = reportWriter
 	bar.SetMaxWidth(80)
@@ -277,14 +431,20 @@ func copyBlob(dest types.ImageDestination, src types.ImageSource, srcInfo types.
 	bar.ShowPercent = false
 	bar.Start()
 	destStream = bar.NewProxyReader(destStream)
-
 	defer fmt.Fprint(reportWriter, "\n")
 
+	// === Send a copy of the original, uncompressed, stream, to a separate path if necessary.
+	var originalLayerReader io.Reader // DO NOT USE this other than to drain the input if no other consumer in the pipeline has done so.
+	if getOriginalLayerCopyWriter != nil {
+		destStream = io.TeeReader(destStream, getOriginalLayerCopyWriter(decompressor))
+		originalLayerReader = destStream
+	}
+
+	// === Compress the layer if it is uncompressed and compression is desired
 	var inputInfo types.BlobInfo
 	if !canCompress || isCompressed || !dest.ShouldCompressLayers() {
 		logrus.Debugf("Using original blob without modification")
-		inputInfo.Digest = srcInfo.Digest
-		inputInfo.Size = srcBlobSize
+		inputInfo = srcInfo
 	} else {
 		logrus.Debugf("Compressing blob on the fly")
 		pipeReader, pipeWriter := io.Pipe()
@@ -299,51 +459,31 @@ func copyBlob(dest types.ImageDestination, src types.ImageSource, srcInfo types.
 		inputInfo.Size = -1
 	}
 
+	// === Finally, send the layer stream to dest.
 	uploadedInfo, err := dest.PutBlob(destStream, inputInfo)
 	if err != nil {
 		return types.BlobInfo{}, fmt.Errorf("Error writing blob: %v", err)
 	}
-	if digestingReader.validationFailed { // Coverage: This should never happen.
-		return types.BlobInfo{}, fmt.Errorf("Internal error uploading blob %s, digest verification failed but was ignored", srcInfo.Digest)
-	}
-	if inputInfo.Digest != "" && uploadedInfo.Digest != inputInfo.Digest {
-		return types.BlobInfo{}, fmt.Errorf("Internal error uploading blob %s, blob with digest %s uploaded with digest %s", srcInfo.Digest, inputInfo.Digest, uploadedInfo.Digest)
-	}
-	return uploadedInfo, nil
-}
 
-// compressionPrefixes is an internal implementation detail of isStreamCompressed
-var compressionPrefixes = map[string][]byte{
-	"gzip":  {0x1F, 0x8B, 0x08},                   // gzip (RFC 1952)
-	"bzip2": {0x42, 0x5A, 0x68},                   // bzip2 (decompress.c:BZ2_decompress)
-	"xz":    {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, // xz (/usr/share/doc/xz/xz-file-format.txt)
-}
-
-// isStreamCompressed returns true if input is recognized as a compressed format.
-// Because it consumes the start of input, other consumers must use the returned io.Reader instead to also read from the beginning.
-func isStreamCompressed(input io.Reader) (bool, io.Reader, error) {
-	buffer := [8]byte{}
-
-	n, err := io.ReadAtLeast(input, buffer[:], len(buffer))
-	if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
-		// This is a “real” error. We could just ignore it this time, process the data we have, and hope that the source will report the same error again.
-		// Instead, fail immediately with the original error cause instead of a possibly secondary/misleading error returned later.
-		return false, nil, err
-	}
-
-	isCompressed := false
-	for algo, prefix := range compressionPrefixes {
-		if bytes.HasPrefix(buffer[:n], prefix) {
-			logrus.Debugf("Detected compression format %s", algo)
-			isCompressed = true
-			break
+	// This is fairly horrible: the writer from getOriginalLayerCopyWriter wants to consumer
+	// all of the input (to compute DiffIDs), even if dest.PutBlob does not need it.
+	// So, read everything from originalLayerReader, which will cause the rest to be
+	// sent there if we are not already at EOF.
+	if getOriginalLayerCopyWriter != nil {
+		logrus.Debugf("Consuming rest of the original blob to satisfy getOriginalLayerCopyWriter")
+		_, err := io.Copy(ioutil.Discard, originalLayerReader)
+		if err != nil {
+			return types.BlobInfo{}, fmt.Errorf("Error reading input blob %s: %v", srcInfo.Digest, err)
 		}
 	}
-	if !isCompressed {
-		logrus.Debugf("No compression detected")
-	}
 
-	return isCompressed, io.MultiReader(bytes.NewReader(buffer[:n]), input), nil
+	if digestingReader.validationFailed { // Coverage: This should never happen.
+		return types.BlobInfo{}, fmt.Errorf("Internal error writing blob %s, digest verification failed but was ignored", srcInfo.Digest)
+	}
+	if inputInfo.Digest != "" && uploadedInfo.Digest != inputInfo.Digest {
+		return types.BlobInfo{}, fmt.Errorf("Internal error writing blob %s, blob with digest %s saved with digest %s", srcInfo.Digest, inputInfo.Digest, uploadedInfo.Digest)
+	}
+	return uploadedInfo, nil
 }
 
 // compressGoroutine reads all input from src and writes its compressed equivalent to dest.
@@ -358,3 +498,41 @@ func compressGoroutine(dest *io.PipeWriter, src io.Reader) {
 
 	_, err = io.Copy(zipper, src) // Sets err to nil, i.e. causes dest.Close()
 }
+
+// determineManifestConversion updates manifestUpdates to convert manifest to a supported MIME type, if necessary and canModifyManifest.
+// Note that the conversion will only happen later, through src.UpdatedImage
+func determineManifestConversion(manifestUpdates *types.ManifestUpdateOptions, src types.Image, destSupportedManifestMIMETypes []string, canModifyManifest bool) error {
+	if len(destSupportedManifestMIMETypes) == 0 {
+		return nil // Anything goes
+	}
+	supportedByDest := map[string]struct{}{}
+	for _, t := range destSupportedManifestMIMETypes {
+		supportedByDest[t] = struct{}{}
+	}
+
+	_, srcType, err := src.Manifest()
+	if err != nil { // This should have been cached?!
+		return fmt.Errorf("Error reading manifest: %v", err)
+	}
+	if _, ok := supportedByDest[srcType]; ok {
+		logrus.Debugf("Manifest MIME type %s is declared supported by the destination", srcType)
+		return nil
+	}
+
+	// OK, we should convert the manifest.
+	if !canModifyManifest {
+		logrus.Debugf("Manifest MIME type %s is not supported by the destination, but we can't modify the manifest, hoping for the best...")
+		return nil // Take our chances - FIXME? Or should we fail without trying?
+	}
+
+	var chosenType = destSupportedManifestMIMETypes[0] // This one is known to be supported.
+	for _, t := range preferredManifestMIMETypes {
+		if _, ok := supportedByDest[t]; ok {
+			chosenType = t
+			break
+		}
+	}
+	logrus.Debugf("Will convert manifest from MIME type %s to %s", srcType, chosenType)
+	manifestUpdates.ManifestMIMEType = chosenType
+	return nil
+}
diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_dest.go b/vendor/github.com/containers/image/docker/daemon/daemon_dest.go
new file mode 100644
index 00000000..151243b8
--- /dev/null
+++ b/vendor/github.com/containers/image/docker/daemon/daemon_dest.go
@@ -0,0 +1,262 @@
+package daemon
+
+import (
+	"archive/tar"
+	"bytes"
+	"crypto/sha256"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"time"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/containers/image/manifest"
+	"github.com/containers/image/types"
+	"github.com/docker/engine-api/client"
+	"golang.org/x/net/context"
+)
+
+type daemonImageDestination struct {
+	ref daemonReference
+	// For talking to imageLoadGoroutine
+	goroutineCancel context.CancelFunc
+	statusChannel   <-chan error
+	writer          *io.PipeWriter
+	tar             *tar.Writer
+	// Other state
+	committed bool // writer has been closed
+}
+
+// newImageDestination returns a types.ImageDestination for the specified image reference.
+func newImageDestination(systemCtx *types.SystemContext, ref daemonReference) (types.ImageDestination, error) {
+	// FIXME: Do something with ref
+	c, err := client.NewClient(client.DefaultDockerHost, "1.22", nil, nil) // FIXME: overridable host
+	if err != nil {
+		return nil, fmt.Errorf("Error initializing docker engine client: %v", err)
+	}
+
+	reader, writer := io.Pipe()
+	// Commit() may never be called, so we may never read from this channel; so, make this buffered to allow imageLoadGoroutine to write status and terminate even if we never read it.
+	statusChannel := make(chan error, 1)
+
+	ctx, goroutineCancel := context.WithCancel(context.Background())
+	go imageLoadGoroutine(ctx, c, reader, statusChannel)
+
+	return &daemonImageDestination{
+		ref:             ref,
+		goroutineCancel: goroutineCancel,
+		statusChannel:   statusChannel,
+		writer:          writer,
+		tar:             tar.NewWriter(writer),
+		committed:       false,
+	}, nil
+}
+
+// imageLoadGoroutine accepts tar stream on reader, sends it to c, and reports error or success by writing to statusChannel
+func imageLoadGoroutine(ctx context.Context, c *client.Client, reader *io.PipeReader, statusChannel chan<- error) {
+	err := errors.New("Internal error: unexpected panic in imageLoadGoroutine")
+	defer func() {
+		logrus.Debugf("docker-daemon: sending done, status %v", err)
+		statusChannel <- err
+	}()
+	defer func() {
+		if err == nil {
+			reader.Close()
+		} else {
+			reader.CloseWithError(err)
+		}
+	}()
+
+	resp, err := c.ImageLoad(ctx, reader, true)
+	if err != nil {
+		err = fmt.Errorf("Error saving image to docker engine: %v", err)
+		return
+	}
+	defer resp.Body.Close()
+}
+
+// Close removes resources associated with an initialized ImageDestination, if any.
+func (d *daemonImageDestination) Close() {
+	if !d.committed {
+		logrus.Debugf("docker-daemon: Closing tar stream to abort loading")
+		// In principle, goroutineCancel() should abort the HTTP request and stop the process from continuing.
+		// In practice, though, https://github.com/docker/engine-api/blob/master/client/transport/cancellable/cancellable.go
+		// currently just runs the HTTP request to completion in a goroutine, and returns early if the context is canceled
+		// without terminating the HTTP request at all.  So we need this CloseWithError to terminate sending the HTTP request Body
+		// immediately, and hopefully, through terminating the sending which uses "Transfer-Encoding: chunked"" without sending
+		// the terminating zero-length chunk, prevent the docker daemon from processing the tar stream at all.
+		// Whether that works or not, closing the PipeWriter seems desirable in any case.
+		d.writer.CloseWithError(errors.New("Aborting upload, daemonImageDestination closed without a previous .Commit()"))
+	}
+	d.goroutineCancel()
+}
+
+// Reference returns the reference used to set up this destination.  Note that this should directly correspond to user's intent,
+// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
+func (d *daemonImageDestination) Reference() types.ImageReference {
+	return d.ref
+}
+
+// SupportedManifestMIMETypes tells which manifest mime types the destination supports
+// If an empty slice or nil it's returned, then any mime type can be tried to upload
+func (d *daemonImageDestination) SupportedManifestMIMETypes() []string {
+	return []string{
+		manifest.DockerV2Schema2MediaType, // FIXME: Handle others.
+	}
+}
+
+// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
+// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil.
+func (d *daemonImageDestination) SupportsSignatures() error {
+	return fmt.Errorf("Storing signatures for docker-daemon: destinations is not supported")
+}
+
+// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination.
+func (d *daemonImageDestination) ShouldCompressLayers() bool {
+	return false
+}
+
+// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
+// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
+// inputInfo.Size is the expected length of stream, if known.
+// WARNING: The contents of stream are being verified on the fly.  Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
+// to any other readers for download using the supplied digest.
+// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
+func (d *daemonImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) {
+	if inputInfo.Digest == "" {
+		return types.BlobInfo{}, fmt.Errorf("Can not stream a blob with unknown digest to docker-daemon:")
+	}
+
+	if inputInfo.Size == -1 { // Ouch, we need to stream the blob into a temporary file just to determine the size.
+		logrus.Debugf("docker-daemon: input with unknown size, streaming to disk first…")
+		streamCopy, err := ioutil.TempFile(temporaryDirectoryForBigFiles, "docker-daemon-blob")
+		if err != nil {
+			return types.BlobInfo{}, err
+		}
+		defer os.Remove(streamCopy.Name())
+		defer streamCopy.Close()
+
+		size, err := io.Copy(streamCopy, stream)
+		if err != nil {
+			return types.BlobInfo{}, err
+		}
+		_, err = streamCopy.Seek(0, os.SEEK_SET)
+		if err != nil {
+			return types.BlobInfo{}, err
+		}
+		inputInfo.Size = size // inputInfo is a struct, so we are only modifying our copy.
+		stream = streamCopy
+		logrus.Debugf("… streaming done")
+	}
+
+	hash := sha256.New()
+	tee := io.TeeReader(stream, hash)
+	if err := d.sendFile(inputInfo.Digest, inputInfo.Size, tee); err != nil {
+		return types.BlobInfo{}, err
+	}
+	return types.BlobInfo{Digest: "sha256:" + hex.EncodeToString(hash.Sum(nil)), Size: inputInfo.Size}, nil
+}
+
+func (d *daemonImageDestination) PutManifest(m []byte) error {
+	var man schema2Manifest
+	if err := json.Unmarshal(m, &man); err != nil {
+		return fmt.Errorf("Error parsing manifest: %v", err)
+	}
+	if man.SchemaVersion != 2 || man.MediaType != manifest.DockerV2Schema2MediaType {
+		// FIXME FIXME: Teach copy.go about this.
+		return fmt.Errorf("Unsupported manifest type, need a Docker schema 2 manifest")
+	}
+
+	layerPaths := []string{}
+	for _, l := range man.Layers {
+		layerPaths = append(layerPaths, l.Digest)
+	}
+	items := []manifestItem{{
+		Config:       man.Config.Digest,
+		RepoTags:     []string{string(d.ref)}, // FIXME: Only if ref is a NamedTagged
+		Layers:       layerPaths,
+		Parent:       "",
+		LayerSources: nil,
+	}}
+	itemsBytes, err := json.Marshal(&items)
+	if err != nil {
+		return err
+	}
+
+	// FIXME? Do we also need to support the legacy format?
+	return d.sendFile(manifestFileName, int64(len(itemsBytes)), bytes.NewReader(itemsBytes))
+}
+
+type tarFI struct {
+	path string
+	size int64
+}
+
+func (t *tarFI) Name() string {
+	return t.path
+}
+func (t *tarFI) Size() int64 {
+	return t.size
+}
+func (t *tarFI) Mode() os.FileMode {
+	return 0444
+}
+func (t *tarFI) ModTime() time.Time {
+	return time.Unix(0, 0)
+}
+func (t *tarFI) IsDir() bool {
+	return false
+}
+func (t *tarFI) Sys() interface{} {
+	return nil
+}
+
+// sendFile sends a file into the tar stream.
+func (d *daemonImageDestination) sendFile(path string, expectedSize int64, stream io.Reader) error {
+	hdr, err := tar.FileInfoHeader(&tarFI{path: path, size: expectedSize}, "")
+	if err != nil {
+		return nil
+	}
+	logrus.Debugf("Sending as tar file %s", path)
+	if err := d.tar.WriteHeader(hdr); err != nil {
+		return err
+	}
+	size, err := io.Copy(d.tar, stream)
+	if err != nil {
+		return err
+	}
+	if size != expectedSize {
+		return fmt.Errorf("Size mismatch when copying %s, expected %d, got %d", path, expectedSize, size)
+	}
+	return nil
+}
+
+func (d *daemonImageDestination) PutSignatures(signatures [][]byte) error {
+	if len(signatures) != 0 {
+		return fmt.Errorf("Storing signatures for docker-daemon: destinations is not supported")
+	}
+	return nil
+}
+
+// Commit marks the process of storing the image as successful and asks for the image to be persisted.
+// WARNING: This does not have any transactional semantics:
+// - Uploaded data MAY be visible to others before Commit() is called
+// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
+func (d *daemonImageDestination) Commit() error {
+	logrus.Debugf("docker-daemon: Closing tar stream")
+	if err := d.tar.Close(); err != nil {
+		return err
+	}
+	if err := d.writer.Close(); err != nil {
+		return err
+	}
+	d.committed = true // We may still fail, but we are done sending to imageLoadGoroutine.
+
+	logrus.Debugf("docker-daemon: Waiting for status")
+	err := <-d.statusChannel
+	return err
+}
diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_src.go b/vendor/github.com/containers/image/docker/daemon/daemon_src.go
new file mode 100644
index 00000000..7bdcf3ee
--- /dev/null
+++ b/vendor/github.com/containers/image/docker/daemon/daemon_src.go
@@ -0,0 +1,361 @@
+package daemon
+
+import (
+	"archive/tar"
+	"bytes"
+	"crypto/sha256"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path"
+
+	"github.com/containers/image/manifest"
+	"github.com/containers/image/types"
+	"github.com/docker/engine-api/client"
+	"golang.org/x/net/context"
+)
+
+const temporaryDirectoryForBigFiles = "/var/tmp" // Do not use the system default of os.TempDir(), usually /tmp, because with systemd it could be a tmpfs.
+
+type daemonImageSource struct {
+	ref         daemonReference
+	tarCopyPath string
+	// The following data is only available after ensureCachedDataIsPresent() succeeds
+	tarManifest       *manifestItem // nil if not available yet.
+	configBytes       []byte
+	configDigest      string
+	orderedDiffIDList []diffID
+	knownLayers       map[diffID]*layerInfo
+	// Other state
+	generatedManifest []byte // Private cache for GetManifest(), nil if not set yet.
+}
+
+type layerInfo struct {
+	path string
+	size int64
+}
+
+// newImageSource returns a types.ImageSource for the specified image reference.
+// The caller must call .Close() on the returned ImageSource.
+//
+// It would be great if we were able to stream the input tar as it is being
+// sent; but Docker sends the top-level manifest, which determines which paths
+// to look for, at the end, so in we will need to seek back and re-read, several times.
+// (We could, perhaps, expect an exact sequence, assume that the first plaintext file
+// is the config, and that the following len(RootFS) files are the layers, but that feels
+// way too brittle.)
+func newImageSource(ctx *types.SystemContext, ref daemonReference) (types.ImageSource, error) {
+	c, err := client.NewClient(client.DefaultDockerHost, "1.22", nil, nil) // FIXME: overridable host
+	if err != nil {
+		return nil, fmt.Errorf("Error initializing docker engine client: %v", err)
+	}
+	inputStream, err := c.ImageSave(context.TODO(), []string{string(ref)}) // FIXME: ref should be per docker/reference.ParseIDOrReference, and we don't want NameOnly
+	if err != nil {
+		return nil, fmt.Errorf("Error loading image from docker engine: %v", err)
+	}
+	defer inputStream.Close()
+
+	// FIXME: use SystemContext here.
+	tarCopyFile, err := ioutil.TempFile(temporaryDirectoryForBigFiles, "docker-daemon-tar")
+	if err != nil {
+		return nil, err
+	}
+	defer tarCopyFile.Close()
+
+	succeeded := false
+	defer func() {
+		if !succeeded {
+			os.Remove(tarCopyFile.Name())
+		}
+	}()
+
+	if _, err := io.Copy(tarCopyFile, inputStream); err != nil {
+		return nil, err
+	}
+
+	succeeded = true
+	return &daemonImageSource{
+		ref:         ref,
+		tarCopyPath: tarCopyFile.Name(),
+	}, nil
+}
+
+// Reference returns the reference used to set up this source, _as specified by the user_
+// (not as the image itself, or its underlying storage, claims).  This can be used e.g. to determine which public keys are trusted for this image.
+func (s *daemonImageSource) Reference() types.ImageReference {
+	return s.ref
+}
+
+// Close removes resources associated with an initialized ImageSource, if any.
+func (s *daemonImageSource) Close() {
+	_ = os.Remove(s.tarCopyPath)
+}
+
+// tarReadCloser is a way to close the backing file of a tar.Reader when the user no longer needs the tar component.
+type tarReadCloser struct {
+	*tar.Reader
+	backingFile *os.File
+}
+
+func (t *tarReadCloser) Close() error {
+	return t.backingFile.Close()
+}
+
+// openTarComponent returns a ReadCloser for the specific file within the archive.
+// This is linear scan; we assume that the tar file will have a fairly small amount of files (~layers),
+// and that filesystem caching will make the repeated seeking over the (uncompressed) tarCopyPath cheap enough.
+// The caller should call .Close() on the returned stream.
+func (s *daemonImageSource) openTarComponent(componentPath string) (io.ReadCloser, error) {
+	f, err := os.Open(s.tarCopyPath)
+	if err != nil {
+		return nil, err
+	}
+	succeeded := false
+	defer func() {
+		if !succeeded {
+			f.Close()
+		}
+	}()
+
+	tarReader, header, err := findTarComponent(f, componentPath)
+	if err != nil {
+		return nil, err
+	}
+	if header == nil {
+		return nil, os.ErrNotExist
+	}
+	if header.FileInfo().Mode()&os.ModeType == os.ModeSymlink { // FIXME: untested
+		// We follow only one symlink; so no loops are possible.
+		if _, err := f.Seek(0, os.SEEK_SET); err != nil {
+			return nil, err
+		}
+		// The new path could easily point "outside" the archive, but we only compare it to existing tar headers without extracting the archive,
+		// so we don't care.
+		tarReader, header, err = findTarComponent(f, path.Join(path.Dir(componentPath), header.Linkname))
+		if err != nil {
+			return nil, err
+		}
+		if header == nil {
+			return nil, os.ErrNotExist
+		}
+	}
+
+	if !header.FileInfo().Mode().IsRegular() {
+		return nil, fmt.Errorf("Error reading tar archive component %s: not a regular file", header.Name)
+	}
+	succeeded = true
+	return &tarReadCloser{Reader: tarReader, backingFile: f}, nil
+}
+
+// findTarComponent returns a header and a reader matching path within inputFile,
+// or (nil, nil, nil) if not found.
+func findTarComponent(inputFile io.Reader, path string) (*tar.Reader, *tar.Header, error) {
+	t := tar.NewReader(inputFile)
+	for {
+		h, err := t.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, nil, err
+		}
+		if h.Name == path {
+			return t, h, nil
+		}
+	}
+	return nil, nil, nil
+}
+
+// readTarComponent returns full contents of componentPath.
+func (s *daemonImageSource) readTarComponent(path string) ([]byte, error) {
+	file, err := s.openTarComponent(path)
+	if err != nil {
+		return nil, fmt.Errorf("Error loading tar component %s: %v", path, err)
+	}
+	defer file.Close()
+	bytes, err := ioutil.ReadAll(file)
+	if err != nil {
+		return nil, err
+	}
+	return bytes, nil
+}
+
+// ensureCachedDataIsPresent loads data necessary for any of the public accessors.
+func (s *daemonImageSource) ensureCachedDataIsPresent() error {
+	if s.tarManifest != nil {
+		return nil
+	}
+
+	// Read and parse manifest.json
+	tarManifest, err := s.loadTarManifest()
+	if err != nil {
+		return err
+	}
+
+	// Read and parse config.
+	configBytes, err := s.readTarComponent(tarManifest.Config)
+	if err != nil {
+		return err
+	}
+	var parsedConfig image // Most fields ommitted, we only care about layer DiffIDs.
+	if err := json.Unmarshal(configBytes, &parsedConfig); err != nil {
+		return fmt.Errorf("Error decoding tar config %s: %v", tarManifest.Config, err)
+	}
+
+	knownLayers, err := s.prepareLayerData(tarManifest, &parsedConfig)
+	if err != nil {
+		return err
+	}
+
+	// Success; commit.
+	configHash := sha256.Sum256(configBytes)
+	s.tarManifest = tarManifest
+	s.configBytes = configBytes
+	s.configDigest = "sha256:" + hex.EncodeToString(configHash[:])
+	s.orderedDiffIDList = parsedConfig.RootFS.DiffIDs
+	s.knownLayers = knownLayers
+	return nil
+}
+
+// loadTarManifest loads and decodes the manifest.json.
+func (s *daemonImageSource) loadTarManifest() (*manifestItem, error) {
+	// FIXME? Do we need to deal with the legacy format?
+	bytes, err := s.readTarComponent(manifestFileName)
+	if err != nil {
+		return nil, err
+	}
+	var items []manifestItem
+	if err := json.Unmarshal(bytes, &items); err != nil {
+		return nil, fmt.Errorf("Error decoding tar manifest.json: %v", err)
+	}
+	if len(items) != 1 {
+		return nil, fmt.Errorf("Unexpected tar manifest.json: expected 1 item, got %d", len(items))
+	}
+	return &items[0], nil
+}
+
+func (s *daemonImageSource) prepareLayerData(tarManifest *manifestItem, parsedConfig *image) (map[diffID]*layerInfo, error) {
+	// Collect layer data available in manifest and config.
+	if len(tarManifest.Layers) != len(parsedConfig.RootFS.DiffIDs) {
+		return nil, fmt.Errorf("Inconsistent layer count: %d in manifest, %d in config", len(tarManifest.Layers), len(parsedConfig.RootFS.DiffIDs))
+	}
+	knownLayers := map[diffID]*layerInfo{}
+	unknownLayerSizes := map[string]*layerInfo{} // Points into knownLayers, a "to do list" of items with unknown sizes.
+	for i, diffID := range parsedConfig.RootFS.DiffIDs {
+		if _, ok := knownLayers[diffID]; ok {
+			// Apparently it really can happen that a single image contains the same layer diff more than once.
+			// In that case, the diffID validation ensures that both layers truly are the same, and it should not matter
+			// which of the tarManifest.Layers paths is used; (docker save) actually makes the duplicates symlinks to the original.
+			continue
+		}
+		layerPath := tarManifest.Layers[i]
+		if _, ok := unknownLayerSizes[layerPath]; ok {
+			return nil, fmt.Errorf("Layer tarfile %s used for two different DiffID values", layerPath)
+		}
+		li := &layerInfo{ // A new element in each iteration
+			path: layerPath,
+			size: -1,
+		}
+		knownLayers[diffID] = li
+		unknownLayerSizes[layerPath] = li
+	}
+
+	// Scan the tar file to collect layer sizes.
+	file, err := os.Open(s.tarCopyPath)
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+	t := tar.NewReader(file)
+	for {
+		h, err := t.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+		if li, ok := unknownLayerSizes[h.Name]; ok {
+			li.size = h.Size
+			delete(unknownLayerSizes, h.Name)
+		}
+	}
+	if len(unknownLayerSizes) != 0 {
+		return nil, fmt.Errorf("Some layer tarfiles are missing in the tarball") // This could do with a better error reporting, if this ever happened in practice.
+	}
+
+	return knownLayers, nil
+}
+
+// GetManifest returns the image's manifest along with its MIME type. The empty string is returned if the MIME type is unknown.
+// It may use a remote (= slow) service.
+func (s *daemonImageSource) GetManifest() ([]byte, string, error) {
+	if s.generatedManifest == nil {
+		if err := s.ensureCachedDataIsPresent(); err != nil {
+			return nil, "", err
+		}
+		m := schema2Manifest{
+			SchemaVersion: 2,
+			MediaType:     manifest.DockerV2Schema2MediaType,
+			Config: distributionDescriptor{
+				MediaType: manifest.DockerV2Schema2ConfigMediaType,
+				Size:      int64(len(s.configBytes)),
+				Digest:    s.configDigest,
+			},
+			Layers: []distributionDescriptor{},
+		}
+		for _, diffID := range s.orderedDiffIDList {
+			li, ok := s.knownLayers[diffID]
+			if !ok {
+				return nil, "", fmt.Errorf("Internal inconsistency: Information about layer %s missing", diffID)
+			}
+			m.Layers = append(m.Layers, distributionDescriptor{
+				Digest:    string(diffID), // diffID is a digest of the uncompressed tarball
+				MediaType: manifest.DockerV2Schema2LayerMediaType,
+				Size:      li.size,
+			})
+		}
+		manifestBytes, err := json.Marshal(&m)
+		if err != nil {
+			return nil, "", err
+		}
+		s.generatedManifest = manifestBytes
+	}
+	return s.generatedManifest, manifest.DockerV2Schema2MediaType, nil
+}
+
+// GetTargetManifest returns an image's manifest given a digest. This is mainly used to retrieve a single image's manifest
+// out of a manifest list.
+func (s *daemonImageSource) GetTargetManifest(digest string) ([]byte, string, error) {
+	// How did we even get here? GetManifest() above has returned a manifest.DockerV2Schema2MediaType.
+	return nil, "", fmt.Errorf("Manifests list are not supported by docker-daemon:")
+}
+
+// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
+func (s *daemonImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
+	if err := s.ensureCachedDataIsPresent(); err != nil {
+		return nil, 0, err
+	}
+
+	if digest == s.configDigest { // FIXME? Implement a more general algorithm matching instead of assuming sha256.
+		return ioutil.NopCloser(bytes.NewReader(s.configBytes)), int64(len(s.configBytes)), nil
+	}
+
+	if li, ok := s.knownLayers[diffID(digest)]; ok { // diffID is a digest of the uncompressed tarball,
+		stream, err := s.openTarComponent(li.path)
+		if err != nil {
+			return nil, 0, err
+		}
+		return stream, li.size, nil
+	}
+
+	return nil, 0, fmt.Errorf("Unknown blob %s", digest)
+}
+
+// GetSignatures returns the image's signatures.  It may use a remote (= slow) service.
+func (s *daemonImageSource) GetSignatures() ([][]byte, error) {
+	return [][]byte{}, nil
+}
diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_transport.go b/vendor/github.com/containers/image/docker/daemon/daemon_transport.go
new file mode 100644
index 00000000..bd100180
--- /dev/null
+++ b/vendor/github.com/containers/image/docker/daemon/daemon_transport.go
@@ -0,0 +1,108 @@
+package daemon
+
+import (
+	"fmt"
+
+	"github.com/containers/image/docker/reference"
+	"github.com/containers/image/types"
+)
+
+// Transport is an ImageTransport for images managed by a local Docker daemon.
+var Transport = daemonTransport{}
+
+type daemonTransport struct{}
+
+// Name returns the name of the transport, which must be unique among other transports.
+func (t daemonTransport) Name() string {
+	return "docker-daemon"
+}
+
+// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference.
+func (t daemonTransport) ParseReference(reference string) (types.ImageReference, error) {
+	return ParseReference(reference)
+}
+
+// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys
+// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value).
+// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion.
+// scope passed to this function will not be "", that value is always allowed.
+func (t daemonTransport) ValidatePolicyConfigurationScope(scope string) error {
+	// FIXME FIXME
+	return nil
+}
+
+// daemonReference is an ImageReference for images managed by a local Docker daemon.
+type daemonReference string // FIXME FIXME
+
+// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference.
+func ParseReference(reference string) (types.ImageReference, error) {
+	return daemonReference(reference), nil // FIXME FIXME
+}
+
+// FIXME FIXME: NewReference?
+
+func (ref daemonReference) Transport() types.ImageTransport {
+	return Transport
+}
+
+// StringWithinTransport returns a string representation of the reference, which MUST be such that
+// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference.
+// NOTE: The returned string is not promised to be equal to the original input to ParseReference;
+// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
+// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix;
+// instead, see transports.ImageName().
+func (ref daemonReference) StringWithinTransport() string {
+	return string(ref) // FIXME FIXME
+}
+
+// DockerReference returns a Docker reference associated with this reference
+// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent,
+// not e.g. after redirect or alias processing), or nil if unknown/not applicable.
+func (ref daemonReference) DockerReference() reference.Named {
+	return nil // FIXME FIXME
+}
+
+// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup.
+// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases;
+// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical
+// (i.e. various references with exactly the same semantics should return the same configuration identity)
+// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but
+// not required/guaranteed that it will be a valid input to Transport().ParseReference().
+// Returns "" if configuration identities for these references are not supported.
+func (ref daemonReference) PolicyConfigurationIdentity() string {
+	return string(ref) // FIXME FIXME
+}
+
+// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search
+// for if explicit configuration for PolicyConfigurationIdentity() is not set.  The list will be processed
+// in order, terminating on first match, and an implicit "" is always checked at the end.
+// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(),
+// and each following element to be a prefix of the element preceding it.
+func (ref daemonReference) PolicyConfigurationNamespaces() []string {
+	return []string{} // FIXME FIXME?
+}
+
+// NewImage returns a types.Image for this reference.
+// The caller must call .Close() on the returned Image.
+func (ref daemonReference) NewImage(ctx *types.SystemContext) (types.Image, error) {
+	panic("FIXME FIXME")
+}
+
+// NewImageSource returns a types.ImageSource for this reference,
+// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
+// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
+// The caller must call .Close() on the returned ImageSource.
+func (ref daemonReference) NewImageSource(ctx *types.SystemContext, requestedManifestMIMETypes []string) (types.ImageSource, error) {
+	return newImageSource(ctx, ref)
+}
+
+// NewImageDestination returns a types.ImageDestination for this reference.
+// The caller must call .Close() on the returned ImageDestination.
+func (ref daemonReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
+	return newImageDestination(ctx, ref)
+}
+
+// DeleteImage deletes the named image from the registry, if supported.
+func (ref daemonReference) DeleteImage(ctx *types.SystemContext) error {
+	return fmt.Errorf("Deleting images not implemented for docker-daemon: images") // FIXME FIXME?
+}
diff --git a/vendor/github.com/containers/image/docker/daemon/daemon_types.go b/vendor/github.com/containers/image/docker/daemon/daemon_types.go
new file mode 100644
index 00000000..aedf92fe
--- /dev/null
+++ b/vendor/github.com/containers/image/docker/daemon/daemon_types.go
@@ -0,0 +1,51 @@
+package daemon
+
+// Various data structures.
+
+// Based on github.com/docker/docker/image/tarexport/tarexport.go
+const (
+	manifestFileName = "manifest.json"
+	// legacyLayerFileName        = "layer.tar"
+	// legacyConfigFileName       = "json"
+	// legacyVersionFileName      = "VERSION"
+	// legacyRepositoriesFileName = "repositories"
+)
+
+type manifestItem struct {
+	Config       string
+	RepoTags     []string
+	Layers       []string
+	Parent       imageID                           `json:",omitempty"`
+	LayerSources map[diffID]distributionDescriptor `json:",omitempty"`
+}
+
+type imageID string
+type diffID string
+
+// Based on github.com/docker/distribution/blobs.go
+type distributionDescriptor struct {
+	MediaType string   `json:"mediaType,omitempty"`
+	Size      int64    `json:"size,omitempty"`
+	Digest    string   `json:"digest,omitempty"`
+	URLs      []string `json:"urls,omitempty"`
+}
+
+// Based on github.com/docker/distribution/manifest/schema2/manifest.go
+// FIXME: We are repeating this all over the place; make a public copy?
+type schema2Manifest struct {
+	SchemaVersion int                      `json:"schemaVersion"`
+	MediaType     string                   `json:"mediaType,omitempty"`
+	Config        distributionDescriptor   `json:"config"`
+	Layers        []distributionDescriptor `json:"layers"`
+}
+
+// Based on github.com/docker/docker/image/image.go
+// MOST CONTENT OMITTED AS UNNECESSARY
+type image struct {
+	RootFS *rootFS `json:"rootfs,omitempty"`
+}
+
+type rootFS struct {
+	Type    string   `json:"type"`
+	DiffIDs []diffID `json:"diff_ids,omitempty"`
+}
diff --git a/vendor/github.com/containers/image/image/docker_list.go b/vendor/github.com/containers/image/image/docker_list.go
index 57f1763e..236a1be9 100644
--- a/vendor/github.com/containers/image/image/docker_list.go
+++ b/vendor/github.com/containers/image/image/docker_list.go
@@ -3,8 +3,10 @@ package image
 import (
 	"encoding/json"
 	"errors"
+	"fmt"
 	"runtime"
 
+	"github.com/containers/image/manifest"
 	"github.com/containers/image/types"
 )
 
@@ -48,5 +50,14 @@ func manifestSchema2FromManifestList(src types.ImageSource, manblob []byte) (gen
 	if err != nil {
 		return nil, err
 	}
+
+	matches, err := manifest.MatchesDigest(manblob, targetManifestDigest)
+	if err != nil {
+		return nil, fmt.Errorf("Error computing manifest digest: %v", err)
+	}
+	if !matches {
+		return nil, fmt.Errorf("Manifest image does not match selected manifest digest %s", targetManifestDigest)
+	}
+
 	return manifestInstanceFromBlob(src, manblob, mt)
 }
diff --git a/vendor/github.com/containers/image/image/docker_schema1.go b/vendor/github.com/containers/image/image/docker_schema1.go
index 7b3f894f..0d508554 100644
--- a/vendor/github.com/containers/image/image/docker_schema1.go
+++ b/vendor/github.com/containers/image/image/docker_schema1.go
@@ -1,11 +1,16 @@
 package image
 
 import (
+	"crypto/sha256"
+	"encoding/hex"
 	"encoding/json"
 	"errors"
 	"fmt"
 	"regexp"
+	"strings"
+	"time"
 
+	"github.com/containers/image/docker/reference"
 	"github.com/containers/image/manifest"
 	"github.com/containers/image/types"
 )
@@ -18,15 +23,30 @@ type fsLayersSchema1 struct {
 	BlobSum string `json:"blobSum"`
 }
 
+type historySchema1 struct {
+	V1Compatibility string `json:"v1Compatibility"`
+}
+
+// historySchema1 is a string containing this.  It is similar to v1Image but not the same, in particular note the ThrowAway field.
+type v1Compatibility struct {
+	ID              string    `json:"id"`
+	Parent          string    `json:"parent,omitempty"`
+	Comment         string    `json:"comment,omitempty"`
+	Created         time.Time `json:"created"`
+	ContainerConfig struct {
+		Cmd []string
+	} `json:"container_config,omitempty"`
+	Author    string `json:"author,omitempty"`
+	ThrowAway bool   `json:"throwaway,omitempty"`
+}
+
 type manifestSchema1 struct {
-	Name         string            `json:"name"`
-	Tag          string            `json:"tag"`
-	Architecture string            `json:"architecture"`
-	FSLayers     []fsLayersSchema1 `json:"fsLayers"`
-	History      []struct {
-		V1Compatibility string `json:"v1Compatibility"`
-	} `json:"history"`
-	SchemaVersion int `json:"schemaVersion"`
+	Name          string            `json:"name"`
+	Tag           string            `json:"tag"`
+	Architecture  string            `json:"architecture"`
+	FSLayers      []fsLayersSchema1 `json:"fsLayers"`
+	History       []historySchema1  `json:"history"`
+	SchemaVersion int               `json:"schemaVersion"`
 }
 
 func manifestSchema1FromManifest(manifest []byte) (genericManifest, error) {
@@ -47,6 +67,25 @@ func manifestSchema1FromManifest(manifest []byte) (genericManifest, error) {
 	return mschema1, nil
 }
 
+// manifestSchema1FromComponents builds a new manifestSchema1 from the supplied data.
+func manifestSchema1FromComponents(ref reference.Named, fsLayers []fsLayersSchema1, history []historySchema1, architecture string) genericManifest {
+	var name, tag string
+	if ref != nil { // Well, what to do if it _is_ nil? Most consumers actually don't use these fields nowadays, so we might as well try not supplying them.
+		name = ref.RemoteName()
+		if tagged, ok := ref.(reference.NamedTagged); ok {
+			tag = tagged.Tag()
+		}
+	}
+	return &manifestSchema1{
+		Name:          name,
+		Tag:           tag,
+		Architecture:  architecture,
+		FSLayers:      fsLayers,
+		History:       history,
+		SchemaVersion: 1,
+	}
+}
+
 func (m *manifestSchema1) serialize() ([]byte, error) {
 	// docker/distribution requires a signature even if the incoming data uses the nominally unsigned DockerV2Schema1MediaType.
 	unsigned, err := json.Marshal(*m)
@@ -61,10 +100,17 @@ func (m *manifestSchema1) manifestMIMEType() string {
 }
 
 // ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object.
+// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below.
 func (m *manifestSchema1) ConfigInfo() types.BlobInfo {
 	return types.BlobInfo{}
 }
 
+// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise.
+// The result is cached; it is OK to call this however often you need.
+func (m *manifestSchema1) ConfigBlob() ([]byte, error) {
+	return nil, nil
+}
+
 // LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers).
 // The Digest field is guaranteed to be provided; Size may be -1.
 // WARNING: The list may contain duplicates, and they are semantically relevant.
@@ -76,17 +122,9 @@ func (m *manifestSchema1) LayerInfos() []types.BlobInfo {
 	return layers
 }
 
-func (m *manifestSchema1) config() ([]byte, error) {
-	return []byte(m.History[0].V1Compatibility), nil
-}
-
 func (m *manifestSchema1) imageInspectInfo() (*types.ImageInspectInfo, error) {
 	v1 := &v1Image{}
-	config, err := m.config()
-	if err != nil {
-		return nil, err
-	}
-	if err := json.Unmarshal(config, v1); err != nil {
+	if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), v1); err != nil {
 		return nil, err
 	}
 	return &types.ImageInspectInfo{
@@ -99,6 +137,13 @@ func (m *manifestSchema1) imageInspectInfo() (*types.ImageInspectInfo, error) {
 	}, nil
 }
 
+// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs.
+// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute
+// (most importantly it forces us to download the full layers even if they are already present at the destination).
+func (m *manifestSchema1) UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool {
+	return options.ManifestMIMEType == manifest.DockerV2Schema2MediaType
+}
+
 // UpdatedImage returns a types.Image modified according to options.
 // This does not change the state of the original Image object.
 func (m *manifestSchema1) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) {
@@ -115,6 +160,18 @@ func (m *manifestSchema1) UpdatedImage(options types.ManifestUpdateOptions) (typ
 			copy.FSLayers[(len(options.LayerInfos)-1)-i].BlobSum = info.Digest
 		}
 	}
+
+	switch options.ManifestMIMEType {
+	case "": // No conversion, OK
+	case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema1SignedMediaType:
+	// We have 2 MIME types for schema 1, which are basically equivalent (even the un-"Signed" MIME type will be rejected if there isn’t a signature; so,
+	// handle conversions between them by doing nothing.
+	case manifest.DockerV2Schema2MediaType:
+		return copy.convertToManifestSchema2(options.InformationOnly.LayerInfos, options.InformationOnly.LayerDiffIDs)
+	default:
+		return nil, fmt.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema1SignedMediaType, options.ManifestMIMEType)
+	}
+
 	return memoryImageFromManifest(&copy), nil
 }
 
@@ -175,3 +232,95 @@ func validateV1ID(id string) error {
 	}
 	return nil
 }
+
+// Based on github.com/docker/docker/distribution/pull_v2.go
+func (m *manifestSchema1) convertToManifestSchema2(uploadedLayerInfos []types.BlobInfo, layerDiffIDs []string) (types.Image, error) {
+	if len(m.History) == 0 {
+		// What would this even mean?! Anyhow, the rest of the code depends on fsLayers[0] and history[0] existing.
+		return nil, fmt.Errorf("Cannot convert an image with 0 history entries to %s", manifest.DockerV2Schema2MediaType)
+	}
+	if len(m.History) != len(m.FSLayers) {
+		return nil, fmt.Errorf("Inconsistent schema 1 manifest: %d history entries, %d fsLayers entries", len(m.History), len(m.FSLayers))
+	}
+	if len(uploadedLayerInfos) != len(m.FSLayers) {
+		return nil, fmt.Errorf("Internal error: uploaded %d blobs, but schema1 manifest has %d fsLayers", len(uploadedLayerInfos), len(m.FSLayers))
+	}
+	if len(layerDiffIDs) != len(m.FSLayers) {
+		return nil, fmt.Errorf("Internal error: collected %d DiffID values, but schema1 manifest has %d fsLayers", len(layerDiffIDs), len(m.FSLayers))
+	}
+
+	rootFS := rootFS{
+		Type:      "layers",
+		DiffIDs:   []string{},
+		BaseLayer: "",
+	}
+	var layers []descriptor
+	history := make([]imageHistory, len(m.History))
+	for v1Index := len(m.History) - 1; v1Index >= 0; v1Index-- {
+		v2Index := (len(m.History) - 1) - v1Index
+
+		var v1compat v1Compatibility
+		if err := json.Unmarshal([]byte(m.History[v1Index].V1Compatibility), &v1compat); err != nil {
+			return nil, fmt.Errorf("Error decoding history entry %d: %v", v1Index, err)
+		}
+		history[v2Index] = imageHistory{
+			Created:    v1compat.Created,
+			Author:     v1compat.Author,
+			CreatedBy:  strings.Join(v1compat.ContainerConfig.Cmd, " "),
+			Comment:    v1compat.Comment,
+			EmptyLayer: v1compat.ThrowAway,
+		}
+
+		if !v1compat.ThrowAway {
+			layers = append(layers, descriptor{
+				MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
+				Size:      uploadedLayerInfos[v2Index].Size,
+				Digest:    m.FSLayers[v1Index].BlobSum,
+			})
+			rootFS.DiffIDs = append(rootFS.DiffIDs, layerDiffIDs[v2Index])
+		}
+	}
+	configJSON, err := configJSONFromV1Config([]byte(m.History[0].V1Compatibility), rootFS, history)
+	if err != nil {
+		return nil, err
+	}
+	configHash := sha256.Sum256(configJSON)
+	configDescriptor := descriptor{
+		MediaType: "application/vnd.docker.container.image.v1+json",
+		Size:      int64(len(configJSON)),
+		Digest:    "sha256:" + hex.EncodeToString(configHash[:]),
+	}
+
+	m2 := manifestSchema2FromComponents(configDescriptor, configJSON, layers)
+	return memoryImageFromManifest(m2), nil
+}
+
+func configJSONFromV1Config(v1ConfigJSON []byte, rootFS rootFS, history []imageHistory) ([]byte, error) {
+	// github.com/docker/docker/image/v1/imagev1.go:MakeConfigFromV1Config unmarshals and re-marshals the input if docker_version is < 1.8.3 to remove blank fields;
+	// we don't do that here. FIXME? Should we? AFAICT it would only affect the digest value of the schema2 manifest, and we don't particularly need that to be
+	// a consistently reproducible value.
+
+	// Preserve everything we don't specifically know about.
+	// (This must be a *json.RawMessage, even though *[]byte is fairly redundant, because only *RawMessage implements json.Marshaler.)
+	rawContents := map[string]*json.RawMessage{}
+	if err := json.Unmarshal(v1ConfigJSON, &rawContents); err != nil { // We have already unmarshaled it before, using a more detailed schema?!
+		return nil, err
+	}
+
+	delete(rawContents, "id")
+	delete(rawContents, "parent")
+	delete(rawContents, "Size")
+	delete(rawContents, "parent_id")
+	delete(rawContents, "layer_id")
+	delete(rawContents, "throwaway")
+
+	updates := map[string]interface{}{"rootfs": rootFS, "history": history}
+	for field, value := range updates {
+		encoded, err := json.Marshal(value)
+		if err != nil {
+			return nil, err
+		}
+		rawContents[field] = (*json.RawMessage)(&encoded)
+	}
+	return json.Marshal(rawContents)
+}
diff --git a/vendor/github.com/containers/image/image/docker_schema2.go b/vendor/github.com/containers/image/image/docker_schema2.go
index b803f1c7..bc3a5f0b 100644
--- a/vendor/github.com/containers/image/image/docker_schema2.go
+++ b/vendor/github.com/containers/image/image/docker_schema2.go
@@ -1,13 +1,31 @@
 package image
 
 import (
+	"bytes"
+	"crypto/sha256"
+	"encoding/hex"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
+	"strings"
 
+	"github.com/Sirupsen/logrus"
+	"github.com/containers/image/manifest"
 	"github.com/containers/image/types"
 )
 
+// gzippedEmptyLayer is a gzip-compressed version of an empty tar file (1024 NULL bytes)
+// This comes from github.com/docker/distribution/manifest/schema1/config_builder.go; there is
+// a non-zero embedded timestamp; we could zero that, but that would just waste storage space
+// in registries, so let’s use the same values.
+var gzippedEmptyLayer = []byte{
+	31, 139, 8, 0, 0, 9, 110, 136, 0, 255, 98, 24, 5, 163, 96, 20, 140, 88,
+	0, 8, 0, 0, 255, 255, 46, 175, 181, 239, 0, 4, 0, 0,
+}
+
+// gzippedEmptyLayerDigest is a digest of gzippedEmptyLayer
+const gzippedEmptyLayerDigest = "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
+
 type descriptor struct {
 	MediaType string `json:"mediaType"`
 	Size      int64  `json:"size"`
@@ -15,11 +33,12 @@ type descriptor struct {
 }
 
 type manifestSchema2 struct {
-	src               types.ImageSource
-	SchemaVersion     int          `json:"schemaVersion"`
-	MediaType         string       `json:"mediaType"`
-	ConfigDescriptor  descriptor   `json:"config"`
-	LayersDescriptors []descriptor `json:"layers"`
+	src               types.ImageSource // May be nil if configBlob is not nil
+	configBlob        []byte            // If set, corresponds to contents of ConfigDescriptor.
+	SchemaVersion     int               `json:"schemaVersion"`
+	MediaType         string            `json:"mediaType"`
+	ConfigDescriptor  descriptor        `json:"config"`
+	LayersDescriptors []descriptor      `json:"layers"`
 }
 
 func manifestSchema2FromManifest(src types.ImageSource, manifest []byte) (genericManifest, error) {
@@ -30,6 +49,18 @@ func manifestSchema2FromManifest(src types.ImageSource, manifest []byte) (generi
 	return &v2s2, nil
 }
 
+// manifestSchema2FromComponents builds a new manifestSchema2 from the supplied data:
+func manifestSchema2FromComponents(config descriptor, configBlob []byte, layers []descriptor) genericManifest {
+	return &manifestSchema2{
+		src:               nil,
+		configBlob:        configBlob,
+		SchemaVersion:     2,
+		MediaType:         manifest.DockerV2Schema2MediaType,
+		ConfigDescriptor:  config,
+		LayersDescriptors: layers,
+	}
+}
+
 func (m *manifestSchema2) serialize() ([]byte, error) {
 	return json.Marshal(*m)
 }
@@ -39,10 +70,37 @@ func (m *manifestSchema2) manifestMIMEType() string {
 }
 
 // ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object.
+// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below.
 func (m *manifestSchema2) ConfigInfo() types.BlobInfo {
 	return types.BlobInfo{Digest: m.ConfigDescriptor.Digest, Size: m.ConfigDescriptor.Size}
 }
 
+// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise.
+// The result is cached; it is OK to call this however often you need.
+func (m *manifestSchema2) ConfigBlob() ([]byte, error) {
+	if m.configBlob == nil {
+		if m.src == nil {
+			return nil, fmt.Errorf("Internal error: neither src nor configBlob set in manifestSchema2")
+		}
+		stream, _, err := m.src.GetBlob(m.ConfigDescriptor.Digest)
+		if err != nil {
+			return nil, err
+		}
+		defer stream.Close()
+		blob, err := ioutil.ReadAll(stream)
+		if err != nil {
+			return nil, err
+		}
+		hash := sha256.Sum256(blob)
+		computedDigest := "sha256:" + hex.EncodeToString(hash[:])
+		if computedDigest != m.ConfigDescriptor.Digest {
+			return nil, fmt.Errorf("Download config.json digest %s does not match expected %s", computedDigest, m.ConfigDescriptor.Digest)
+		}
+		m.configBlob = blob
+	}
+	return m.configBlob, nil
+}
+
 // LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers).
 // The Digest field is guaranteed to be provided; Size may be -1.
 // WARNING: The list may contain duplicates, and they are semantically relevant.
@@ -54,18 +112,8 @@ func (m *manifestSchema2) LayerInfos() []types.BlobInfo {
 	return blobs
 }
 
-func (m *manifestSchema2) config() ([]byte, error) {
-	rawConfig, _, err := m.src.GetBlob(m.ConfigDescriptor.Digest)
-	if err != nil {
-		return nil, err
-	}
-	config, err := ioutil.ReadAll(rawConfig)
-	rawConfig.Close()
-	return config, err
-}
-
 func (m *manifestSchema2) imageInspectInfo() (*types.ImageInspectInfo, error) {
-	config, err := m.config()
+	config, err := m.ConfigBlob()
 	if err != nil {
 		return nil, err
 	}
@@ -82,18 +130,161 @@ func (m *manifestSchema2) imageInspectInfo() (*types.ImageInspectInfo, error) {
 	}, nil
 }
 
+// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs.
+// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute
+// (most importantly it forces us to download the full layers even if they are already present at the destination).
+func (m *manifestSchema2) UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool {
+	return false
+}
+
 // UpdatedImage returns a types.Image modified according to options.
 // This does not change the state of the original Image object.
 func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error) {
-	copy := *m
+	copy := *m // NOTE: This is not a deep copy, it still shares slices etc.
 	if options.LayerInfos != nil {
 		if len(copy.LayersDescriptors) != len(options.LayerInfos) {
 			return nil, fmt.Errorf("Error preparing updated manifest: layer count changed from %d to %d", len(copy.LayersDescriptors), len(options.LayerInfos))
 		}
+		copy.LayersDescriptors = make([]descriptor, len(options.LayerInfos))
 		for i, info := range options.LayerInfos {
 			copy.LayersDescriptors[i].Digest = info.Digest
 			copy.LayersDescriptors[i].Size = info.Size
 		}
 	}
+
+	switch options.ManifestMIMEType {
+	case "": // No conversion, OK
+	case manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema1MediaType:
+		return copy.convertToManifestSchema1(options.InformationOnly.Destination)
+	default:
+		return nil, fmt.Errorf("Conversion of image manifest from %s to %s is not implemented", manifest.DockerV2Schema2MediaType, options.ManifestMIMEType)
+	}
+
 	return memoryImageFromManifest(&copy), nil
 }
+
+// Based on docker/distribution/manifest/schema1/config_builder.go
+func (m *manifestSchema2) convertToManifestSchema1(dest types.ImageDestination) (types.Image, error) {
+	configBytes, err := m.ConfigBlob()
+	if err != nil {
+		return nil, err
+	}
+	imageConfig := &image{}
+	if err := json.Unmarshal(configBytes, imageConfig); err != nil {
+		return nil, err
+	}
+
+	// Build fsLayers and History, discarding all configs. We will patch the top-level config in later.
+	fsLayers := make([]fsLayersSchema1, len(imageConfig.History))
+	history := make([]historySchema1, len(imageConfig.History))
+	nonemptyLayerIndex := 0
+	var parentV1ID string // Set in the loop
+	v1ID := ""
+	haveGzippedEmptyLayer := false
+	if len(imageConfig.History) == 0 {
+		// What would this even mean?! Anyhow, the rest of the code depends on fsLayers[0] and history[0] existing.
+		return nil, fmt.Errorf("Cannot convert an image with 0 history entries to %s", manifest.DockerV2Schema1SignedMediaType)
+	}
+	for v2Index, historyEntry := range imageConfig.History {
+		parentV1ID = v1ID
+		v1Index := len(imageConfig.History) - 1 - v2Index
+
+		var blobDigest string
+		if historyEntry.EmptyLayer {
+			if !haveGzippedEmptyLayer {
+				logrus.Debugf("Uploading empty layer during conversion to schema 1")
+				info, err := dest.PutBlob(bytes.NewReader(gzippedEmptyLayer), types.BlobInfo{Digest: gzippedEmptyLayerDigest, Size: int64(len(gzippedEmptyLayer))})
+				if err != nil {
+					return nil, fmt.Errorf("Error uploading empty layer: %v", err)
+				}
+				if info.Digest != gzippedEmptyLayerDigest {
+					return nil, fmt.Errorf("Internal error: Uploaded empty layer has digest %#v instead of %s", info.Digest, gzippedEmptyLayerDigest)
+				}
+				haveGzippedEmptyLayer = true
+			}
+			blobDigest = gzippedEmptyLayerDigest
+		} else {
+			if nonemptyLayerIndex >= len(m.LayersDescriptors) {
+				return nil, fmt.Errorf("Invalid image configuration, needs more than the %d distributed layers", len(m.LayersDescriptors))
+			}
+			blobDigest = m.LayersDescriptors[nonemptyLayerIndex].Digest
+			nonemptyLayerIndex++
+		}
+
+		// AFAICT pull ignores these ID values, at least nowadays, so we could use anything unique, including a simple counter. Use what Docker uses for cargo-cult consistency.
+		v, err := v1IDFromBlobDigestAndComponents(blobDigest, parentV1ID)
+		if err != nil {
+			return nil, err
+		}
+		v1ID = v
+
+		fakeImage := v1Compatibility{
+			ID:        v1ID,
+			Parent:    parentV1ID,
+			Comment:   historyEntry.Comment,
+			Created:   historyEntry.Created,
+			Author:    historyEntry.Author,
+			ThrowAway: historyEntry.EmptyLayer,
+		}
+		fakeImage.ContainerConfig.Cmd = []string{historyEntry.CreatedBy}
+		v1CompatibilityBytes, err := json.Marshal(&fakeImage)
+		if err != nil {
+			return nil, fmt.Errorf("Internal error: Error creating v1compatibility for %#v", fakeImage)
+		}
+
+		fsLayers[v1Index] = fsLayersSchema1{BlobSum: blobDigest}
+		history[v1Index] = historySchema1{V1Compatibility: string(v1CompatibilityBytes)}
+		// Note that parentV1ID of the top layer is preserved when exiting this loop
+	}
+
+	// Now patch in real configuration for the top layer (v1Index == 0)
+	v1ID, err = v1IDFromBlobDigestAndComponents(fsLayers[0].BlobSum, parentV1ID, string(configBytes)) // See above WRT v1ID value generation and cargo-cult consistency.
+	if err != nil {
+		return nil, err
+	}
+	v1Config, err := v1ConfigFromConfigJSON(configBytes, v1ID, parentV1ID, imageConfig.History[len(imageConfig.History)-1].EmptyLayer)
+	if err != nil {
+		return nil, err
+	}
+	history[0].V1Compatibility = string(v1Config)
+
+	m1 := manifestSchema1FromComponents(dest.Reference().DockerReference(), fsLayers, history, imageConfig.Architecture)
+	return memoryImageFromManifest(m1), nil
+}
+
+func v1IDFromBlobDigestAndComponents(blobDigest string, others ...string) (string, error) {
+	blobDigestComponents := strings.SplitN(blobDigest, ":", 2)
+	if len(blobDigestComponents) != 2 {
+		return "", fmt.Errorf("Invalid layer digest %s: expecting algorithm:value", blobDigest)
+	}
+	parts := append([]string{blobDigestComponents[1]}, others...)
+	v1IDHash := sha256.Sum256([]byte(strings.Join(parts, " ")))
+	return hex.EncodeToString(v1IDHash[:]), nil
+}
+
+func v1ConfigFromConfigJSON(configJSON []byte, v1ID, parentV1ID string, throwaway bool) ([]byte, error) {
+	// Preserve everything we don't specifically know about.
+	// (This must be a *json.RawMessage, even though *[]byte is fairly redundant, because only *RawMessage implements json.Marshaler.)
+	rawContents := map[string]*json.RawMessage{}
+	if err := json.Unmarshal(configJSON, &rawContents); err != nil { // We have already unmarshaled it before, using a more detailed schema?!
+		return nil, err
+	}
+	delete(rawContents, "rootfs")
+	delete(rawContents, "history")
+
+	updates := map[string]interface{}{"id": v1ID}
+	if parentV1ID != "" {
+		updates["parent"] = parentV1ID
+	}
+	if throwaway {
+		updates["throwaway"] = throwaway
+	}
+	for field, value := range updates {
+		encoded, err := json.Marshal(value)
+		if err != nil {
+			return nil, err
+		}
+		rawContents[field] = (*json.RawMessage)(&encoded)
+	}
+	return json.Marshal(rawContents)
+}
diff --git a/vendor/github.com/containers/image/image/manifest.go b/vendor/github.com/containers/image/image/manifest.go
index 17b12235..feb20032 100644
--- a/vendor/github.com/containers/image/image/manifest.go
+++ b/vendor/github.com/containers/image/image/manifest.go
@@ -5,27 +5,53 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/docker/engine-api/types/strslice"
+
 	"github.com/containers/image/manifest"
 	"github.com/containers/image/types"
 )
 
 type config struct {
+	Cmd    strslice.StrSlice
 	Labels map[string]string
 }
 
 type v1Image struct {
+	ID              string    `json:"id,omitempty"`
+	Parent          string    `json:"parent,omitempty"`
+	Comment         string    `json:"comment,omitempty"`
+	Created         time.Time `json:"created"`
+	ContainerConfig *config   `json:"container_config,omitempty"`
+	DockerVersion   string    `json:"docker_version,omitempty"`
+	Author          string    `json:"author,omitempty"`
 	// Config is the configuration of the container received from the client
 	Config *config `json:"config,omitempty"`
-	// DockerVersion specifies version on which image is built
-	DockerVersion string `json:"docker_version,omitempty"`
-	// Created timestamp when image was created
-	Created time.Time `json:"created"`
 	// Architecture is the hardware that the image is build and runs on
 	Architecture string `json:"architecture,omitempty"`
 	// OS is the operating system used to build and run the image
 	OS string `json:"os,omitempty"`
 }
 
+type image struct {
+	v1Image
+	History []imageHistory `json:"history,omitempty"`
+	RootFS  *rootFS        `json:"rootfs,omitempty"`
+}
+
+type imageHistory struct {
+	Created    time.Time `json:"created"`
+	Author     string    `json:"author,omitempty"`
+	CreatedBy  string    `json:"created_by,omitempty"`
+	Comment    string    `json:"comment,omitempty"`
+	EmptyLayer bool      `json:"empty_layer,omitempty"`
+}
+
+type rootFS struct {
+	Type      string   `json:"type"`
+	DiffIDs   []string `json:"diff_ids,omitempty"`
+	BaseLayer string   `json:"base_layer,omitempty"`
+}
+
 // genericManifest is an interface for parsing, modifying image manifests and related data.
 // Note that the public methods are intended to be a subset of types.Image
 // so that embedding a genericManifest into structs works.
@@ -33,14 +59,21 @@ type v1Image struct {
 type genericManifest interface {
 	serialize() ([]byte, error)
 	manifestMIMEType() string
-	config() ([]byte, error)
 	// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object.
+	// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below.
 	ConfigInfo() types.BlobInfo
+	// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise.
+	// The result is cached; it is OK to call this however often you need.
+	ConfigBlob() ([]byte, error)
 	// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers).
 	// The Digest field is guaranteed to be provided; Size may be -1.
 	// WARNING: The list may contain duplicates, and they are semantically relevant.
 	LayerInfos() []types.BlobInfo
 	imageInspectInfo() (*types.ImageInspectInfo, error) // To be called by inspectManifest
+	// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs.
+	// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute
+	// (most importantly it forces us to download the full layers even if they are already present at the destination).
+	UpdatedImageNeedsLayerDiffIDs(options types.ManifestUpdateOptions) bool
 	// UpdatedImage returns a types.Image modified according to options.
 	// This does not change the state of the original Image object.
 	UpdatedImage(options types.ManifestUpdateOptions) (types.Image, error)
diff --git a/vendor/github.com/containers/image/image/unparsed.go b/vendor/github.com/containers/image/image/unparsed.go
index 2682a5d8..b57c31db 100644
--- a/vendor/github.com/containers/image/image/unparsed.go
+++ b/vendor/github.com/containers/image/image/unparsed.go
@@ -1,6 +1,12 @@
 package image
 
-import "github.com/containers/image/types"
+import (
+	"fmt"
+
+	"github.com/containers/image/docker/reference"
+	"github.com/containers/image/manifest"
+	"github.com/containers/image/types"
+)
 
 // UnparsedImage implements types.UnparsedImage .
 type UnparsedImage struct {
@@ -41,6 +47,23 @@ func (i *UnparsedImage) Manifest() ([]byte, string, error) {
 		if err != nil {
 			return nil, "", err
 		}
+
+		// ImageSource.GetManifest does not do digest verification, but we do;
+		// this immediately protects also any user of types.Image.
+		ref := i.Reference().DockerReference()
+		if ref != nil {
+			if canonical, ok := ref.(reference.Canonical); ok {
+				digest := canonical.Digest().String()
+				matches, err := manifest.MatchesDigest(m, digest)
+				if err != nil {
+					return nil, "", fmt.Errorf("Error computing manifest digest: %v", err)
+				}
+				if !matches {
+					return nil, "", fmt.Errorf("Manifest does not match provided manifest digest %s", digest)
+				}
+			}
+		}
+
 		i.cachedManifest = m
 		i.cachedManifestMIMEType = mt
 	}
diff --git a/vendor/github.com/containers/image/manifest/manifest.go b/vendor/github.com/containers/image/manifest/manifest.go
index 2e4ba206..176120bc 100644
--- a/vendor/github.com/containers/image/manifest/manifest.go
+++ b/vendor/github.com/containers/image/manifest/manifest.go
@@ -19,6 +19,10 @@ const (
 	DockerV2Schema1SignedMediaType = "application/vnd.docker.distribution.manifest.v1+prettyjws"
 	// DockerV2Schema2MediaType MIME type represents Docker manifest schema 2
 	DockerV2Schema2MediaType = "application/vnd.docker.distribution.manifest.v2+json"
+	// DockerV2Schema2ConfigMediaType is the MIME type used for schema 2 config blobs.
+	DockerV2Schema2ConfigMediaType = "application/vnd.docker.container.image.v1+json"
+	// DockerV2Schema2LayerMediaType is the MIME type used for schema 2 layers.
+	DockerV2Schema2LayerMediaType = "application/vnd.docker.image.rootfs.diff.tar.gzip"
 	// DockerV2ListMediaType MIME type represents Docker manifest schema 2 list
 	DockerV2ListMediaType = "application/vnd.docker.distribution.manifest.list.v2+json"
 )
diff --git a/vendor/github.com/containers/image/transports/transports.go b/vendor/github.com/containers/image/transports/transports.go
index 70aa8801..97613517 100644
--- a/vendor/github.com/containers/image/transports/transports.go
+++ b/vendor/github.com/containers/image/transports/transports.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/containers/image/directory"
 	"github.com/containers/image/docker"
+	"github.com/containers/image/docker/daemon"
 	ociLayout "github.com/containers/image/oci/layout"
 	"github.com/containers/image/openshift"
 	"github.com/containers/image/types"
@@ -21,6 +22,7 @@ func init() {
 	for _, t := range []types.ImageTransport{
 		directory.Transport,
 		docker.Transport,
+		daemon.Transport,
 		ociLayout.Transport,
 		openshift.Transport,
 	} {
diff --git a/vendor/github.com/containers/image/types/types.go b/vendor/github.com/containers/image/types/types.go
index 8ee2946b..a893c421 100644
--- a/vendor/github.com/containers/image/types/types.go
+++ b/vendor/github.com/containers/image/types/types.go
@@ -99,6 +99,9 @@ type BlobInfo struct {
 // This is primarily useful for copying images around; for examining their properties, Image (below)
 // is usually more useful.
 // Each ImageSource should eventually be closed by calling Close().
+//
+// WARNING: Various methods which return an object identified by digest generally do not
+// validate that the returned data actually matches that digest; this is the caller’s responsibility.
 type ImageSource interface {
 	// Reference returns the reference used to set up this source, _as specified by the user_
 	// (not as the image itself, or its underlying storage, claims).  This can be used e.g. to determine which public keys are trusted for this image.
@@ -181,14 +184,23 @@ type Image interface {
 	// Note that Reference may return nil in the return value of UpdatedImage!
 	UnparsedImage
 	// ConfigInfo returns a complete BlobInfo for the separate config object, or a BlobInfo{Digest:""} if there isn't a separate object.
+	// Note that the config object may not exist in the underlying storage in the return value of UpdatedImage! Use ConfigBlob() below.
 	ConfigInfo() BlobInfo
+	// ConfigBlob returns the blob described by ConfigInfo, iff ConfigInfo().Digest != ""; nil otherwise.
+	// The result is cached; it is OK to call this however often you need.
+	ConfigBlob() ([]byte, error)
 	// LayerInfos returns a list of BlobInfos of layers referenced by this image, in order (the root layer first, and then successive layered layers).
 	// The Digest field is guaranteed to be provided; Size may be -1.
 	// WARNING: The list may contain duplicates, and they are semantically relevant.
 	LayerInfos() []BlobInfo
 	// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration.
 	Inspect() (*ImageInspectInfo, error)
+	// UpdatedImageNeedsLayerDiffIDs returns true iff UpdatedImage(options) needs InformationOnly.LayerDiffIDs.
+	// This is a horribly specific interface, but computing InformationOnly.LayerDiffIDs can be very expensive to compute
+	// (most importantly it forces us to download the full layers even if they are already present at the destination).
+	UpdatedImageNeedsLayerDiffIDs(options ManifestUpdateOptions) bool
 	// UpdatedImage returns a types.Image modified according to options.
+	// Everything in options.InformationOnly should be provided, other fields should be set only if a modification is desired.
 	// This does not change the state of the original Image object.
 	UpdatedImage(options ManifestUpdateOptions) (Image, error)
 	// IsMultiImage returns true if the image's manifest is a list of images, false otherwise.
@@ -197,7 +209,18 @@ type Image interface {
 
 // ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest
 type ManifestUpdateOptions struct {
-	LayerInfos []BlobInfo // Complete BlobInfos (size+digest) which should replace the originals, in order (the root layer first, and then successive layered layers)
+	LayerInfos       []BlobInfo // Complete BlobInfos (size+digest) which should replace the originals, in order (the root layer first, and then successive layered layers)
+	ManifestMIMEType string
+	// The values below are NOT requests to modify the image; they provide optional context which may or may not be used.
+	InformationOnly ManifestUpdateInformation
+}
+
+// ManifestUpdateInformation is a component of ManifestUpdateOptions, named here
+// only to make writing struct literals possible.
+type ManifestUpdateInformation struct {
+	Destination  ImageDestination // and yes, UpdatedManifest may write to Destination (see the schema2 → schema1 conversion logic in image/docker_schema2.go)
+	LayerInfos   []BlobInfo       // Complete BlobInfos (size+digest) which have been uploaded, in order (the root layer first, and then successive layered layers)
+	LayerDiffIDs []string         // Digest values for the _uncompressed_ contents of the blobs which have been uploaded, in the same order.
 }
 
 // ImageInspectInfo is a set of metadata describing Docker images, primarily their manifest and configuration.
diff --git a/vendor/github.com/docker/engine-api/client/checkpoint_create.go b/vendor/github.com/docker/engine-api/client/checkpoint_create.go
new file mode 100644
index 00000000..23883cc0
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/checkpoint_create.go
@@ -0,0 +1,13 @@
+package client
+
+import (
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// CheckpointCreate creates a checkpoint from the given container with the given name
+func (cli *Client) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error {
+	resp, err := cli.post(ctx, "/containers/"+container+"/checkpoints", nil, options, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/checkpoint_delete.go b/vendor/github.com/docker/engine-api/client/checkpoint_delete.go
new file mode 100644
index 00000000..a4e9ed0c
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/checkpoint_delete.go
@@ -0,0 +1,12 @@
+package client
+
+import (
+	"golang.org/x/net/context"
+)
+
+// CheckpointDelete deletes the checkpoint with the given name from the given container
+func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, checkpointID string) error {
+	resp, err := cli.delete(ctx, "/containers/"+containerID+"/checkpoints/"+checkpointID, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/checkpoint_list.go b/vendor/github.com/docker/engine-api/client/checkpoint_list.go
new file mode 100644
index 00000000..ef5ec261
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/checkpoint_list.go
@@ -0,0 +1,22 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// CheckpointList returns the volumes configured in the docker host.
+func (cli *Client) CheckpointList(ctx context.Context, container string) ([]types.Checkpoint, error) {
+	var checkpoints []types.Checkpoint
+
+	resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", nil, nil)
+	if err != nil {
+		return checkpoints, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&checkpoints)
+	ensureReaderClosed(resp)
+	return checkpoints, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/client.go b/vendor/github.com/docker/engine-api/client/client.go
new file mode 100644
index 00000000..f3ad2cf3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/client.go
@@ -0,0 +1,153 @@
+package client
+
+import (
+	"fmt"
+	"net/http"
+	"net/url"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/docker/engine-api/client/transport"
+	"github.com/docker/go-connections/tlsconfig"
+)
+
+// DefaultVersion is the version of the current stable API
+const DefaultVersion string = "1.23"
+
+// Client is the API client that performs all operations
+// against a docker server.
+type Client struct {
+	// proto holds the client protocol i.e. unix.
+	proto string
+	// addr holds the client address.
+	addr string
+	// basePath holds the path to prepend to the requests.
+	basePath string
+	// transport is the interface to send request with, it implements transport.Client.
+	transport transport.Client
+	// version of the server to talk to.
+	version string
+	// custom http headers configured by users.
+	customHTTPHeaders map[string]string
+}
+
+// NewEnvClient initializes a new API client based on environment variables.
+// Use DOCKER_HOST to set the url to the docker server.
+// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
+// Use DOCKER_CERT_PATH to load the tls certificates from.
+// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
+func NewEnvClient() (*Client, error) {
+	var client *http.Client
+	if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
+		options := tlsconfig.Options{
+			CAFile:             filepath.Join(dockerCertPath, "ca.pem"),
+			CertFile:           filepath.Join(dockerCertPath, "cert.pem"),
+			KeyFile:            filepath.Join(dockerCertPath, "key.pem"),
+			InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
+		}
+		tlsc, err := tlsconfig.Client(options)
+		if err != nil {
+			return nil, err
+		}
+
+		client = &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: tlsc,
+			},
+		}
+	}
+
+	host := os.Getenv("DOCKER_HOST")
+	if host == "" {
+		host = DefaultDockerHost
+	}
+
+	version := os.Getenv("DOCKER_API_VERSION")
+	if version == "" {
+		version = DefaultVersion
+	}
+
+	return NewClient(host, version, client, nil)
+}
+
+// NewClient initializes a new API client for the given host and API version.
+// It uses the given http client as transport.
+// It also initializes the custom http headers to add to each request.
+//
+// It won't send any version information if the version number is empty. It is
+// highly recommended that you set a version or your client may break if the
+// server is upgraded.
+func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
+	proto, addr, basePath, err := ParseHost(host)
+	if err != nil {
+		return nil, err
+	}
+
+	transport, err := transport.NewTransportWithHTTP(proto, addr, client)
+	if err != nil {
+		return nil, err
+	}
+
+	return &Client{
+		proto:             proto,
+		addr:              addr,
+		basePath:          basePath,
+		transport:         transport,
+		version:           version,
+		customHTTPHeaders: httpHeaders,
+	}, nil
+}
+
+// getAPIPath returns the versioned request path to call the api.
+// It appends the query parameters to the path if they are not empty.
+func (cli *Client) getAPIPath(p string, query url.Values) string {
+	var apiPath string
+	if cli.version != "" {
+		v := strings.TrimPrefix(cli.version, "v")
+		apiPath = fmt.Sprintf("%s/v%s%s", cli.basePath, v, p)
+	} else {
+		apiPath = fmt.Sprintf("%s%s", cli.basePath, p)
+	}
+
+	u := &url.URL{
+		Path: apiPath,
+	}
+	if len(query) > 0 {
+		u.RawQuery = query.Encode()
+	}
+	return u.String()
+}
+
+// ClientVersion returns the version string associated with this
+// instance of the Client. Note that this value can be changed
+// via the DOCKER_API_VERSION env var.
+func (cli *Client) ClientVersion() string {
+	return cli.version
+}
+
+// UpdateClientVersion updates the version string associated with this
+// instance of the Client.
+func (cli *Client) UpdateClientVersion(v string) {
+	cli.version = v
+}
+
+// ParseHost verifies that the given host strings is valid.
+func ParseHost(host string) (string, string, string, error) {
+	protoAddrParts := strings.SplitN(host, "://", 2)
+	if len(protoAddrParts) == 1 {
+		return "", "", "", fmt.Errorf("unable to parse docker host `%s`", host)
+	}
+
+	var basePath string
+	proto, addr := protoAddrParts[0], protoAddrParts[1]
+	if proto == "tcp" {
+		parsed, err := url.Parse("tcp://" + addr)
+		if err != nil {
+			return "", "", "", err
+		}
+		addr = parsed.Host
+		basePath = parsed.Path
+	}
+	return proto, addr, basePath, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/client_darwin.go b/vendor/github.com/docker/engine-api/client/client_darwin.go
new file mode 100644
index 00000000..4b47a178
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/client_darwin.go
@@ -0,0 +1,4 @@
+package client
+
+// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
+const DefaultDockerHost = "tcp://127.0.0.1:2375"
diff --git a/vendor/github.com/docker/engine-api/client/client_unix.go b/vendor/github.com/docker/engine-api/client/client_unix.go
new file mode 100644
index 00000000..572c5f87
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/client_unix.go
@@ -0,0 +1,6 @@
+// +build linux freebsd solaris openbsd
+
+package client
+
+// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
+const DefaultDockerHost = "unix:///var/run/docker.sock"
diff --git a/vendor/github.com/docker/engine-api/client/client_windows.go b/vendor/github.com/docker/engine-api/client/client_windows.go
new file mode 100644
index 00000000..07c0c7a7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/client_windows.go
@@ -0,0 +1,4 @@
+package client
+
+// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
+const DefaultDockerHost = "npipe:////./pipe/docker_engine"
diff --git a/vendor/github.com/docker/engine-api/client/container_attach.go b/vendor/github.com/docker/engine-api/client/container_attach.go
new file mode 100644
index 00000000..1b616bf0
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_attach.go
@@ -0,0 +1,34 @@
+package client
+
+import (
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerAttach attaches a connection to a container in the server.
+// It returns a types.HijackedConnection with the hijacked connection
+// and the a reader to get output. It's up to the called to close
+// the hijacked connection by calling types.HijackedResponse.Close.
+func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) {
+	query := url.Values{}
+	if options.Stream {
+		query.Set("stream", "1")
+	}
+	if options.Stdin {
+		query.Set("stdin", "1")
+	}
+	if options.Stdout {
+		query.Set("stdout", "1")
+	}
+	if options.Stderr {
+		query.Set("stderr", "1")
+	}
+	if options.DetachKeys != "" {
+		query.Set("detachKeys", options.DetachKeys)
+	}
+
+	headers := map[string][]string{"Content-Type": {"text/plain"}}
+	return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers)
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_commit.go b/vendor/github.com/docker/engine-api/client/container_commit.go
new file mode 100644
index 00000000..d5c47499
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_commit.go
@@ -0,0 +1,53 @@
+package client
+
+import (
+	"encoding/json"
+	"errors"
+	"net/url"
+
+	distreference "github.com/docker/distribution/reference"
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/reference"
+	"golang.org/x/net/context"
+)
+
+// ContainerCommit applies changes into a container and creates a new tagged image.
+func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) {
+	var repository, tag string
+	if options.Reference != "" {
+		distributionRef, err := distreference.ParseNamed(options.Reference)
+		if err != nil {
+			return types.ContainerCommitResponse{}, err
+		}
+
+		if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
+			return types.ContainerCommitResponse{}, errors.New("refusing to create a tag with a digest reference")
+		}
+
+		tag = reference.GetTagFromNamedRef(distributionRef)
+		repository = distributionRef.Name()
+	}
+
+	query := url.Values{}
+	query.Set("container", container)
+	query.Set("repo", repository)
+	query.Set("tag", tag)
+	query.Set("comment", options.Comment)
+	query.Set("author", options.Author)
+	for _, change := range options.Changes {
+		query.Add("changes", change)
+	}
+	if options.Pause != true {
+		query.Set("pause", "0")
+	}
+
+	var response types.ContainerCommitResponse
+	resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
+	if err != nil {
+		return response, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&response)
+	ensureReaderClosed(resp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_copy.go b/vendor/github.com/docker/engine-api/client/container_copy.go
new file mode 100644
index 00000000..d3dd0b11
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_copy.go
@@ -0,0 +1,97 @@
+package client
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/url"
+	"path/filepath"
+	"strings"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+)
+
+// ContainerStatPath returns Stat information about a path inside the container filesystem.
+func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (types.ContainerPathStat, error) {
+	query := url.Values{}
+	query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API.
+
+	urlStr := fmt.Sprintf("/containers/%s/archive", containerID)
+	response, err := cli.head(ctx, urlStr, query, nil)
+	if err != nil {
+		return types.ContainerPathStat{}, err
+	}
+	defer ensureReaderClosed(response)
+	return getContainerPathStatFromHeader(response.header)
+}
+
+// CopyToContainer copies content into the container filesystem.
+func (cli *Client) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error {
+	query := url.Values{}
+	query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API.
+	// Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
+	if !options.AllowOverwriteDirWithFile {
+		query.Set("noOverwriteDirNonDir", "true")
+	}
+
+	apiPath := fmt.Sprintf("/containers/%s/archive", container)
+
+	response, err := cli.putRaw(ctx, apiPath, query, content, nil)
+	if err != nil {
+		return err
+	}
+	defer ensureReaderClosed(response)
+
+	if response.statusCode != http.StatusOK {
+		return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
+	}
+
+	return nil
+}
+
+// CopyFromContainer gets the content from the container and returns it as a Reader
+// to manipulate it in the host. It's up to the caller to close the reader.
+func (cli *Client) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
+	query := make(url.Values, 1)
+	query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API.
+
+	apiPath := fmt.Sprintf("/containers/%s/archive", container)
+	response, err := cli.get(ctx, apiPath, query, nil)
+	if err != nil {
+		return nil, types.ContainerPathStat{}, err
+	}
+
+	if response.statusCode != http.StatusOK {
+		return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
+	}
+
+	// In order to get the copy behavior right, we need to know information
+	// about both the source and the destination. The response headers include
+	// stat info about the source that we can use in deciding exactly how to
+	// copy it locally. Along with the stat info about the local destination,
+	// we have everything we need to handle the multiple possibilities there
+	// can be when copying a file/dir from one location to another file/dir.
+	stat, err := getContainerPathStatFromHeader(response.header)
+	if err != nil {
+		return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err)
+	}
+	return response.body, stat, err
+}
+
+func getContainerPathStatFromHeader(header http.Header) (types.ContainerPathStat, error) {
+	var stat types.ContainerPathStat
+
+	encodedStat := header.Get("X-Docker-Container-Path-Stat")
+	statDecoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encodedStat))
+
+	err := json.NewDecoder(statDecoder).Decode(&stat)
+	if err != nil {
+		err = fmt.Errorf("unable to decode container path stat header: %s", err)
+	}
+
+	return stat, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_create.go b/vendor/github.com/docker/engine-api/client/container_create.go
new file mode 100644
index 00000000..98935794
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_create.go
@@ -0,0 +1,46 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+	"strings"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/container"
+	"github.com/docker/engine-api/types/network"
+	"golang.org/x/net/context"
+)
+
+type configWrapper struct {
+	*container.Config
+	HostConfig       *container.HostConfig
+	NetworkingConfig *network.NetworkingConfig
+}
+
+// ContainerCreate creates a new container based in the given configuration.
+// It can be associated with a name, but it's not mandatory.
+func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error) {
+	var response types.ContainerCreateResponse
+	query := url.Values{}
+	if containerName != "" {
+		query.Set("name", containerName)
+	}
+
+	body := configWrapper{
+		Config:           config,
+		HostConfig:       hostConfig,
+		NetworkingConfig: networkingConfig,
+	}
+
+	serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
+	if err != nil {
+		if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
+			return response, imageNotFoundError{config.Image}
+		}
+		return response, err
+	}
+
+	err = json.NewDecoder(serverResp.body).Decode(&response)
+	ensureReaderClosed(serverResp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_diff.go b/vendor/github.com/docker/engine-api/client/container_diff.go
new file mode 100644
index 00000000..f4bb3a46
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_diff.go
@@ -0,0 +1,23 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerDiff shows differences in a container filesystem since it was started.
+func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]types.ContainerChange, error) {
+	var changes []types.ContainerChange
+
+	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
+	if err != nil {
+		return changes, err
+	}
+
+	err = json.NewDecoder(serverResp.body).Decode(&changes)
+	ensureReaderClosed(serverResp)
+	return changes, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_exec.go b/vendor/github.com/docker/engine-api/client/container_exec.go
new file mode 100644
index 00000000..ff7e1a9d
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_exec.go
@@ -0,0 +1,49 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerExecCreate creates a new exec configuration to run an exec process.
+func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error) {
+	var response types.ContainerExecCreateResponse
+	resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
+	if err != nil {
+		return response, err
+	}
+	err = json.NewDecoder(resp.body).Decode(&response)
+	ensureReaderClosed(resp)
+	return response, err
+}
+
+// ContainerExecStart starts an exec process already created in the docker host.
+func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
+	resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, config, nil)
+	ensureReaderClosed(resp)
+	return err
+}
+
+// ContainerExecAttach attaches a connection to an exec process in the server.
+// It returns a types.HijackedConnection with the hijacked connection
+// and the a reader to get output. It's up to the called to close
+// the hijacked connection by calling types.HijackedResponse.Close.
+func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error) {
+	headers := map[string][]string{"Content-Type": {"application/json"}}
+	return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
+}
+
+// ContainerExecInspect returns information about a specific exec process on the docker host.
+func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) {
+	var response types.ContainerExecInspect
+	resp, err := cli.get(ctx, "/exec/"+execID+"/json", nil, nil)
+	if err != nil {
+		return response, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&response)
+	ensureReaderClosed(resp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_export.go b/vendor/github.com/docker/engine-api/client/container_export.go
new file mode 100644
index 00000000..52194f3d
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_export.go
@@ -0,0 +1,20 @@
+package client
+
+import (
+	"io"
+	"net/url"
+
+	"golang.org/x/net/context"
+)
+
+// ContainerExport retrieves the raw contents of a container
+// and returns them as an io.ReadCloser. It's up to the caller
+// to close the stream.
+func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) {
+	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return serverResp.body, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_inspect.go b/vendor/github.com/docker/engine-api/client/container_inspect.go
new file mode 100644
index 00000000..0fa096d3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_inspect.go
@@ -0,0 +1,54 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerInspect returns the container information.
+func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
+	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
+	if err != nil {
+		if serverResp.statusCode == http.StatusNotFound {
+			return types.ContainerJSON{}, containerNotFoundError{containerID}
+		}
+		return types.ContainerJSON{}, err
+	}
+
+	var response types.ContainerJSON
+	err = json.NewDecoder(serverResp.body).Decode(&response)
+	ensureReaderClosed(serverResp)
+	return response, err
+}
+
+// ContainerInspectWithRaw returns the container information and its raw representation.
+func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
+	query := url.Values{}
+	if getSize {
+		query.Set("size", "1")
+	}
+	serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
+	if err != nil {
+		if serverResp.statusCode == http.StatusNotFound {
+			return types.ContainerJSON{}, nil, containerNotFoundError{containerID}
+		}
+		return types.ContainerJSON{}, nil, err
+	}
+	defer ensureReaderClosed(serverResp)
+
+	body, err := ioutil.ReadAll(serverResp.body)
+	if err != nil {
+		return types.ContainerJSON{}, nil, err
+	}
+
+	var response types.ContainerJSON
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&response)
+	return response, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_kill.go b/vendor/github.com/docker/engine-api/client/container_kill.go
new file mode 100644
index 00000000..29f80c73
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_kill.go
@@ -0,0 +1,17 @@
+package client
+
+import (
+	"net/url"
+
+	"golang.org/x/net/context"
+)
+
+// ContainerKill terminates the container process but does not remove the container from the docker host.
+func (cli *Client) ContainerKill(ctx context.Context, containerID, signal string) error {
+	query := url.Values{}
+	query.Set("signal", signal)
+
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/kill", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_list.go b/vendor/github.com/docker/engine-api/client/container_list.go
new file mode 100644
index 00000000..87f7333d
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_list.go
@@ -0,0 +1,56 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+	"strconv"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"golang.org/x/net/context"
+)
+
+// ContainerList returns the list of containers in the docker host.
+func (cli *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) {
+	query := url.Values{}
+
+	if options.All {
+		query.Set("all", "1")
+	}
+
+	if options.Limit != -1 {
+		query.Set("limit", strconv.Itoa(options.Limit))
+	}
+
+	if options.Since != "" {
+		query.Set("since", options.Since)
+	}
+
+	if options.Before != "" {
+		query.Set("before", options.Before)
+	}
+
+	if options.Size {
+		query.Set("size", "1")
+	}
+
+	if options.Filter.Len() > 0 {
+		filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filter)
+
+		if err != nil {
+			return nil, err
+		}
+
+		query.Set("filters", filterJSON)
+	}
+
+	resp, err := cli.get(ctx, "/containers/json", query, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var containers []types.Container
+	err = json.NewDecoder(resp.body).Decode(&containers)
+	ensureReaderClosed(resp)
+	return containers, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_logs.go b/vendor/github.com/docker/engine-api/client/container_logs.go
new file mode 100644
index 00000000..08b9b918
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_logs.go
@@ -0,0 +1,52 @@
+package client
+
+import (
+	"io"
+	"net/url"
+	"time"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+	timetypes "github.com/docker/engine-api/types/time"
+)
+
+// ContainerLogs returns the logs generated by a container in an io.ReadCloser.
+// It's up to the caller to close the stream.
+func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
+	query := url.Values{}
+	if options.ShowStdout {
+		query.Set("stdout", "1")
+	}
+
+	if options.ShowStderr {
+		query.Set("stderr", "1")
+	}
+
+	if options.Since != "" {
+		ts, err := timetypes.GetTimestamp(options.Since, time.Now())
+		if err != nil {
+			return nil, err
+		}
+		query.Set("since", ts)
+	}
+
+	if options.Timestamps {
+		query.Set("timestamps", "1")
+	}
+
+	if options.Details {
+		query.Set("details", "1")
+	}
+
+	if options.Follow {
+		query.Set("follow", "1")
+	}
+	query.Set("tail", options.Tail)
+
+	resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil)
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_pause.go b/vendor/github.com/docker/engine-api/client/container_pause.go
new file mode 100644
index 00000000..412067a7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_pause.go
@@ -0,0 +1,10 @@
+package client
+
+import "golang.org/x/net/context"
+
+// ContainerPause pauses the main process of a given container without terminating it.
+func (cli *Client) ContainerPause(ctx context.Context, containerID string) error {
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/pause", nil, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_remove.go b/vendor/github.com/docker/engine-api/client/container_remove.go
new file mode 100644
index 00000000..cef4b812
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_remove.go
@@ -0,0 +1,27 @@
+package client
+
+import (
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerRemove kills and removes a container from the docker host.
+func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error {
+	query := url.Values{}
+	if options.RemoveVolumes {
+		query.Set("v", "1")
+	}
+	if options.RemoveLinks {
+		query.Set("link", "1")
+	}
+
+	if options.Force {
+		query.Set("force", "1")
+	}
+
+	resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_rename.go b/vendor/github.com/docker/engine-api/client/container_rename.go
new file mode 100644
index 00000000..0e718da7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_rename.go
@@ -0,0 +1,16 @@
+package client
+
+import (
+	"net/url"
+
+	"golang.org/x/net/context"
+)
+
+// ContainerRename changes the name of a given container.
+func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error {
+	query := url.Values{}
+	query.Set("name", newContainerName)
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_resize.go b/vendor/github.com/docker/engine-api/client/container_resize.go
new file mode 100644
index 00000000..b95d26b3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_resize.go
@@ -0,0 +1,29 @@
+package client
+
+import (
+	"net/url"
+	"strconv"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerResize changes the size of the tty for a container.
+func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error {
+	return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width)
+}
+
+// ContainerExecResize changes the size of the tty for an exec process running inside a container.
+func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error {
+	return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width)
+}
+
+func (cli *Client) resize(ctx context.Context, basePath string, height, width int) error {
+	query := url.Values{}
+	query.Set("h", strconv.Itoa(height))
+	query.Set("w", strconv.Itoa(width))
+
+	resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_restart.go b/vendor/github.com/docker/engine-api/client/container_restart.go
new file mode 100644
index 00000000..93c042d0
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_restart.go
@@ -0,0 +1,22 @@
+package client
+
+import (
+	"net/url"
+	"time"
+
+	timetypes "github.com/docker/engine-api/types/time"
+	"golang.org/x/net/context"
+)
+
+// ContainerRestart stops and starts a container again.
+// It makes the daemon to wait for the container to be up again for
+// a specific amount of time, given the timeout.
+func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout *time.Duration) error {
+	query := url.Values{}
+	if timeout != nil {
+		query.Set("t", timetypes.DurationToSecondsString(*timeout))
+	}
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_start.go b/vendor/github.com/docker/engine-api/client/container_start.go
new file mode 100644
index 00000000..1e22eec6
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_start.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+)
+
+// ContainerStart sends a request to the docker daemon to start a container.
+func (cli *Client) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error {
+	query := url.Values{}
+	if len(options.CheckpointID) != 0 {
+		query.Set("checkpoint", options.CheckpointID)
+	}
+
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/start", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_stats.go b/vendor/github.com/docker/engine-api/client/container_stats.go
new file mode 100644
index 00000000..2cc67c3a
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_stats.go
@@ -0,0 +1,24 @@
+package client
+
+import (
+	"io"
+	"net/url"
+
+	"golang.org/x/net/context"
+)
+
+// ContainerStats returns near realtime stats for a given container.
+// It's up to the caller to close the io.ReadCloser returned.
+func (cli *Client) ContainerStats(ctx context.Context, containerID string, stream bool) (io.ReadCloser, error) {
+	query := url.Values{}
+	query.Set("stream", "0")
+	if stream {
+		query.Set("stream", "1")
+	}
+
+	resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil)
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_stop.go b/vendor/github.com/docker/engine-api/client/container_stop.go
new file mode 100644
index 00000000..1fc577f2
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_stop.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"net/url"
+	"time"
+
+	timetypes "github.com/docker/engine-api/types/time"
+	"golang.org/x/net/context"
+)
+
+// ContainerStop stops a container without terminating the process.
+// The process is blocked until the container stops or the timeout expires.
+func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error {
+	query := url.Values{}
+	if timeout != nil {
+		query.Set("t", timetypes.DurationToSecondsString(*timeout))
+	}
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_top.go b/vendor/github.com/docker/engine-api/client/container_top.go
new file mode 100644
index 00000000..5ad926ae
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_top.go
@@ -0,0 +1,28 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+	"strings"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ContainerTop shows process information from within a container.
+func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (types.ContainerProcessList, error) {
+	var response types.ContainerProcessList
+	query := url.Values{}
+	if len(arguments) > 0 {
+		query.Set("ps_args", strings.Join(arguments, " "))
+	}
+
+	resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil)
+	if err != nil {
+		return response, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&response)
+	ensureReaderClosed(resp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_unpause.go b/vendor/github.com/docker/engine-api/client/container_unpause.go
new file mode 100644
index 00000000..5c762112
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_unpause.go
@@ -0,0 +1,10 @@
+package client
+
+import "golang.org/x/net/context"
+
+// ContainerUnpause resumes the process execution within a container
+func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error {
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_update.go b/vendor/github.com/docker/engine-api/client/container_update.go
new file mode 100644
index 00000000..a5a1826d
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_update.go
@@ -0,0 +1,13 @@
+package client
+
+import (
+	"github.com/docker/engine-api/types/container"
+	"golang.org/x/net/context"
+)
+
+// ContainerUpdate updates resources of a container
+func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) error {
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/container_wait.go b/vendor/github.com/docker/engine-api/client/container_wait.go
new file mode 100644
index 00000000..c26ff3f3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/container_wait.go
@@ -0,0 +1,26 @@
+package client
+
+import (
+	"encoding/json"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+)
+
+// ContainerWait pauses execution until a container exits.
+// It returns the API status code as response of its readiness.
+func (cli *Client) ContainerWait(ctx context.Context, containerID string) (int, error) {
+	resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil)
+	if err != nil {
+		return -1, err
+	}
+	defer ensureReaderClosed(resp)
+
+	var res types.ContainerWaitResponse
+	if err := json.NewDecoder(resp.body).Decode(&res); err != nil {
+		return -1, err
+	}
+
+	return res.StatusCode, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/errors.go b/vendor/github.com/docker/engine-api/client/errors.go
new file mode 100644
index 00000000..e026320b
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/errors.go
@@ -0,0 +1,203 @@
+package client
+
+import (
+	"errors"
+	"fmt"
+)
+
+// ErrConnectionFailed is an error raised when the connection between the client and the server failed.
+var ErrConnectionFailed = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
+
+type notFound interface {
+	error
+	NotFound() bool // Is the error a NotFound error
+}
+
+// IsErrNotFound returns true if the error is caused with an
+// object (image, container, network, volume, …) is not found in the docker host.
+func IsErrNotFound(err error) bool {
+	te, ok := err.(notFound)
+	return ok && te.NotFound()
+}
+
+// imageNotFoundError implements an error returned when an image is not in the docker host.
+type imageNotFoundError struct {
+	imageID string
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e imageNotFoundError) NotFound() bool {
+	return true
+}
+
+// Error returns a string representation of an imageNotFoundError
+func (e imageNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such image: %s", e.imageID)
+}
+
+// IsErrImageNotFound returns true if the error is caused
+// when an image is not found in the docker host.
+func IsErrImageNotFound(err error) bool {
+	return IsErrNotFound(err)
+}
+
+// containerNotFoundError implements an error returned when a container is not in the docker host.
+type containerNotFoundError struct {
+	containerID string
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e containerNotFoundError) NotFound() bool {
+	return true
+}
+
+// Error returns a string representation of a containerNotFoundError
+func (e containerNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such container: %s", e.containerID)
+}
+
+// IsErrContainerNotFound returns true if the error is caused
+// when a container is not found in the docker host.
+func IsErrContainerNotFound(err error) bool {
+	return IsErrNotFound(err)
+}
+
+// networkNotFoundError implements an error returned when a network is not in the docker host.
+type networkNotFoundError struct {
+	networkID string
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e networkNotFoundError) NotFound() bool {
+	return true
+}
+
+// Error returns a string representation of a networkNotFoundError
+func (e networkNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such network: %s", e.networkID)
+}
+
+// IsErrNetworkNotFound returns true if the error is caused
+// when a network is not found in the docker host.
+func IsErrNetworkNotFound(err error) bool {
+	return IsErrNotFound(err)
+}
+
+// volumeNotFoundError implements an error returned when a volume is not in the docker host.
+type volumeNotFoundError struct {
+	volumeID string
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e volumeNotFoundError) NotFound() bool {
+	return true
+}
+
+// Error returns a string representation of a networkNotFoundError
+func (e volumeNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such volume: %s", e.volumeID)
+}
+
+// IsErrVolumeNotFound returns true if the error is caused
+// when a volume is not found in the docker host.
+func IsErrVolumeNotFound(err error) bool {
+	return IsErrNotFound(err)
+}
+
+// unauthorizedError represents an authorization error in a remote registry.
+type unauthorizedError struct {
+	cause error
+}
+
+// Error returns a string representation of an unauthorizedError
+func (u unauthorizedError) Error() string {
+	return u.cause.Error()
+}
+
+// IsErrUnauthorized returns true if the error is caused
+// when a remote registry authentication fails
+func IsErrUnauthorized(err error) bool {
+	_, ok := err.(unauthorizedError)
+	return ok
+}
+
+// nodeNotFoundError implements an error returned when a node is not found.
+type nodeNotFoundError struct {
+	nodeID string
+}
+
+// Error returns a string representation of a nodeNotFoundError
+func (e nodeNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such node: %s", e.nodeID)
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e nodeNotFoundError) NotFound() bool {
+	return true
+}
+
+// IsErrNodeNotFound returns true if the error is caused
+// when a node is not found.
+func IsErrNodeNotFound(err error) bool {
+	_, ok := err.(nodeNotFoundError)
+	return ok
+}
+
+// serviceNotFoundError implements an error returned when a service is not found.
+type serviceNotFoundError struct {
+	serviceID string
+}
+
+// Error returns a string representation of a serviceNotFoundError
+func (e serviceNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such service: %s", e.serviceID)
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e serviceNotFoundError) NotFound() bool {
+	return true
+}
+
+// IsErrServiceNotFound returns true if the error is caused
+// when a service is not found.
+func IsErrServiceNotFound(err error) bool {
+	_, ok := err.(serviceNotFoundError)
+	return ok
+}
+
+// taskNotFoundError implements an error returned when a task is not found.
+type taskNotFoundError struct {
+	taskID string
+}
+
+// Error returns a string representation of a taskNotFoundError
+func (e taskNotFoundError) Error() string {
+	return fmt.Sprintf("Error: No such task: %s", e.taskID)
+}
+
+// NoFound indicates that this error type is of NotFound
+func (e taskNotFoundError) NotFound() bool {
+	return true
+}
+
+// IsErrTaskNotFound returns true if the error is caused
+// when a task is not found.
+func IsErrTaskNotFound(err error) bool {
+	_, ok := err.(taskNotFoundError)
+	return ok
+}
+
+type pluginPermissionDenied struct {
+	name string
+}
+
+func (e pluginPermissionDenied) Error() string {
+	return "Permission denied while installing plugin " + e.name
+}
+
+// IsErrPluginPermissionDenied returns true if the error is caused
+// when a user denies a plugin's permissions
+func IsErrPluginPermissionDenied(err error) bool {
+	_, ok := err.(pluginPermissionDenied)
+	return ok
+}
diff --git a/vendor/github.com/docker/engine-api/client/events.go b/vendor/github.com/docker/engine-api/client/events.go
new file mode 100644
index 00000000..f22a18e1
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/events.go
@@ -0,0 +1,48 @@
+package client
+
+import (
+	"io"
+	"net/url"
+	"time"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	timetypes "github.com/docker/engine-api/types/time"
+)
+
+// Events returns a stream of events in the daemon in a ReadCloser.
+// It's up to the caller to close the stream.
+func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error) {
+	query := url.Values{}
+	ref := time.Now()
+
+	if options.Since != "" {
+		ts, err := timetypes.GetTimestamp(options.Since, ref)
+		if err != nil {
+			return nil, err
+		}
+		query.Set("since", ts)
+	}
+	if options.Until != "" {
+		ts, err := timetypes.GetTimestamp(options.Until, ref)
+		if err != nil {
+			return nil, err
+		}
+		query.Set("until", ts)
+	}
+	if options.Filters.Len() > 0 {
+		filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
+		if err != nil {
+			return nil, err
+		}
+		query.Set("filters", filterJSON)
+	}
+
+	serverResponse, err := cli.get(ctx, "/events", query, nil)
+	if err != nil {
+		return nil, err
+	}
+	return serverResponse.body, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/hijack.go b/vendor/github.com/docker/engine-api/client/hijack.go
new file mode 100644
index 00000000..dbd91ef6
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/hijack.go
@@ -0,0 +1,174 @@
+package client
+
+import (
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"net"
+	"net/http/httputil"
+	"net/url"
+	"strings"
+	"time"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/go-connections/sockets"
+	"golang.org/x/net/context"
+)
+
+// tlsClientCon holds tls information and a dialed connection.
+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 conn, ok := c.rawConn.(types.CloseWriter); ok {
+		return conn.CloseWrite()
+	}
+	return nil
+}
+
+// postHijacked sends a POST request and hijacks the connection.
+func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
+	bodyEncoded, err := encodeData(body)
+	if err != nil {
+		return types.HijackedResponse{}, err
+	}
+
+	req, err := cli.newRequest("POST", path, query, bodyEncoded, headers)
+	if err != nil {
+		return types.HijackedResponse{}, err
+	}
+	req.Host = cli.addr
+
+	req.Header.Set("Connection", "Upgrade")
+	req.Header.Set("Upgrade", "tcp")
+
+	conn, err := dial(cli.proto, cli.addr, cli.transport.TLSConfig())
+	if err != nil {
+		if strings.Contains(err.Error(), "connection refused") {
+			return types.HijackedResponse{}, fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
+		}
+		return types.HijackedResponse{}, 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 := conn.(*net.TCPConn); ok {
+		tcpConn.SetKeepAlive(true)
+		tcpConn.SetKeepAlivePeriod(30 * time.Second)
+	}
+
+	clientconn := httputil.NewClientConn(conn, nil)
+	defer clientconn.Close()
+
+	// Server hijacks the connection, error 'connection closed' expected
+	_, err = clientconn.Do(req)
+
+	rwc, br := clientconn.Hijack()
+
+	return types.HijackedResponse{Conn: rwc, Reader: br}, err
+}
+
+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("")
+		})
+	}
+
+	proxyDialer, err := sockets.DialerFromEnvironment(dialer)
+	if err != nil {
+		return nil, err
+	}
+
+	rawConn, err := proxyDialer.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 dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
+	if tlsConfig != nil && proto != "unix" && proto != "npipe" {
+		// Notice this isn't Go standard's tls.Dial function
+		return tlsDial(proto, addr, tlsConfig)
+	}
+	if proto == "npipe" {
+		return sockets.DialPipe(addr, 32*time.Second)
+	}
+	return net.Dial(proto, addr)
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_build.go b/vendor/github.com/docker/engine-api/client/image_build.go
new file mode 100644
index 00000000..0ceb88cf
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_build.go
@@ -0,0 +1,119 @@
+package client
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"io"
+	"net/http"
+	"net/url"
+	"regexp"
+	"strconv"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/container"
+)
+
+var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
+
+// ImageBuild sends request to the daemon to build images.
+// The Body in the response implement an io.ReadCloser and it's up to the caller to
+// close it.
+func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
+	query, err := imageBuildOptionsToQuery(options)
+	if err != nil {
+		return types.ImageBuildResponse{}, err
+	}
+
+	headers := http.Header(make(map[string][]string))
+	buf, err := json.Marshal(options.AuthConfigs)
+	if err != nil {
+		return types.ImageBuildResponse{}, err
+	}
+	headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
+	headers.Set("Content-Type", "application/tar")
+
+	serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
+	if err != nil {
+		return types.ImageBuildResponse{}, err
+	}
+
+	osType := getDockerOS(serverResp.header.Get("Server"))
+
+	return types.ImageBuildResponse{
+		Body:   serverResp.body,
+		OSType: osType,
+	}, nil
+}
+
+func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
+	query := url.Values{
+		"t": options.Tags,
+	}
+	if options.SuppressOutput {
+		query.Set("q", "1")
+	}
+	if options.RemoteContext != "" {
+		query.Set("remote", options.RemoteContext)
+	}
+	if options.NoCache {
+		query.Set("nocache", "1")
+	}
+	if options.Remove {
+		query.Set("rm", "1")
+	} else {
+		query.Set("rm", "0")
+	}
+
+	if options.ForceRemove {
+		query.Set("forcerm", "1")
+	}
+
+	if options.PullParent {
+		query.Set("pull", "1")
+	}
+
+	if !container.Isolation.IsDefault(options.Isolation) {
+		query.Set("isolation", string(options.Isolation))
+	}
+
+	query.Set("cpusetcpus", options.CPUSetCPUs)
+	query.Set("cpusetmems", options.CPUSetMems)
+	query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
+	query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
+	query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
+	query.Set("memory", strconv.FormatInt(options.Memory, 10))
+	query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
+	query.Set("cgroupparent", options.CgroupParent)
+	query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
+	query.Set("dockerfile", options.Dockerfile)
+
+	ulimitsJSON, err := json.Marshal(options.Ulimits)
+	if err != nil {
+		return query, err
+	}
+	query.Set("ulimits", string(ulimitsJSON))
+
+	buildArgsJSON, err := json.Marshal(options.BuildArgs)
+	if err != nil {
+		return query, err
+	}
+	query.Set("buildargs", string(buildArgsJSON))
+
+	labelsJSON, err := json.Marshal(options.Labels)
+	if err != nil {
+		return query, err
+	}
+	query.Set("labels", string(labelsJSON))
+	return query, nil
+}
+
+func getDockerOS(serverHeader string) string {
+	var osType string
+	matches := headerRegexp.FindStringSubmatch(serverHeader)
+	if len(matches) > 0 {
+		osType = matches[1]
+	}
+	return osType
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_create.go b/vendor/github.com/docker/engine-api/client/image_create.go
new file mode 100644
index 00000000..6dfc0391
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_create.go
@@ -0,0 +1,34 @@
+package client
+
+import (
+	"io"
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/reference"
+)
+
+// ImageCreate creates a new image based in the parent options.
+// It returns the JSON content in the response body.
+func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
+	repository, tag, err := reference.Parse(parentReference)
+	if err != nil {
+		return nil, err
+	}
+
+	query := url.Values{}
+	query.Set("fromImage", repository)
+	query.Set("tag", tag)
+	resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, nil
+}
+
+func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
+	headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
+	return cli.post(ctx, "/images/create", query, nil, headers)
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_history.go b/vendor/github.com/docker/engine-api/client/image_history.go
new file mode 100644
index 00000000..b2840b5e
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_history.go
@@ -0,0 +1,22 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ImageHistory returns the changes in an image in history format.
+func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]types.ImageHistory, error) {
+	var history []types.ImageHistory
+	serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
+	if err != nil {
+		return history, err
+	}
+
+	err = json.NewDecoder(serverResp.body).Decode(&history)
+	ensureReaderClosed(serverResp)
+	return history, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_import.go b/vendor/github.com/docker/engine-api/client/image_import.go
new file mode 100644
index 00000000..4e8749a0
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_import.go
@@ -0,0 +1,37 @@
+package client
+
+import (
+	"io"
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/distribution/reference"
+	"github.com/docker/engine-api/types"
+)
+
+// ImageImport creates a new image based in the source options.
+// It returns the JSON content in the response body.
+func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
+	if ref != "" {
+		//Check if the given image name can be resolved
+		if _, err := reference.ParseNamed(ref); err != nil {
+			return nil, err
+		}
+	}
+
+	query := url.Values{}
+	query.Set("fromSrc", source.SourceName)
+	query.Set("repo", ref)
+	query.Set("tag", options.Tag)
+	query.Set("message", options.Message)
+	for _, change := range options.Changes {
+		query.Add("changes", change)
+	}
+
+	resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil)
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_inspect.go b/vendor/github.com/docker/engine-api/client/image_inspect.go
new file mode 100644
index 00000000..859ba640
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_inspect.go
@@ -0,0 +1,38 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ImageInspectWithRaw returns the image information and its raw representation.
+func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string, getSize bool) (types.ImageInspect, []byte, error) {
+	query := url.Values{}
+	if getSize {
+		query.Set("size", "1")
+	}
+	serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil)
+	if err != nil {
+		if serverResp.statusCode == http.StatusNotFound {
+			return types.ImageInspect{}, nil, imageNotFoundError{imageID}
+		}
+		return types.ImageInspect{}, nil, err
+	}
+	defer ensureReaderClosed(serverResp)
+
+	body, err := ioutil.ReadAll(serverResp.body)
+	if err != nil {
+		return types.ImageInspect{}, nil, err
+	}
+
+	var response types.ImageInspect
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&response)
+	return response, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_list.go b/vendor/github.com/docker/engine-api/client/image_list.go
new file mode 100644
index 00000000..74082582
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_list.go
@@ -0,0 +1,40 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"golang.org/x/net/context"
+)
+
+// ImageList returns a list of images in the docker host.
+func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) {
+	var images []types.Image
+	query := url.Values{}
+
+	if options.Filters.Len() > 0 {
+		filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
+		if err != nil {
+			return images, err
+		}
+		query.Set("filters", filterJSON)
+	}
+	if options.MatchName != "" {
+		// FIXME rename this parameter, to not be confused with the filters flag
+		query.Set("filter", options.MatchName)
+	}
+	if options.All {
+		query.Set("all", "1")
+	}
+
+	serverResp, err := cli.get(ctx, "/images/json", query, nil)
+	if err != nil {
+		return images, err
+	}
+
+	err = json.NewDecoder(serverResp.body).Decode(&images)
+	ensureReaderClosed(serverResp)
+	return images, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_load.go b/vendor/github.com/docker/engine-api/client/image_load.go
new file mode 100644
index 00000000..72f55fdc
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_load.go
@@ -0,0 +1,30 @@
+package client
+
+import (
+	"io"
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+)
+
+// ImageLoad loads an image in the docker host from the client host.
+// It's up to the caller to close the io.ReadCloser in the
+// ImageLoadResponse returned by this function.
+func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) {
+	v := url.Values{}
+	v.Set("quiet", "0")
+	if quiet {
+		v.Set("quiet", "1")
+	}
+	headers := map[string][]string{"Content-Type": {"application/x-tar"}}
+	resp, err := cli.postRaw(ctx, "/images/load", v, input, headers)
+	if err != nil {
+		return types.ImageLoadResponse{}, err
+	}
+	return types.ImageLoadResponse{
+		Body: resp.body,
+		JSON: resp.header.Get("Content-Type") == "application/json",
+	}, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_pull.go b/vendor/github.com/docker/engine-api/client/image_pull.go
new file mode 100644
index 00000000..e2c49ec5
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_pull.go
@@ -0,0 +1,46 @@
+package client
+
+import (
+	"io"
+	"net/http"
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/reference"
+)
+
+// ImagePull requests the docker host to pull an image from a remote registry.
+// It executes the privileged function if the operation is unauthorized
+// and it tries one more time.
+// It's up to the caller to handle the io.ReadCloser and close it properly.
+//
+// FIXME(vdemeester): there is currently used in a few way in docker/docker
+// - if not in trusted content, ref is used to pass the whole reference, and tag is empty
+// - if in trusted content, ref is used to pass the reference name, and tag for the digest
+func (cli *Client) ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
+	repository, tag, err := reference.Parse(ref)
+	if err != nil {
+		return nil, err
+	}
+
+	query := url.Values{}
+	query.Set("fromImage", repository)
+	if tag != "" && !options.All {
+		query.Set("tag", tag)
+	}
+
+	resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
+	if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
+		newAuthHeader, privilegeErr := options.PrivilegeFunc()
+		if privilegeErr != nil {
+			return nil, privilegeErr
+		}
+		resp, err = cli.tryImageCreate(ctx, query, newAuthHeader)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_push.go b/vendor/github.com/docker/engine-api/client/image_push.go
new file mode 100644
index 00000000..89191ee3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_push.go
@@ -0,0 +1,54 @@
+package client
+
+import (
+	"errors"
+	"io"
+	"net/http"
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	distreference "github.com/docker/distribution/reference"
+	"github.com/docker/engine-api/types"
+)
+
+// ImagePush requests the docker host to push an image to a remote registry.
+// It executes the privileged function if the operation is unauthorized
+// and it tries one more time.
+// It's up to the caller to handle the io.ReadCloser and close it properly.
+func (cli *Client) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) {
+	distributionRef, err := distreference.ParseNamed(ref)
+	if err != nil {
+		return nil, err
+	}
+
+	if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
+		return nil, errors.New("cannot push a digest reference")
+	}
+
+	var tag = ""
+	if nameTaggedRef, isNamedTagged := distributionRef.(distreference.NamedTagged); isNamedTagged {
+		tag = nameTaggedRef.Tag()
+	}
+
+	query := url.Values{}
+	query.Set("tag", tag)
+
+	resp, err := cli.tryImagePush(ctx, distributionRef.Name(), query, options.RegistryAuth)
+	if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
+		newAuthHeader, privilegeErr := options.PrivilegeFunc()
+		if privilegeErr != nil {
+			return nil, privilegeErr
+		}
+		resp, err = cli.tryImagePush(ctx, distributionRef.Name(), query, newAuthHeader)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, nil
+}
+
+func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
+	headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
+	return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers)
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_remove.go b/vendor/github.com/docker/engine-api/client/image_remove.go
new file mode 100644
index 00000000..47224326
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_remove.go
@@ -0,0 +1,31 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ImageRemove removes an image from the docker host.
+func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDelete, error) {
+	query := url.Values{}
+
+	if options.Force {
+		query.Set("force", "1")
+	}
+	if !options.PruneChildren {
+		query.Set("noprune", "1")
+	}
+
+	resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var dels []types.ImageDelete
+	err = json.NewDecoder(resp.body).Decode(&dels)
+	ensureReaderClosed(resp)
+	return dels, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_save.go b/vendor/github.com/docker/engine-api/client/image_save.go
new file mode 100644
index 00000000..ecac880a
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_save.go
@@ -0,0 +1,22 @@
+package client
+
+import (
+	"io"
+	"net/url"
+
+	"golang.org/x/net/context"
+)
+
+// ImageSave retrieves one or more images from the docker host as an io.ReadCloser.
+// It's up to the caller to store the images and close the stream.
+func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) {
+	query := url.Values{
+		"names": imageIDs,
+	}
+
+	resp, err := cli.get(ctx, "/images/get", query, nil)
+	if err != nil {
+		return nil, err
+	}
+	return resp.body, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_search.go b/vendor/github.com/docker/engine-api/client/image_search.go
new file mode 100644
index 00000000..3940dfd7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_search.go
@@ -0,0 +1,51 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"github.com/docker/engine-api/types/registry"
+	"golang.org/x/net/context"
+)
+
+// ImageSearch makes the docker host to search by a term in a remote registry.
+// The list of results is not sorted in any fashion.
+func (cli *Client) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) {
+	var results []registry.SearchResult
+	query := url.Values{}
+	query.Set("term", term)
+	query.Set("limit", fmt.Sprintf("%d", options.Limit))
+
+	if options.Filters.Len() > 0 {
+		filterJSON, err := filters.ToParam(options.Filters)
+		if err != nil {
+			return results, err
+		}
+		query.Set("filters", filterJSON)
+	}
+
+	resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth)
+	if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
+		newAuthHeader, privilegeErr := options.PrivilegeFunc()
+		if privilegeErr != nil {
+			return results, privilegeErr
+		}
+		resp, err = cli.tryImageSearch(ctx, query, newAuthHeader)
+	}
+	if err != nil {
+		return results, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&results)
+	ensureReaderClosed(resp)
+	return results, err
+}
+
+func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
+	headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
+	return cli.get(ctx, "/images/search", query, headers)
+}
diff --git a/vendor/github.com/docker/engine-api/client/image_tag.go b/vendor/github.com/docker/engine-api/client/image_tag.go
new file mode 100644
index 00000000..71829136
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/image_tag.go
@@ -0,0 +1,34 @@
+package client
+
+import (
+	"errors"
+	"fmt"
+	"net/url"
+
+	"golang.org/x/net/context"
+
+	distreference "github.com/docker/distribution/reference"
+	"github.com/docker/engine-api/types/reference"
+)
+
+// ImageTag tags an image in the docker host
+func (cli *Client) ImageTag(ctx context.Context, imageID, ref string) error {
+	distributionRef, err := distreference.ParseNamed(ref)
+	if err != nil {
+		return fmt.Errorf("Error parsing reference: %q is not a valid repository/tag", ref)
+	}
+
+	if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
+		return errors.New("refusing to create a tag with a digest reference")
+	}
+
+	tag := reference.GetTagFromNamedRef(distributionRef)
+
+	query := url.Values{}
+	query.Set("repo", distributionRef.Name())
+	query.Set("tag", tag)
+
+	resp, err := cli.post(ctx, "/images/"+imageID+"/tag", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/info.go b/vendor/github.com/docker/engine-api/client/info.go
new file mode 100644
index 00000000..ff0958d6
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/info.go
@@ -0,0 +1,26 @@
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// Info returns information about the docker server.
+func (cli *Client) Info(ctx context.Context) (types.Info, error) {
+	var info types.Info
+	serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)
+	if err != nil {
+		return info, err
+	}
+	defer ensureReaderClosed(serverResp)
+
+	if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil {
+		return info, fmt.Errorf("Error reading remote info: %v", err)
+	}
+
+	return info, nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/interface.go b/vendor/github.com/docker/engine-api/client/interface.go
new file mode 100644
index 00000000..1b4fa421
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/interface.go
@@ -0,0 +1,135 @@
+package client
+
+import (
+	"io"
+	"time"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/container"
+	"github.com/docker/engine-api/types/filters"
+	"github.com/docker/engine-api/types/network"
+	"github.com/docker/engine-api/types/registry"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// CommonAPIClient is the common methods between stable and experimental versions of APIClient.
+type CommonAPIClient interface {
+	ContainerAPIClient
+	ImageAPIClient
+	NodeAPIClient
+	NetworkAPIClient
+	ServiceAPIClient
+	SwarmAPIClient
+	SystemAPIClient
+	VolumeAPIClient
+	ClientVersion() string
+	ServerVersion(ctx context.Context) (types.Version, error)
+	UpdateClientVersion(v string)
+}
+
+// ContainerAPIClient defines API client methods for the containers
+type ContainerAPIClient interface {
+	ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
+	ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error)
+	ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error)
+	ContainerDiff(ctx context.Context, container string) ([]types.ContainerChange, error)
+	ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error)
+	ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error)
+	ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
+	ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error
+	ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
+	ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
+	ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error)
+	ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error)
+	ContainerKill(ctx context.Context, container, signal string) error
+	ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error)
+	ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error)
+	ContainerPause(ctx context.Context, container string) error
+	ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
+	ContainerRename(ctx context.Context, container, newContainerName string) error
+	ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
+	ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error
+	ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
+	ContainerStats(ctx context.Context, container string, stream bool) (io.ReadCloser, error)
+	ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error
+	ContainerStop(ctx context.Context, container string, timeout *time.Duration) error
+	ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error)
+	ContainerUnpause(ctx context.Context, container string) error
+	ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) error
+	ContainerWait(ctx context.Context, container string) (int, error)
+	CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
+	CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
+}
+
+// ImageAPIClient defines API client methods for the images
+type ImageAPIClient interface {
+	ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
+	ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
+	ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error)
+	ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
+	ImageInspectWithRaw(ctx context.Context, image string, getSize bool) (types.ImageInspect, []byte, error)
+	ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error)
+	ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
+	ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
+	ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
+	ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDelete, error)
+	ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
+	ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
+	ImageTag(ctx context.Context, image, ref string) error
+}
+
+// NetworkAPIClient defines API client methods for the networks
+type NetworkAPIClient interface {
+	NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
+	NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
+	NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error
+	NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error)
+	NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error)
+	NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
+	NetworkRemove(ctx context.Context, networkID string) error
+}
+
+// NodeAPIClient defines API client methods for the nodes
+type NodeAPIClient interface {
+	NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error)
+	NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error)
+	NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error
+	NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error
+}
+
+// ServiceAPIClient defines API client methods for the services
+type ServiceAPIClient interface {
+	ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error)
+	ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error)
+	ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
+	ServiceRemove(ctx context.Context, serviceID string) error
+	ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error
+	TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
+	TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
+}
+
+// SwarmAPIClient defines API client methods for the swarm
+type SwarmAPIClient interface {
+	SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error)
+	SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
+	SwarmLeave(ctx context.Context, force bool) error
+	SwarmInspect(ctx context.Context) (swarm.Swarm, error)
+	SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error
+}
+
+// SystemAPIClient defines API client methods for the system
+type SystemAPIClient interface {
+	Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error)
+	Info(ctx context.Context) (types.Info, error)
+	RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error)
+}
+
+// VolumeAPIClient defines API client methods for the volumes
+type VolumeAPIClient interface {
+	VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error)
+	VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
+	VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
+	VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error)
+	VolumeRemove(ctx context.Context, volumeID string) error
+}
diff --git a/vendor/github.com/docker/engine-api/client/interface_experimental.go b/vendor/github.com/docker/engine-api/client/interface_experimental.go
new file mode 100644
index 00000000..eb0cd7bf
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/interface_experimental.go
@@ -0,0 +1,37 @@
+// +build experimental
+
+package client
+
+import (
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// APIClient is an interface that clients that talk with a docker server must implement.
+type APIClient interface {
+	CommonAPIClient
+	CheckpointAPIClient
+	PluginAPIClient
+}
+
+// CheckpointAPIClient defines API client methods for the checkpoints
+type CheckpointAPIClient interface {
+	CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error
+	CheckpointDelete(ctx context.Context, container string, checkpointID string) error
+	CheckpointList(ctx context.Context, container string) ([]types.Checkpoint, error)
+}
+
+// PluginAPIClient defines API client methods for the plugins
+type PluginAPIClient interface {
+	PluginList(ctx context.Context) (types.PluginsListResponse, error)
+	PluginRemove(ctx context.Context, name string) error
+	PluginEnable(ctx context.Context, name string) error
+	PluginDisable(ctx context.Context, name string) error
+	PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error
+	PluginPush(ctx context.Context, name string, registryAuth string) error
+	PluginSet(ctx context.Context, name string, args []string) error
+	PluginInspect(ctx context.Context, name string) (*types.Plugin, error)
+}
+
+// Ensure that Client always implements APIClient.
+var _ APIClient = &Client{}
diff --git a/vendor/github.com/docker/engine-api/client/interface_stable.go b/vendor/github.com/docker/engine-api/client/interface_stable.go
new file mode 100644
index 00000000..496f522d
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/interface_stable.go
@@ -0,0 +1,11 @@
+// +build !experimental
+
+package client
+
+// APIClient is an interface that clients that talk with a docker server must implement.
+type APIClient interface {
+	CommonAPIClient
+}
+
+// Ensure that Client always implements APIClient.
+var _ APIClient = &Client{}
diff --git a/vendor/github.com/docker/engine-api/client/login.go b/vendor/github.com/docker/engine-api/client/login.go
new file mode 100644
index 00000000..482f9478
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/login.go
@@ -0,0 +1,28 @@
+package client
+
+import (
+	"encoding/json"
+	"net/http"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// RegistryLogin authenticates the docker server with a given docker registry.
+// It returns UnauthorizerError when the authentication fails.
+func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) {
+	resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
+
+	if resp != nil && resp.statusCode == http.StatusUnauthorized {
+		return types.AuthResponse{}, unauthorizedError{err}
+	}
+	if err != nil {
+		return types.AuthResponse{}, err
+	}
+
+	var response types.AuthResponse
+	err = json.NewDecoder(resp.body).Decode(&response)
+	ensureReaderClosed(resp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/network_connect.go b/vendor/github.com/docker/engine-api/client/network_connect.go
new file mode 100644
index 00000000..9a402a3e
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/network_connect.go
@@ -0,0 +1,18 @@
+package client
+
+import (
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/network"
+	"golang.org/x/net/context"
+)
+
+// NetworkConnect connects a container to an existent network in the docker host.
+func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error {
+	nc := types.NetworkConnect{
+		Container:      containerID,
+		EndpointConfig: config,
+	}
+	resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/network_create.go b/vendor/github.com/docker/engine-api/client/network_create.go
new file mode 100644
index 00000000..c9c0b9fd
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/network_create.go
@@ -0,0 +1,25 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// NetworkCreate creates a new network in the docker host.
+func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
+	networkCreateRequest := types.NetworkCreateRequest{
+		NetworkCreate: options,
+		Name:          name,
+	}
+	var response types.NetworkCreateResponse
+	serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil)
+	if err != nil {
+		return response, err
+	}
+
+	json.NewDecoder(serverResp.body).Decode(&response)
+	ensureReaderClosed(serverResp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/network_disconnect.go b/vendor/github.com/docker/engine-api/client/network_disconnect.go
new file mode 100644
index 00000000..a3e33672
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/network_disconnect.go
@@ -0,0 +1,14 @@
+package client
+
+import (
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// NetworkDisconnect disconnects a container from an existent network in the docker host.
+func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error {
+	nd := types.NetworkDisconnect{Container: containerID, Force: force}
+	resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nd, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/network_inspect.go b/vendor/github.com/docker/engine-api/client/network_inspect.go
new file mode 100644
index 00000000..e22fcd67
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/network_inspect.go
@@ -0,0 +1,38 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// NetworkInspect returns the information for a specific network configured in the docker host.
+func (cli *Client) NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) {
+	networkResource, _, err := cli.NetworkInspectWithRaw(ctx, networkID)
+	return networkResource, err
+}
+
+// NetworkInspectWithRaw returns the information for a specific network configured in the docker host and its raw representation.
+func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error) {
+	var networkResource types.NetworkResource
+	resp, err := cli.get(ctx, "/networks/"+networkID, nil, nil)
+	if err != nil {
+		if resp.statusCode == http.StatusNotFound {
+			return networkResource, nil, networkNotFoundError{networkID}
+		}
+		return networkResource, nil, err
+	}
+	defer ensureReaderClosed(resp)
+
+	body, err := ioutil.ReadAll(resp.body)
+	if err != nil {
+		return networkResource, nil, err
+	}
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&networkResource)
+	return networkResource, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/network_list.go b/vendor/github.com/docker/engine-api/client/network_list.go
new file mode 100644
index 00000000..05695524
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/network_list.go
@@ -0,0 +1,31 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"golang.org/x/net/context"
+)
+
+// NetworkList returns the list of networks configured in the docker host.
+func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
+	query := url.Values{}
+	if options.Filters.Len() > 0 {
+		filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
+		if err != nil {
+			return nil, err
+		}
+
+		query.Set("filters", filterJSON)
+	}
+	var networkResources []types.NetworkResource
+	resp, err := cli.get(ctx, "/networks", query, nil)
+	if err != nil {
+		return networkResources, err
+	}
+	err = json.NewDecoder(resp.body).Decode(&networkResources)
+	ensureReaderClosed(resp)
+	return networkResources, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/network_remove.go b/vendor/github.com/docker/engine-api/client/network_remove.go
new file mode 100644
index 00000000..6bd67489
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/network_remove.go
@@ -0,0 +1,10 @@
+package client
+
+import "golang.org/x/net/context"
+
+// NetworkRemove removes an existent network from the docker host.
+func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
+	resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/node_inspect.go b/vendor/github.com/docker/engine-api/client/node_inspect.go
new file mode 100644
index 00000000..5f555bb3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/node_inspect.go
@@ -0,0 +1,33 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// NodeInspectWithRaw returns the node information.
+func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) {
+	serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil)
+	if err != nil {
+		if serverResp.statusCode == http.StatusNotFound {
+			return swarm.Node{}, nil, nodeNotFoundError{nodeID}
+		}
+		return swarm.Node{}, nil, err
+	}
+	defer ensureReaderClosed(serverResp)
+
+	body, err := ioutil.ReadAll(serverResp.body)
+	if err != nil {
+		return swarm.Node{}, nil, err
+	}
+
+	var response swarm.Node
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&response)
+	return response, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/node_list.go b/vendor/github.com/docker/engine-api/client/node_list.go
new file mode 100644
index 00000000..57cf1482
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/node_list.go
@@ -0,0 +1,36 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// NodeList returns the list of nodes.
+func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
+	query := url.Values{}
+
+	if options.Filter.Len() > 0 {
+		filterJSON, err := filters.ToParam(options.Filter)
+
+		if err != nil {
+			return nil, err
+		}
+
+		query.Set("filters", filterJSON)
+	}
+
+	resp, err := cli.get(ctx, "/nodes", query, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var nodes []swarm.Node
+	err = json.NewDecoder(resp.body).Decode(&nodes)
+	ensureReaderClosed(resp)
+	return nodes, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/node_remove.go b/vendor/github.com/docker/engine-api/client/node_remove.go
new file mode 100644
index 00000000..a9cf8ba8
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/node_remove.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+
+	"golang.org/x/net/context"
+)
+
+// NodeRemove removes a Node.
+func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error {
+	query := url.Values{}
+	if options.Force {
+		query.Set("force", "1")
+	}
+
+	resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/node_update.go b/vendor/github.com/docker/engine-api/client/node_update.go
new file mode 100644
index 00000000..47222115
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/node_update.go
@@ -0,0 +1,18 @@
+package client
+
+import (
+	"net/url"
+	"strconv"
+
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// NodeUpdate updates a Node.
+func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error {
+	query := url.Values{}
+	query.Set("version", strconv.FormatUint(version.Index, 10))
+	resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, node, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_disable.go b/vendor/github.com/docker/engine-api/client/plugin_disable.go
new file mode 100644
index 00000000..893fc6e8
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_disable.go
@@ -0,0 +1,14 @@
+// +build experimental
+
+package client
+
+import (
+	"golang.org/x/net/context"
+)
+
+// PluginDisable disables a plugin
+func (cli *Client) PluginDisable(ctx context.Context, name string) error {
+	resp, err := cli.post(ctx, "/plugins/"+name+"/disable", nil, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_enable.go b/vendor/github.com/docker/engine-api/client/plugin_enable.go
new file mode 100644
index 00000000..84422abc
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_enable.go
@@ -0,0 +1,14 @@
+// +build experimental
+
+package client
+
+import (
+	"golang.org/x/net/context"
+)
+
+// PluginEnable enables a plugin
+func (cli *Client) PluginEnable(ctx context.Context, name string) error {
+	resp, err := cli.post(ctx, "/plugins/"+name+"/enable", nil, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_inspect.go b/vendor/github.com/docker/engine-api/client/plugin_inspect.go
new file mode 100644
index 00000000..b4bcc200
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_inspect.go
@@ -0,0 +1,22 @@
+// +build experimental
+
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// PluginInspect inspects an existing plugin
+func (cli *Client) PluginInspect(ctx context.Context, name string) (*types.Plugin, error) {
+	var p types.Plugin
+	resp, err := cli.get(ctx, "/plugins/"+name, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+	err = json.NewDecoder(resp.body).Decode(&p)
+	ensureReaderClosed(resp)
+	return &p, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_install.go b/vendor/github.com/docker/engine-api/client/plugin_install.go
new file mode 100644
index 00000000..3f5e59ff
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_install.go
@@ -0,0 +1,59 @@
+// +build experimental
+
+package client
+
+import (
+	"encoding/json"
+	"net/http"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// PluginInstall installs a plugin
+func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error {
+	// FIXME(vdemeester) name is a ref, we might want to parse/validate it here.
+	query := url.Values{}
+	query.Set("name", name)
+	resp, err := cli.tryPluginPull(ctx, query, options.RegistryAuth)
+	if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
+		newAuthHeader, privilegeErr := options.PrivilegeFunc()
+		if privilegeErr != nil {
+			ensureReaderClosed(resp)
+			return privilegeErr
+		}
+		resp, err = cli.tryPluginPull(ctx, query, newAuthHeader)
+	}
+	if err != nil {
+		ensureReaderClosed(resp)
+		return err
+	}
+	var privileges types.PluginPrivileges
+	if err := json.NewDecoder(resp.body).Decode(&privileges); err != nil {
+		ensureReaderClosed(resp)
+		return err
+	}
+	ensureReaderClosed(resp)
+
+	if !options.AcceptAllPermissions && options.AcceptPermissionsFunc != nil && len(privileges) > 0 {
+		accept, err := options.AcceptPermissionsFunc(privileges)
+		if err != nil {
+			return err
+		}
+		if !accept {
+			resp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil)
+			ensureReaderClosed(resp)
+			return pluginPermissionDenied{name}
+		}
+	}
+	if options.Disabled {
+		return nil
+	}
+	return cli.PluginEnable(ctx, name)
+}
+
+func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
+	headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
+	return cli.post(ctx, "/plugins/pull", query, nil, headers)
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_list.go b/vendor/github.com/docker/engine-api/client/plugin_list.go
new file mode 100644
index 00000000..7f2e2f21
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_list.go
@@ -0,0 +1,23 @@
+// +build experimental
+
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// PluginList returns the installed plugins
+func (cli *Client) PluginList(ctx context.Context) (types.PluginsListResponse, error) {
+	var plugins types.PluginsListResponse
+	resp, err := cli.get(ctx, "/plugins", nil, nil)
+	if err != nil {
+		return plugins, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&plugins)
+	ensureReaderClosed(resp)
+	return plugins, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_push.go b/vendor/github.com/docker/engine-api/client/plugin_push.go
new file mode 100644
index 00000000..3afea5ed
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_push.go
@@ -0,0 +1,15 @@
+// +build experimental
+
+package client
+
+import (
+	"golang.org/x/net/context"
+)
+
+// PluginPush pushes a plugin to a registry
+func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) error {
+	headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
+	resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_remove.go b/vendor/github.com/docker/engine-api/client/plugin_remove.go
new file mode 100644
index 00000000..baf66655
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_remove.go
@@ -0,0 +1,14 @@
+// +build experimental
+
+package client
+
+import (
+	"golang.org/x/net/context"
+)
+
+// PluginRemove removes a plugin
+func (cli *Client) PluginRemove(ctx context.Context, name string) error {
+	resp, err := cli.delete(ctx, "/plugins/"+name, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/plugin_set.go b/vendor/github.com/docker/engine-api/client/plugin_set.go
new file mode 100644
index 00000000..fb40f38b
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/plugin_set.go
@@ -0,0 +1,14 @@
+// +build experimental
+
+package client
+
+import (
+	"golang.org/x/net/context"
+)
+
+// PluginSet modifies settings for an existing plugin
+func (cli *Client) PluginSet(ctx context.Context, name string, args []string) error {
+	resp, err := cli.post(ctx, "/plugins/"+name+"/set", nil, args, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/request.go b/vendor/github.com/docker/engine-api/client/request.go
new file mode 100644
index 00000000..85490155
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/request.go
@@ -0,0 +1,207 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strings"
+
+	"github.com/docker/engine-api/client/transport/cancellable"
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/versions"
+	"golang.org/x/net/context"
+)
+
+// serverResponse is a wrapper for http API responses.
+type serverResponse struct {
+	body       io.ReadCloser
+	header     http.Header
+	statusCode int
+}
+
+// head sends an http request to the docker API using the method HEAD.
+func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendRequest(ctx, "HEAD", path, query, nil, headers)
+}
+
+// getWithContext sends an http request to the docker API using the method GET with a specific go context.
+func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendRequest(ctx, "GET", path, query, nil, headers)
+}
+
+// postWithContext sends an http request to the docker API using the method POST with a specific go context.
+func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendRequest(ctx, "POST", path, query, obj, headers)
+}
+
+func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendClientRequest(ctx, "POST", path, query, body, headers)
+}
+
+// put sends an http request to the docker API using the method PUT.
+func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendRequest(ctx, "PUT", path, query, obj, headers)
+}
+
+// put sends an http request to the docker API using the method PUT.
+func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendClientRequest(ctx, "PUT", path, query, body, headers)
+}
+
+// delete sends an http request to the docker API using the method DELETE.
+func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
+	return cli.sendRequest(ctx, "DELETE", path, query, nil, headers)
+}
+
+func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
+	var body io.Reader
+
+	if obj != nil {
+		var err error
+		body, err = encodeData(obj)
+		if err != nil {
+			return nil, err
+		}
+		if headers == nil {
+			headers = make(map[string][]string)
+		}
+		headers["Content-Type"] = []string{"application/json"}
+	}
+
+	return cli.sendClientRequest(ctx, method, path, query, body, headers)
+}
+
+func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
+	serverResp := &serverResponse{
+		body:       nil,
+		statusCode: -1,
+	}
+
+	expectedPayload := (method == "POST" || method == "PUT")
+	if expectedPayload && body == nil {
+		body = bytes.NewReader([]byte{})
+	}
+
+	req, err := cli.newRequest(method, path, query, body, headers)
+	if err != nil {
+		return serverResp, err
+	}
+
+	if cli.proto == "unix" || cli.proto == "npipe" {
+		// For local communications, it doesn't matter what the host is. We just
+		// need a valid and meaningful host name. (See #189)
+		req.Host = "docker"
+	}
+	req.URL.Host = cli.addr
+	req.URL.Scheme = cli.transport.Scheme()
+
+	if expectedPayload && req.Header.Get("Content-Type") == "" {
+		req.Header.Set("Content-Type", "text/plain")
+	}
+
+	resp, err := cancellable.Do(ctx, cli.transport, req)
+	if err != nil {
+		if isTimeout(err) || strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
+			return serverResp, ErrConnectionFailed
+		}
+
+		if !cli.transport.Secure() && strings.Contains(err.Error(), "malformed HTTP response") {
+			return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
+		}
+
+		if cli.transport.Secure() && strings.Contains(err.Error(), "bad certificate") {
+			return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
+		}
+
+		return serverResp, fmt.Errorf("An error occurred trying to connect: %v", err)
+	}
+
+	if resp != nil {
+		serverResp.statusCode = resp.StatusCode
+	}
+
+	if serverResp.statusCode < 200 || serverResp.statusCode >= 400 {
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			return serverResp, err
+		}
+		if len(body) == 0 {
+			return serverResp, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), req.URL)
+		}
+
+		var errorMessage string
+		if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) &&
+			resp.Header.Get("Content-Type") == "application/json" {
+			var errorResponse types.ErrorResponse
+			if err := json.Unmarshal(body, &errorResponse); err != nil {
+				return serverResp, fmt.Errorf("Error reading JSON: %v", err)
+			}
+			errorMessage = errorResponse.Message
+		} else {
+			errorMessage = string(body)
+		}
+
+		return serverResp, fmt.Errorf("Error response from daemon: %s", strings.TrimSpace(errorMessage))
+	}
+
+	serverResp.body = resp.Body
+	serverResp.header = resp.Header
+	return serverResp, nil
+}
+
+func (cli *Client) newRequest(method, path string, query url.Values, body io.Reader, headers map[string][]string) (*http.Request, error) {
+	apiPath := cli.getAPIPath(path, query)
+	req, err := http.NewRequest(method, apiPath, body)
+	if err != nil {
+		return nil, 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.customHTTPHeaders {
+		req.Header.Set(k, v)
+	}
+
+	if headers != nil {
+		for k, v := range headers {
+			req.Header[k] = v
+		}
+	}
+
+	return req, nil
+}
+
+func 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 ensureReaderClosed(response *serverResponse) {
+	if response != nil && response.body != nil {
+		// Drain up to 512 bytes and close the body to let the Transport reuse the connection
+		io.CopyN(ioutil.Discard, response.body, 512)
+		response.body.Close()
+	}
+}
+
+func isTimeout(err error) bool {
+	type timeout interface {
+		Timeout() bool
+	}
+	e := err
+	switch urlErr := err.(type) {
+	case *url.Error:
+		e = urlErr.Err
+	}
+	t, ok := e.(timeout)
+	return ok && t.Timeout()
+}
diff --git a/vendor/github.com/docker/engine-api/client/service_create.go b/vendor/github.com/docker/engine-api/client/service_create.go
new file mode 100644
index 00000000..7349a984
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/service_create.go
@@ -0,0 +1,30 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// ServiceCreate creates a new Service.
+func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) {
+	var headers map[string][]string
+
+	if options.EncodedRegistryAuth != "" {
+		headers = map[string][]string{
+			"X-Registry-Auth": []string{options.EncodedRegistryAuth},
+		}
+	}
+
+	var response types.ServiceCreateResponse
+	resp, err := cli.post(ctx, "/services/create", nil, service, headers)
+	if err != nil {
+		return response, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&response)
+	ensureReaderClosed(resp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/service_inspect.go b/vendor/github.com/docker/engine-api/client/service_inspect.go
new file mode 100644
index 00000000..958cd662
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/service_inspect.go
@@ -0,0 +1,33 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// ServiceInspectWithRaw returns the service information and the raw data.
+func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error) {
+	serverResp, err := cli.get(ctx, "/services/"+serviceID, nil, nil)
+	if err != nil {
+		if serverResp.statusCode == http.StatusNotFound {
+			return swarm.Service{}, nil, serviceNotFoundError{serviceID}
+		}
+		return swarm.Service{}, nil, err
+	}
+	defer ensureReaderClosed(serverResp)
+
+	body, err := ioutil.ReadAll(serverResp.body)
+	if err != nil {
+		return swarm.Service{}, nil, err
+	}
+
+	var response swarm.Service
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&response)
+	return response, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/service_list.go b/vendor/github.com/docker/engine-api/client/service_list.go
new file mode 100644
index 00000000..b48964aa
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/service_list.go
@@ -0,0 +1,35 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// ServiceList returns the list of services.
+func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
+	query := url.Values{}
+
+	if options.Filter.Len() > 0 {
+		filterJSON, err := filters.ToParam(options.Filter)
+		if err != nil {
+			return nil, err
+		}
+
+		query.Set("filters", filterJSON)
+	}
+
+	resp, err := cli.get(ctx, "/services", query, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var services []swarm.Service
+	err = json.NewDecoder(resp.body).Decode(&services)
+	ensureReaderClosed(resp)
+	return services, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/service_remove.go b/vendor/github.com/docker/engine-api/client/service_remove.go
new file mode 100644
index 00000000..a9331f92
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/service_remove.go
@@ -0,0 +1,10 @@
+package client
+
+import "golang.org/x/net/context"
+
+// ServiceRemove kills and removes a service.
+func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error {
+	resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/service_update.go b/vendor/github.com/docker/engine-api/client/service_update.go
new file mode 100644
index 00000000..ee8b4612
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/service_update.go
@@ -0,0 +1,30 @@
+package client
+
+import (
+	"net/url"
+	"strconv"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// ServiceUpdate updates a Service.
+func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error {
+	var (
+		headers map[string][]string
+		query   = url.Values{}
+	)
+
+	if options.EncodedRegistryAuth != "" {
+		headers = map[string][]string{
+			"X-Registry-Auth": []string{options.EncodedRegistryAuth},
+		}
+	}
+
+	query.Set("version", strconv.FormatUint(version.Index, 10))
+
+	resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/swarm_init.go b/vendor/github.com/docker/engine-api/client/swarm_init.go
new file mode 100644
index 00000000..68f0a744
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/swarm_init.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// SwarmInit initializes the Swarm.
+func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) {
+	serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil)
+	if err != nil {
+		return "", err
+	}
+
+	var response string
+	err = json.NewDecoder(serverResp.body).Decode(&response)
+	ensureReaderClosed(serverResp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/swarm_inspect.go b/vendor/github.com/docker/engine-api/client/swarm_inspect.go
new file mode 100644
index 00000000..d67c7c01
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/swarm_inspect.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// SwarmInspect inspects the Swarm.
+func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) {
+	serverResp, err := cli.get(ctx, "/swarm", nil, nil)
+	if err != nil {
+		return swarm.Swarm{}, err
+	}
+
+	var response swarm.Swarm
+	err = json.NewDecoder(serverResp.body).Decode(&response)
+	ensureReaderClosed(serverResp)
+	return response, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/swarm_join.go b/vendor/github.com/docker/engine-api/client/swarm_join.go
new file mode 100644
index 00000000..a9b14e0c
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/swarm_join.go
@@ -0,0 +1,13 @@
+package client
+
+import (
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// SwarmJoin joins the Swarm.
+func (cli *Client) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error {
+	resp, err := cli.post(ctx, "/swarm/join", nil, req, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/swarm_leave.go b/vendor/github.com/docker/engine-api/client/swarm_leave.go
new file mode 100644
index 00000000..a4df7321
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/swarm_leave.go
@@ -0,0 +1,18 @@
+package client
+
+import (
+	"net/url"
+
+	"golang.org/x/net/context"
+)
+
+// SwarmLeave leaves the Swarm.
+func (cli *Client) SwarmLeave(ctx context.Context, force bool) error {
+	query := url.Values{}
+	if force {
+		query.Set("force", "1")
+	}
+	resp, err := cli.post(ctx, "/swarm/leave", query, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/swarm_update.go b/vendor/github.com/docker/engine-api/client/swarm_update.go
new file mode 100644
index 00000000..5adec81c
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/swarm_update.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"fmt"
+	"net/url"
+	"strconv"
+
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// SwarmUpdate updates the Swarm.
+func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error {
+	query := url.Values{}
+	query.Set("version", strconv.FormatUint(version.Index, 10))
+	query.Set("rotateWorkerToken", fmt.Sprintf("%v", flags.RotateWorkerToken))
+	query.Set("rotateManagerToken", fmt.Sprintf("%v", flags.RotateManagerToken))
+	resp, err := cli.post(ctx, "/swarm/update", query, swarm, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/task_inspect.go b/vendor/github.com/docker/engine-api/client/task_inspect.go
new file mode 100644
index 00000000..3cac8882
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/task_inspect.go
@@ -0,0 +1,34 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/docker/engine-api/types/swarm"
+
+	"golang.org/x/net/context"
+)
+
+// TaskInspectWithRaw returns the task information and its raw representation..
+func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) {
+	serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil)
+	if err != nil {
+		if serverResp.statusCode == http.StatusNotFound {
+			return swarm.Task{}, nil, taskNotFoundError{taskID}
+		}
+		return swarm.Task{}, nil, err
+	}
+	defer ensureReaderClosed(serverResp)
+
+	body, err := ioutil.ReadAll(serverResp.body)
+	if err != nil {
+		return swarm.Task{}, nil, err
+	}
+
+	var response swarm.Task
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&response)
+	return response, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/task_list.go b/vendor/github.com/docker/engine-api/client/task_list.go
new file mode 100644
index 00000000..4604513c
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/task_list.go
@@ -0,0 +1,35 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+// TaskList returns the list of tasks.
+func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
+	query := url.Values{}
+
+	if options.Filter.Len() > 0 {
+		filterJSON, err := filters.ToParam(options.Filter)
+		if err != nil {
+			return nil, err
+		}
+
+		query.Set("filters", filterJSON)
+	}
+
+	resp, err := cli.get(ctx, "/tasks", query, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var tasks []swarm.Task
+	err = json.NewDecoder(resp.body).Decode(&tasks)
+	ensureReaderClosed(resp)
+	return tasks, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/transport/cancellable/canceler.go b/vendor/github.com/docker/engine-api/client/transport/cancellable/canceler.go
new file mode 100644
index 00000000..11dff600
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/transport/cancellable/canceler.go
@@ -0,0 +1,23 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.5
+
+package cancellable
+
+import (
+	"net/http"
+
+	"github.com/docker/engine-api/client/transport"
+)
+
+func canceler(client transport.Sender, req *http.Request) func() {
+	// TODO(djd): Respect any existing value of req.Cancel.
+	ch := make(chan struct{})
+	req.Cancel = ch
+
+	return func() {
+		close(ch)
+	}
+}
diff --git a/vendor/github.com/docker/engine-api/client/transport/cancellable/canceler_go14.go b/vendor/github.com/docker/engine-api/client/transport/cancellable/canceler_go14.go
new file mode 100644
index 00000000..8ff2845c
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/transport/cancellable/canceler_go14.go
@@ -0,0 +1,27 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.5
+
+package cancellable
+
+import (
+	"net/http"
+
+	"github.com/docker/engine-api/client/transport"
+)
+
+type requestCanceler interface {
+	CancelRequest(*http.Request)
+}
+
+func canceler(client transport.Sender, req *http.Request) func() {
+	rc, ok := client.(requestCanceler)
+	if !ok {
+		return func() {}
+	}
+	return func() {
+		rc.CancelRequest(req)
+	}
+}
diff --git a/vendor/github.com/docker/engine-api/client/transport/cancellable/cancellable.go b/vendor/github.com/docker/engine-api/client/transport/cancellable/cancellable.go
new file mode 100644
index 00000000..13941495
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/transport/cancellable/cancellable.go
@@ -0,0 +1,113 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cancellable provides helper function to cancel http requests.
+package cancellable
+
+import (
+	"io"
+	"net/http"
+
+	"github.com/docker/engine-api/client/transport"
+
+	"golang.org/x/net/context"
+)
+
+func nop() {}
+
+var (
+	testHookContextDoneBeforeHeaders = nop
+	testHookDoReturned               = nop
+	testHookDidBodyClose             = nop
+)
+
+// Do sends an HTTP request with the provided transport.Sender and returns an HTTP response.
+// If the client is nil, http.DefaultClient is used.
+// If the context is canceled or times out, ctx.Err() will be returned.
+//
+// FORK INFORMATION:
+//
+// This function deviates from the upstream version in golang.org/x/net/context/ctxhttp by
+// taking a Sender interface rather than a *http.Client directly. That allow us to use
+// this function with mocked clients and hijacked connections.
+func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.Response, error) {
+	if client == nil {
+		client = http.DefaultClient
+	}
+
+	// Request cancelation changed in Go 1.5, see canceler.go and canceler_go14.go.
+	cancel := canceler(client, req)
+
+	type responseAndError struct {
+		resp *http.Response
+		err  error
+	}
+	result := make(chan responseAndError, 1)
+
+	go func() {
+		resp, err := client.Do(req)
+		testHookDoReturned()
+		result <- responseAndError{resp, err}
+	}()
+
+	var resp *http.Response
+
+	select {
+	case <-ctx.Done():
+		testHookContextDoneBeforeHeaders()
+		cancel()
+		// Clean up after the goroutine calling client.Do:
+		go func() {
+			if r := <-result; r.resp != nil && r.resp.Body != nil {
+				testHookDidBodyClose()
+				r.resp.Body.Close()
+			}
+		}()
+		return nil, ctx.Err()
+	case r := <-result:
+		var err error
+		resp, err = r.resp, r.err
+		if err != nil {
+			return resp, err
+		}
+	}
+
+	c := make(chan struct{})
+	go func() {
+		select {
+		case <-ctx.Done():
+			cancel()
+		case <-c:
+			// The response's Body is closed.
+		}
+	}()
+	resp.Body = &notifyingReader{resp.Body, c}
+
+	return resp, nil
+}
+
+// notifyingReader is an io.ReadCloser that closes the notify channel after
+// Close is called or a Read fails on the underlying ReadCloser.
+type notifyingReader struct {
+	io.ReadCloser
+	notify chan<- struct{}
+}
+
+func (r *notifyingReader) Read(p []byte) (int, error) {
+	n, err := r.ReadCloser.Read(p)
+	if err != nil && r.notify != nil {
+		close(r.notify)
+		r.notify = nil
+	}
+	return n, err
+}
+
+func (r *notifyingReader) Close() error {
+	err := r.ReadCloser.Close()
+	if r.notify != nil {
+		close(r.notify)
+		r.notify = nil
+	}
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/client/transport/client.go b/vendor/github.com/docker/engine-api/client/transport/client.go
new file mode 100644
index 00000000..13d4b3ab
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/transport/client.go
@@ -0,0 +1,47 @@
+package transport
+
+import (
+	"crypto/tls"
+	"net/http"
+)
+
+// Sender is an interface that clients must implement
+// to be able to send requests to a remote connection.
+type Sender interface {
+	// Do sends request to a remote endpoint.
+	Do(*http.Request) (*http.Response, error)
+}
+
+// Client is an interface that abstracts all remote connections.
+type Client interface {
+	Sender
+	// Secure tells whether the connection is secure or not.
+	Secure() bool
+	// Scheme returns the connection protocol the client uses.
+	Scheme() string
+	// TLSConfig returns any TLS configuration the client uses.
+	TLSConfig() *tls.Config
+}
+
+// tlsInfo returns information about the TLS configuration.
+type tlsInfo struct {
+	tlsConfig *tls.Config
+}
+
+// TLSConfig returns the TLS configuration.
+func (t *tlsInfo) TLSConfig() *tls.Config {
+	return t.tlsConfig
+}
+
+// Scheme returns protocol scheme to use.
+func (t *tlsInfo) Scheme() string {
+	if t.tlsConfig != nil {
+		return "https"
+	}
+	return "http"
+}
+
+// Secure returns true if there is a TLS configuration.
+func (t *tlsInfo) Secure() bool {
+	return t.tlsConfig != nil
+}
diff --git a/vendor/github.com/docker/engine-api/client/transport/transport.go b/vendor/github.com/docker/engine-api/client/transport/transport.go
new file mode 100644
index 00000000..ff28af18
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/transport/transport.go
@@ -0,0 +1,57 @@
+// Package transport provides function to send request to remote endpoints.
+package transport
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/docker/go-connections/sockets"
+)
+
+// apiTransport holds information about the http transport to connect with the API.
+type apiTransport struct {
+	*http.Client
+	*tlsInfo
+	transport *http.Transport
+}
+
+// NewTransportWithHTTP creates a new transport based on the provided proto, address and http client.
+// It uses Docker's default http transport configuration if the client is nil.
+// It does not modify the client's transport if it's not nil.
+func NewTransportWithHTTP(proto, addr string, client *http.Client) (Client, error) {
+	var transport *http.Transport
+
+	if client != nil {
+		tr, ok := client.Transport.(*http.Transport)
+		if !ok {
+			return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport)
+		}
+		transport = tr
+	} else {
+		transport = defaultTransport(proto, addr)
+		client = &http.Client{
+			Transport: transport,
+		}
+	}
+
+	return &apiTransport{
+		Client:    client,
+		tlsInfo:   &tlsInfo{transport.TLSClientConfig},
+		transport: transport,
+	}, nil
+}
+
+// CancelRequest stops a request execution.
+func (a *apiTransport) CancelRequest(req *http.Request) {
+	a.transport.CancelRequest(req)
+}
+
+// defaultTransport creates a new http.Transport with Docker's
+// default transport configuration.
+func defaultTransport(proto, addr string) *http.Transport {
+	tr := new(http.Transport)
+	sockets.ConfigureTransport(tr, proto, addr)
+	return tr
+}
+
+var _ Client = &apiTransport{}
diff --git a/vendor/github.com/docker/engine-api/client/version.go b/vendor/github.com/docker/engine-api/client/version.go
new file mode 100644
index 00000000..e037551a
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/version.go
@@ -0,0 +1,21 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// ServerVersion returns information of the docker client and server host.
+func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
+	resp, err := cli.get(ctx, "/version", nil, nil)
+	if err != nil {
+		return types.Version{}, err
+	}
+
+	var server types.Version
+	err = json.NewDecoder(resp.body).Decode(&server)
+	ensureReaderClosed(resp)
+	return server, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/volume_create.go b/vendor/github.com/docker/engine-api/client/volume_create.go
new file mode 100644
index 00000000..cc1e1c17
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/volume_create.go
@@ -0,0 +1,20 @@
+package client
+
+import (
+	"encoding/json"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// VolumeCreate creates a volume in the docker host.
+func (cli *Client) VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error) {
+	var volume types.Volume
+	resp, err := cli.post(ctx, "/volumes/create", nil, options, nil)
+	if err != nil {
+		return volume, err
+	}
+	err = json.NewDecoder(resp.body).Decode(&volume)
+	ensureReaderClosed(resp)
+	return volume, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/volume_inspect.go b/vendor/github.com/docker/engine-api/client/volume_inspect.go
new file mode 100644
index 00000000..2eaebfaf
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/volume_inspect.go
@@ -0,0 +1,38 @@
+package client
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// VolumeInspect returns the information about a specific volume in the docker host.
+func (cli *Client) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) {
+	volume, _, err := cli.VolumeInspectWithRaw(ctx, volumeID)
+	return volume, err
+}
+
+// VolumeInspectWithRaw returns the information about a specific volume in the docker host and its raw representation
+func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) {
+	var volume types.Volume
+	resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil)
+	if err != nil {
+		if resp.statusCode == http.StatusNotFound {
+			return volume, nil, volumeNotFoundError{volumeID}
+		}
+		return volume, nil, err
+	}
+	defer ensureReaderClosed(resp)
+
+	body, err := ioutil.ReadAll(resp.body)
+	if err != nil {
+		return volume, nil, err
+	}
+	rdr := bytes.NewReader(body)
+	err = json.NewDecoder(rdr).Decode(&volume)
+	return volume, body, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/volume_list.go b/vendor/github.com/docker/engine-api/client/volume_list.go
new file mode 100644
index 00000000..7c6ccf83
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/volume_list.go
@@ -0,0 +1,32 @@
+package client
+
+import (
+	"encoding/json"
+	"net/url"
+
+	"github.com/docker/engine-api/types"
+	"github.com/docker/engine-api/types/filters"
+	"golang.org/x/net/context"
+)
+
+// VolumeList returns the volumes configured in the docker host.
+func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error) {
+	var volumes types.VolumesListResponse
+	query := url.Values{}
+
+	if filter.Len() > 0 {
+		filterJSON, err := filters.ToParamWithVersion(cli.version, filter)
+		if err != nil {
+			return volumes, err
+		}
+		query.Set("filters", filterJSON)
+	}
+	resp, err := cli.get(ctx, "/volumes", query, nil)
+	if err != nil {
+		return volumes, err
+	}
+
+	err = json.NewDecoder(resp.body).Decode(&volumes)
+	ensureReaderClosed(resp)
+	return volumes, err
+}
diff --git a/vendor/github.com/docker/engine-api/client/volume_remove.go b/vendor/github.com/docker/engine-api/client/volume_remove.go
new file mode 100644
index 00000000..0dce24c7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/client/volume_remove.go
@@ -0,0 +1,10 @@
+package client
+
+import "golang.org/x/net/context"
+
+// VolumeRemove removes a volume from the docker host.
+func (cli *Client) VolumeRemove(ctx context.Context, volumeID string) error {
+	resp, err := cli.delete(ctx, "/volumes/"+volumeID, nil, nil)
+	ensureReaderClosed(resp)
+	return err
+}
diff --git a/vendor/github.com/docker/engine-api/types/auth.go b/vendor/github.com/docker/engine-api/types/auth.go
new file mode 100644
index 00000000..056af6b8
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/auth.go
@@ -0,0 +1,22 @@
+package types
+
+// AuthConfig contains authorization information for connecting to a Registry
+type AuthConfig struct {
+	Username string `json:"username,omitempty"`
+	Password string `json:"password,omitempty"`
+	Auth     string `json:"auth,omitempty"`
+
+	// Email is an optional value associated with the username.
+	// This field is deprecated and will be removed in a later
+	// version of docker.
+	Email string `json:"email,omitempty"`
+
+	ServerAddress string `json:"serveraddress,omitempty"`
+
+	// IdentityToken is used to authenticate the user and get
+	// an access token for the registry.
+	IdentityToken string `json:"identitytoken,omitempty"`
+
+	// RegistryToken is a bearer token to be sent to a registry
+	RegistryToken string `json:"registrytoken,omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/blkiodev/blkio.go b/vendor/github.com/docker/engine-api/types/blkiodev/blkio.go
new file mode 100644
index 00000000..931ae10a
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/blkiodev/blkio.go
@@ -0,0 +1,23 @@
+package blkiodev
+
+import "fmt"
+
+// WeightDevice is a structure that holds device:weight pair
+type WeightDevice struct {
+	Path   string
+	Weight uint16
+}
+
+func (w *WeightDevice) String() string {
+	return fmt.Sprintf("%s:%d", w.Path, w.Weight)
+}
+
+// ThrottleDevice is a structure that holds device:rate_per_second pair
+type ThrottleDevice struct {
+	Path string
+	Rate uint64
+}
+
+func (t *ThrottleDevice) String() string {
+	return fmt.Sprintf("%s:%d", t.Path, t.Rate)
+}
diff --git a/vendor/github.com/docker/engine-api/types/client.go b/vendor/github.com/docker/engine-api/types/client.go
new file mode 100644
index 00000000..c6d244d3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/client.go
@@ -0,0 +1,291 @@
+package types
+
+import (
+	"bufio"
+	"io"
+	"net"
+
+	"github.com/docker/engine-api/types/container"
+	"github.com/docker/engine-api/types/filters"
+	"github.com/docker/go-units"
+)
+
+// CheckpointCreateOptions holds parameters to create a checkpoint from a container
+type CheckpointCreateOptions struct {
+	CheckpointID string
+	Exit         bool
+}
+
+// ContainerAttachOptions holds parameters to attach to a container.
+type ContainerAttachOptions struct {
+	Stream     bool
+	Stdin      bool
+	Stdout     bool
+	Stderr     bool
+	DetachKeys string
+}
+
+// ContainerCommitOptions holds parameters to commit changes into a container.
+type ContainerCommitOptions struct {
+	Reference string
+	Comment   string
+	Author    string
+	Changes   []string
+	Pause     bool
+	Config    *container.Config
+}
+
+// ContainerExecInspect holds information returned by exec inspect.
+type ContainerExecInspect struct {
+	ExecID      string
+	ContainerID string
+	Running     bool
+	ExitCode    int
+}
+
+// ContainerListOptions holds parameters to list containers with.
+type ContainerListOptions struct {
+	Quiet  bool
+	Size   bool
+	All    bool
+	Latest bool
+	Since  string
+	Before string
+	Limit  int
+	Filter filters.Args
+}
+
+// ContainerLogsOptions holds parameters to filter logs with.
+type ContainerLogsOptions struct {
+	ShowStdout bool
+	ShowStderr bool
+	Since      string
+	Timestamps bool
+	Follow     bool
+	Tail       string
+	Details    bool
+}
+
+// ContainerRemoveOptions holds parameters to remove containers.
+type ContainerRemoveOptions struct {
+	RemoveVolumes bool
+	RemoveLinks   bool
+	Force         bool
+}
+
+// ContainerStartOptions holds parameters to start containers.
+type ContainerStartOptions struct {
+	CheckpointID string
+}
+
+// CopyToContainerOptions holds information
+// about files to copy into a container
+type CopyToContainerOptions struct {
+	AllowOverwriteDirWithFile bool
+}
+
+// EventsOptions hold parameters to filter events with.
+type EventsOptions struct {
+	Since   string
+	Until   string
+	Filters filters.Args
+}
+
+// NetworkListOptions holds parameters to filter the list of networks with.
+type NetworkListOptions struct {
+	Filters filters.Args
+}
+
+// HijackedResponse holds connection information for a hijacked request.
+type HijackedResponse struct {
+	Conn   net.Conn
+	Reader *bufio.Reader
+}
+
+// Close closes the hijacked connection and reader.
+func (h *HijackedResponse) Close() {
+	h.Conn.Close()
+}
+
+// CloseWriter is an interface that implements structs
+// that close input streams to prevent from writing.
+type CloseWriter interface {
+	CloseWrite() error
+}
+
+// CloseWrite closes a readWriter for writing.
+func (h *HijackedResponse) CloseWrite() error {
+	if conn, ok := h.Conn.(CloseWriter); ok {
+		return conn.CloseWrite()
+	}
+	return nil
+}
+
+// ImageBuildOptions holds the information
+// necessary to build images.
+type ImageBuildOptions struct {
+	Tags           []string
+	SuppressOutput bool
+	RemoteContext  string
+	NoCache        bool
+	Remove         bool
+	ForceRemove    bool
+	PullParent     bool
+	Isolation      container.Isolation
+	CPUSetCPUs     string
+	CPUSetMems     string
+	CPUShares      int64
+	CPUQuota       int64
+	CPUPeriod      int64
+	Memory         int64
+	MemorySwap     int64
+	CgroupParent   string
+	ShmSize        int64
+	Dockerfile     string
+	Ulimits        []*units.Ulimit
+	BuildArgs      map[string]string
+	AuthConfigs    map[string]AuthConfig
+	Context        io.Reader
+	Labels         map[string]string
+}
+
+// ImageBuildResponse holds information
+// returned by a server after building
+// an image.
+type ImageBuildResponse struct {
+	Body   io.ReadCloser
+	OSType string
+}
+
+// ImageCreateOptions holds information to create images.
+type ImageCreateOptions struct {
+	RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
+}
+
+// ImageImportSource holds source information for ImageImport
+type ImageImportSource struct {
+	Source     io.Reader // Source is the data to send to the server to create this image from (mutually exclusive with SourceName)
+	SourceName string    // SourceName is the name of the image to pull (mutually exclusive with Source)
+}
+
+// ImageImportOptions holds information to import images from the client host.
+type ImageImportOptions struct {
+	Tag     string   // Tag is the name to tag this image with. This attribute is deprecated.
+	Message string   // Message is the message to tag the image with
+	Changes []string // Changes are the raw changes to apply to this image
+}
+
+// ImageListOptions holds parameters to filter the list of images with.
+type ImageListOptions struct {
+	MatchName string
+	All       bool
+	Filters   filters.Args
+}
+
+// ImageLoadResponse returns information to the client about a load process.
+type ImageLoadResponse struct {
+	// Body must be closed to avoid a resource leak
+	Body io.ReadCloser
+	JSON bool
+}
+
+// ImagePullOptions holds information to pull images.
+type ImagePullOptions struct {
+	All           bool
+	RegistryAuth  string // RegistryAuth is the base64 encoded credentials for the registry
+	PrivilegeFunc RequestPrivilegeFunc
+}
+
+// RequestPrivilegeFunc is a function interface that
+// clients can supply to retry operations after
+// getting an authorization error.
+// This function returns the registry authentication
+// header value in base 64 format, or an error
+// if the privilege request fails.
+type RequestPrivilegeFunc func() (string, error)
+
+//ImagePushOptions holds information to push images.
+type ImagePushOptions ImagePullOptions
+
+// ImageRemoveOptions holds parameters to remove images.
+type ImageRemoveOptions struct {
+	Force         bool
+	PruneChildren bool
+}
+
+// ImageSearchOptions holds parameters to search images with.
+type ImageSearchOptions struct {
+	RegistryAuth  string
+	PrivilegeFunc RequestPrivilegeFunc
+	Filters       filters.Args
+	Limit         int
+}
+
+// ResizeOptions holds parameters to resize a tty.
+// It can be used to resize container ttys and
+// exec process ttys too.
+type ResizeOptions struct {
+	Height int
+	Width  int
+}
+
+// VersionResponse holds version information for the client and the server
+type VersionResponse struct {
+	Client *Version
+	Server *Version
+}
+
+// ServerOK returns true when the client could connect to the docker server
+// and parse the information received. It returns false otherwise.
+func (v VersionResponse) ServerOK() bool {
+	return v.Server != nil
+}
+
+// NodeListOptions holds parameters to list nodes with.
+type NodeListOptions struct {
+	Filter filters.Args
+}
+
+// NodeRemoveOptions holds parameters to remove nodes with.
+type NodeRemoveOptions struct {
+	Force bool
+}
+
+// ServiceCreateOptions contains the options to use when creating a service.
+type ServiceCreateOptions struct {
+	// EncodedRegistryAuth is the encoded registry authorization credentials to
+	// use when updating the service.
+	//
+	// This field follows the format of the X-Registry-Auth header.
+	EncodedRegistryAuth string
+}
+
+// ServiceCreateResponse contains the information returned to a client
+// on the  creation of a new service.
+type ServiceCreateResponse struct {
+	// ID is the ID of the created service.
+	ID string
+}
+
+// ServiceUpdateOptions contains the options to be used for updating services.
+type ServiceUpdateOptions struct {
+	// EncodedRegistryAuth is the encoded registry authorization credentials to
+	// use when updating the service.
+	//
+	// This field follows the format of the X-Registry-Auth header.
+	EncodedRegistryAuth string
+
+	// TODO(stevvooe): Consider moving the version parameter of ServiceUpdate
+	// into this field. While it does open API users up to racy writes, most
+	// users may not need that level of consistency in practice.
+}
+
+// ServiceListOptions holds parameters to list  services with.
+type ServiceListOptions struct {
+	Filter filters.Args
+}
+
+// TaskListOptions holds parameters to list  tasks with.
+type TaskListOptions struct {
+	Filter filters.Args
+}
diff --git a/vendor/github.com/docker/engine-api/types/configs.go b/vendor/github.com/docker/engine-api/types/configs.go
new file mode 100644
index 00000000..93384b9f
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/configs.go
@@ -0,0 +1,53 @@
+package types
+
+import (
+	"github.com/docker/engine-api/types/container"
+	"github.com/docker/engine-api/types/network"
+)
+
+// configs holds structs used for internal communication between the
+// frontend (such as an http server) and the backend (such as the
+// docker daemon).
+
+// ContainerCreateConfig is the parameter set to ContainerCreate()
+type ContainerCreateConfig struct {
+	Name             string
+	Config           *container.Config
+	HostConfig       *container.HostConfig
+	NetworkingConfig *network.NetworkingConfig
+	AdjustCPUShares  bool
+}
+
+// ContainerRmConfig holds arguments for the container remove
+// operation. This struct is used to tell the backend what operations
+// to perform.
+type ContainerRmConfig struct {
+	ForceRemove, RemoveVolume, RemoveLink bool
+}
+
+// ContainerCommitConfig contains build configs for commit operation,
+// and is used when making a commit with the current state of the container.
+type ContainerCommitConfig struct {
+	Pause   bool
+	Repo    string
+	Tag     string
+	Author  string
+	Comment string
+	// merge container config into commit config before commit
+	MergeConfigs bool
+	Config       *container.Config
+}
+
+// ExecConfig is a small subset of the Config struct that holds the configuration
+// for the exec feature of docker.
+type ExecConfig struct {
+	User         string   // User that will run the command
+	Privileged   bool     // Is the container in privileged mode
+	Tty          bool     // Attach standard streams to a tty.
+	AttachStdin  bool     // Attach the standard input, makes possible user interaction
+	AttachStderr bool     // Attach the standard error
+	AttachStdout bool     // Attach the standard output
+	Detach       bool     // Execute in detach mode
+	DetachKeys   string   // Escape keys for detach
+	Cmd          []string // Execution commands and args
+}
diff --git a/vendor/github.com/docker/engine-api/types/container/config.go b/vendor/github.com/docker/engine-api/types/container/config.go
new file mode 100644
index 00000000..707fc8c1
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/container/config.go
@@ -0,0 +1,62 @@
+package container
+
+import (
+	"time"
+
+	"github.com/docker/engine-api/types/strslice"
+	"github.com/docker/go-connections/nat"
+)
+
+// HealthConfig holds configuration settings for the HEALTHCHECK feature.
+type HealthConfig struct {
+	// Test is the test to perform to check that the container is healthy.
+	// An empty slice means to inherit the default.
+	// The options are:
+	// {} : inherit healthcheck
+	// {"NONE"} : disable healthcheck
+	// {"CMD", args...} : exec arguments directly
+	// {"CMD-SHELL", command} : run command with system's default shell
+	Test []string `json:",omitempty"`
+
+	// Zero means to inherit. Durations are expressed as integer nanoseconds.
+	Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
+	Timeout  time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
+
+	// Retries is the number of consecutive failures needed to consider a container as unhealthy.
+	// Zero means inherit.
+	Retries int `json:",omitempty"`
+}
+
+// Config contains the configuration data about a container.
+// It should hold only portable information about the container.
+// Here, "portable" means "independent from the host we are running on".
+// Non-portable information *should* appear in HostConfig.
+// All fields added to this struct must be marked `omitempty` to keep getting
+// predictable hashes from the old `v1Compatibility` configuration.
+type Config struct {
+	Hostname        string                // Hostname
+	Domainname      string                // Domainname
+	User            string                // User that will run the command(s) inside the container
+	AttachStdin     bool                  // Attach the standard input, makes possible user interaction
+	AttachStdout    bool                  // Attach the standard output
+	AttachStderr    bool                  // Attach the standard error
+	ExposedPorts    map[nat.Port]struct{} `json:",omitempty"` // List of exposed ports
+	Tty             bool                  // Attach standard streams to a tty, including stdin if it is not closed.
+	OpenStdin       bool                  // Open stdin
+	StdinOnce       bool                  // If true, close stdin after the 1 attached client disconnects.
+	Env             []string              // List of environment variable to set in the container
+	Cmd             strslice.StrSlice     // Command to run when starting the container
+	Healthcheck     *HealthConfig         `json:",omitempty"` // Healthcheck describes how to check the container is healthy
+	ArgsEscaped     bool                  `json:",omitempty"` // True if command is already escaped (Windows specific)
+	Image           string                // Name of the image as it was passed by the operator (eg. could be symbolic)
+	Volumes         map[string]struct{}   // List of volumes (mounts) used for the container
+	WorkingDir      string                // Current directory (PWD) in the command will be launched
+	Entrypoint      strslice.StrSlice     // Entrypoint to run when starting the container
+	NetworkDisabled bool                  `json:",omitempty"` // Is network disabled
+	MacAddress      string                `json:",omitempty"` // Mac Address of the container
+	OnBuild         []string              // ONBUILD metadata that were defined on the image Dockerfile
+	Labels          map[string]string     // List of labels set to this container
+	StopSignal      string                `json:",omitempty"` // Signal to stop a container
+	StopTimeout     *int                  `json:",omitempty"` // Timeout (in seconds) to stop a container
+	Shell           strslice.StrSlice     `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
+}
diff --git a/vendor/github.com/docker/engine-api/types/container/host_config.go b/vendor/github.com/docker/engine-api/types/container/host_config.go
new file mode 100644
index 00000000..a9ff755b
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/container/host_config.go
@@ -0,0 +1,320 @@
+package container
+
+import (
+	"strings"
+
+	"github.com/docker/engine-api/types/blkiodev"
+	"github.com/docker/engine-api/types/strslice"
+	"github.com/docker/go-connections/nat"
+	"github.com/docker/go-units"
+)
+
+// NetworkMode represents the container network stack.
+type NetworkMode string
+
+// Isolation represents the isolation technology of a container. The supported
+// values are platform specific
+type Isolation string
+
+// IsDefault indicates the default isolation technology of a container. On Linux this
+// is the native driver. On Windows, this is a Windows Server Container.
+func (i Isolation) IsDefault() bool {
+	return strings.ToLower(string(i)) == "default" || string(i) == ""
+}
+
+// IpcMode represents the container ipc stack.
+type IpcMode string
+
+// IsPrivate indicates whether the container uses its private ipc stack.
+func (n IpcMode) IsPrivate() bool {
+	return !(n.IsHost() || n.IsContainer())
+}
+
+// IsHost indicates whether the container uses the host's ipc stack.
+func (n IpcMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsContainer indicates whether the container uses a container's ipc stack.
+func (n IpcMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// Valid indicates whether the ipc stack is valid.
+func (n IpcMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	case "container":
+		if len(parts) != 2 || parts[1] == "" {
+			return false
+		}
+	default:
+		return false
+	}
+	return true
+}
+
+// Container returns the name of the container ipc stack is going to be used.
+func (n IpcMode) Container() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+// UsernsMode represents userns mode in the container.
+type UsernsMode string
+
+// IsHost indicates whether the container uses the host's userns.
+func (n UsernsMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsPrivate indicates whether the container uses the a private userns.
+func (n UsernsMode) IsPrivate() bool {
+	return !(n.IsHost())
+}
+
+// Valid indicates whether the userns is valid.
+func (n UsernsMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	default:
+		return false
+	}
+	return true
+}
+
+// CgroupSpec represents the cgroup to use for the container.
+type CgroupSpec string
+
+// IsContainer indicates whether the container is using another container cgroup
+func (c CgroupSpec) IsContainer() bool {
+	parts := strings.SplitN(string(c), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// Valid indicates whether the cgroup spec is valid.
+func (c CgroupSpec) Valid() bool {
+	return c.IsContainer() || c == ""
+}
+
+// Container returns the name of the container whose cgroup will be used.
+func (c CgroupSpec) Container() string {
+	parts := strings.SplitN(string(c), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+// UTSMode represents the UTS namespace of the container.
+type UTSMode string
+
+// IsPrivate indicates whether the container uses its private UTS namespace.
+func (n UTSMode) IsPrivate() bool {
+	return !(n.IsHost())
+}
+
+// IsHost indicates whether the container uses the host's UTS namespace.
+func (n UTSMode) IsHost() bool {
+	return n == "host"
+}
+
+// Valid indicates whether the UTS namespace is valid.
+func (n UTSMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	default:
+		return false
+	}
+	return true
+}
+
+// PidMode represents the pid namespace of the container.
+type PidMode string
+
+// IsPrivate indicates whether the container uses its own new pid namespace.
+func (n PidMode) IsPrivate() bool {
+	return !(n.IsHost() || n.IsContainer())
+}
+
+// IsHost indicates whether the container uses the host's pid namespace.
+func (n PidMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsContainer indicates whether the container uses a container's pid namespace.
+func (n PidMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// Valid indicates whether the pid namespace is valid.
+func (n PidMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	case "container":
+		if len(parts) != 2 || parts[1] == "" {
+			return false
+		}
+	default:
+		return false
+	}
+	return true
+}
+
+// Container returns the name of the container whose pid namespace is going to be used.
+func (n PidMode) Container() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+// DeviceMapping represents the device mapping between the host and the container.
+type DeviceMapping struct {
+	PathOnHost        string
+	PathInContainer   string
+	CgroupPermissions string
+}
+
+// RestartPolicy represents the restart policies of the container.
+type RestartPolicy struct {
+	Name              string
+	MaximumRetryCount int
+}
+
+// IsNone indicates whether the container has the "no" restart policy.
+// This means the container will not automatically restart when exiting.
+func (rp *RestartPolicy) IsNone() bool {
+	return rp.Name == "no" || rp.Name == ""
+}
+
+// IsAlways indicates whether the container has the "always" restart policy.
+// This means the container will automatically restart regardless of the exit status.
+func (rp *RestartPolicy) IsAlways() bool {
+	return rp.Name == "always"
+}
+
+// IsOnFailure indicates whether the container has the "on-failure" restart policy.
+// This means the container will automatically restart of exiting with a non-zero exit status.
+func (rp *RestartPolicy) IsOnFailure() bool {
+	return rp.Name == "on-failure"
+}
+
+// IsUnlessStopped indicates whether the container has the
+// "unless-stopped" restart policy. This means the container will
+// automatically restart unless user has put it to stopped state.
+func (rp *RestartPolicy) IsUnlessStopped() bool {
+	return rp.Name == "unless-stopped"
+}
+
+// IsSame compares two RestartPolicy to see if they are the same
+func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
+	return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
+}
+
+// LogConfig represents the logging configuration of the container.
+type LogConfig struct {
+	Type   string
+	Config map[string]string
+}
+
+// Resources contains container's resources (cgroups config, ulimits...)
+type Resources struct {
+	// Applicable to all platforms
+	CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
+	Memory    int64 // Memory limit (in bytes)
+
+	// Applicable to UNIX platforms
+	CgroupParent         string // Parent cgroup.
+	BlkioWeight          uint16 // Block IO weight (relative weight vs. other containers)
+	BlkioWeightDevice    []*blkiodev.WeightDevice
+	BlkioDeviceReadBps   []*blkiodev.ThrottleDevice
+	BlkioDeviceWriteBps  []*blkiodev.ThrottleDevice
+	BlkioDeviceReadIOps  []*blkiodev.ThrottleDevice
+	BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice
+	CPUPeriod            int64           `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
+	CPUQuota             int64           `json:"CpuQuota"`  // CPU CFS (Completely Fair Scheduler) quota
+	CpusetCpus           string          // CpusetCpus 0-2, 0,1
+	CpusetMems           string          // CpusetMems 0-2, 0,1
+	Devices              []DeviceMapping // List of devices to map inside the container
+	DiskQuota            int64           // Disk limit (in bytes)
+	KernelMemory         int64           // Kernel memory limit (in bytes)
+	MemoryReservation    int64           // Memory soft limit (in bytes)
+	MemorySwap           int64           // Total memory usage (memory + swap); set `-1` to enable unlimited swap
+	MemorySwappiness     *int64          // Tuning container memory swappiness behaviour
+	OomKillDisable       *bool           // Whether to disable OOM Killer or not
+	PidsLimit            int64           // Setting pids limit for a container
+	Ulimits              []*units.Ulimit // List of ulimits to be set in the container
+
+	// Applicable to Windows
+	CPUCount           int64  `json:"CpuCount"`   // CPU count
+	CPUPercent         int64  `json:"CpuPercent"` // CPU percent
+	IOMaximumIOps      uint64 // Maximum IOps for the container system drive
+	IOMaximumBandwidth uint64 // Maximum IO in bytes per second for the container system drive
+}
+
+// UpdateConfig holds the mutable attributes of a Container.
+// Those attributes can be updated at runtime.
+type UpdateConfig struct {
+	// Contains container's resources (cgroups, ulimits)
+	Resources
+	RestartPolicy RestartPolicy
+}
+
+// HostConfig the non-portable Config structure of a container.
+// Here, "non-portable" means "dependent of the host we are running on".
+// Portable information *should* appear in Config.
+type HostConfig struct {
+	// Applicable to all platforms
+	Binds           []string      // List of volume bindings for this container
+	ContainerIDFile string        // File (path) where the containerId is written
+	LogConfig       LogConfig     // Configuration of the logs for this container
+	NetworkMode     NetworkMode   // Network mode to use for the container
+	PortBindings    nat.PortMap   // Port mapping between the exposed port (container) and the host
+	RestartPolicy   RestartPolicy // Restart policy to be used for the container
+	AutoRemove      bool          // Automatically remove container when it exits
+	VolumeDriver    string        // Name of the volume driver used to mount volumes
+	VolumesFrom     []string      // List of volumes to take from other container
+
+	// Applicable to UNIX platforms
+	CapAdd          strslice.StrSlice // List of kernel capabilities to add to the container
+	CapDrop         strslice.StrSlice // List of kernel capabilities to remove from the container
+	DNS             []string          `json:"Dns"`        // List of DNS server to lookup
+	DNSOptions      []string          `json:"DnsOptions"` // List of DNSOption to look for
+	DNSSearch       []string          `json:"DnsSearch"`  // List of DNSSearch to look for
+	ExtraHosts      []string          // List of extra hosts
+	GroupAdd        []string          // List of additional groups that the container process will run as
+	IpcMode         IpcMode           // IPC namespace to use for the container
+	Cgroup          CgroupSpec        // Cgroup to use for the container
+	Links           []string          // List of links (in the name:alias form)
+	OomScoreAdj     int               // Container preference for OOM-killing
+	PidMode         PidMode           // PID namespace to use for the container
+	Privileged      bool              // Is the container in privileged mode
+	PublishAllPorts bool              // Should docker publish all exposed port for the container
+	ReadonlyRootfs  bool              // Is the container root filesystem in read-only
+	SecurityOpt     []string          // List of string values to customize labels for MLS systems, such as SELinux.
+	StorageOpt      map[string]string `json:",omitempty"` // Storage driver options per container.
+	Tmpfs           map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
+	UTSMode         UTSMode           // UTS namespace to use for the container
+	UsernsMode      UsernsMode        // The user namespace to use for the container
+	ShmSize         int64             // Total shm memory usage
+	Sysctls         map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container
+	Runtime         string            `json:",omitempty"` // Runtime to use with this container
+
+	// Applicable to Windows
+	ConsoleSize [2]int    // Initial console size
+	Isolation   Isolation // Isolation technology of the container (eg default, hyperv)
+
+	// Contains container's resources (cgroups, ulimits)
+	Resources
+}
diff --git a/vendor/github.com/docker/engine-api/types/container/hostconfig_unix.go b/vendor/github.com/docker/engine-api/types/container/hostconfig_unix.go
new file mode 100644
index 00000000..4171059a
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/container/hostconfig_unix.go
@@ -0,0 +1,81 @@
+// +build !windows
+
+package container
+
+import "strings"
+
+// IsValid indicates if an isolation technology is valid
+func (i Isolation) IsValid() bool {
+	return i.IsDefault()
+}
+
+// IsPrivate indicates whether container uses it's private network stack.
+func (n NetworkMode) IsPrivate() bool {
+	return !(n.IsHost() || n.IsContainer())
+}
+
+// IsDefault indicates whether container uses the default network stack.
+func (n NetworkMode) IsDefault() bool {
+	return n == "default"
+}
+
+// NetworkName returns the name of the network stack.
+func (n NetworkMode) NetworkName() string {
+	if n.IsBridge() {
+		return "bridge"
+	} else if n.IsHost() {
+		return "host"
+	} else if n.IsContainer() {
+		return "container"
+	} else if n.IsNone() {
+		return "none"
+	} else if n.IsDefault() {
+		return "default"
+	} else if n.IsUserDefined() {
+		return n.UserDefined()
+	}
+	return ""
+}
+
+// IsBridge indicates whether container uses the bridge network stack
+func (n NetworkMode) IsBridge() bool {
+	return n == "bridge"
+}
+
+// IsHost indicates whether container uses the host network stack.
+func (n NetworkMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsContainer indicates whether container uses a container network stack.
+func (n NetworkMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// IsNone indicates whether container isn't using a network stack.
+func (n NetworkMode) IsNone() bool {
+	return n == "none"
+}
+
+// ConnectedContainer is the id of the container which network this container is connected to.
+func (n NetworkMode) ConnectedContainer() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+// IsUserDefined indicates user-created network
+func (n NetworkMode) IsUserDefined() bool {
+	return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
+}
+
+//UserDefined indicates user-created network
+func (n NetworkMode) UserDefined() string {
+	if n.IsUserDefined() {
+		return string(n)
+	}
+	return ""
+}
diff --git a/vendor/github.com/docker/engine-api/types/container/hostconfig_windows.go b/vendor/github.com/docker/engine-api/types/container/hostconfig_windows.go
new file mode 100644
index 00000000..0ee332ba
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/container/hostconfig_windows.go
@@ -0,0 +1,87 @@
+package container
+
+import (
+	"strings"
+)
+
+// IsDefault indicates whether container uses the default network stack.
+func (n NetworkMode) IsDefault() bool {
+	return n == "default"
+}
+
+// IsNone indicates whether container isn't using a network stack.
+func (n NetworkMode) IsNone() bool {
+	return n == "none"
+}
+
+// IsContainer indicates whether container uses a container network stack.
+// Returns false as windows doesn't support this mode
+func (n NetworkMode) IsContainer() bool {
+	return false
+}
+
+// IsBridge indicates whether container uses the bridge network stack
+// in windows it is given the name NAT
+func (n NetworkMode) IsBridge() bool {
+	return n == "nat"
+}
+
+// IsHost indicates whether container uses the host network stack.
+// returns false as this is not supported by windows
+func (n NetworkMode) IsHost() bool {
+	return false
+}
+
+// IsPrivate indicates whether container uses its private network stack.
+func (n NetworkMode) IsPrivate() bool {
+	return !(n.IsHost() || n.IsContainer())
+}
+
+// ConnectedContainer is the id of the container which network this container is connected to.
+// Returns blank string on windows
+func (n NetworkMode) ConnectedContainer() string {
+	return ""
+}
+
+// IsUserDefined indicates user-created network
+func (n NetworkMode) IsUserDefined() bool {
+	return !n.IsDefault() && !n.IsNone() && !n.IsBridge()
+}
+
+// IsHyperV indicates the use of a Hyper-V partition for isolation
+func (i Isolation) IsHyperV() bool {
+	return strings.ToLower(string(i)) == "hyperv"
+}
+
+// IsProcess indicates the use of process isolation
+func (i Isolation) IsProcess() bool {
+	return strings.ToLower(string(i)) == "process"
+}
+
+// IsValid indicates if an isolation technology is valid
+func (i Isolation) IsValid() bool {
+	return i.IsDefault() || i.IsHyperV() || i.IsProcess()
+}
+
+// NetworkName returns the name of the network stack.
+func (n NetworkMode) NetworkName() string {
+	if n.IsDefault() {
+		return "default"
+	} else if n.IsBridge() {
+		return "nat"
+	} else if n.IsNone() {
+		return "none"
+	} else if n.IsUserDefined() {
+		return n.UserDefined()
+	}
+
+	return ""
+}
+
+//UserDefined indicates user-created network
+func (n NetworkMode) UserDefined() string {
+	if n.IsUserDefined() {
+		return string(n)
+	}
+	return ""
+}
diff --git a/vendor/github.com/docker/engine-api/types/errors.go b/vendor/github.com/docker/engine-api/types/errors.go
new file mode 100644
index 00000000..649ab951
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/errors.go
@@ -0,0 +1,6 @@
+package types
+
+// ErrorResponse is the response body of API errors.
+type ErrorResponse struct {
+	Message string `json:"message"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/filters/parse.go b/vendor/github.com/docker/engine-api/types/filters/parse.go
new file mode 100644
index 00000000..dc2c48b8
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/filters/parse.go
@@ -0,0 +1,307 @@
+// Package filters provides helper function to parse and handle command line
+// filter, used for example in docker ps or docker images commands.
+package filters
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"regexp"
+	"strings"
+
+	"github.com/docker/engine-api/types/versions"
+)
+
+// Args stores filter arguments as map key:{map key: bool}.
+// It contains an aggregation of the map of arguments (which are in the form
+// of -f 'key=value') based on the key, and stores values for the same key
+// in a map with string keys and boolean values.
+// e.g given -f 'label=label1=1' -f 'label=label2=2' -f 'image.name=ubuntu'
+// the args will be {"image.name":{"ubuntu":true},"label":{"label1=1":true,"label2=2":true}}
+type Args struct {
+	fields map[string]map[string]bool
+}
+
+// NewArgs initializes a new Args struct.
+func NewArgs() Args {
+	return Args{fields: map[string]map[string]bool{}}
+}
+
+// ParseFlag parses the argument to the filter flag. Like
+//
+//   `docker ps -f 'created=today' -f 'image.name=ubuntu*'`
+//
+// If prev map is provided, then it is appended to, and returned. By default a new
+// map is created.
+func ParseFlag(arg string, prev Args) (Args, error) {
+	filters := prev
+	if len(arg) == 0 {
+		return filters, nil
+	}
+
+	if !strings.Contains(arg, "=") {
+		return filters, ErrBadFormat
+	}
+
+	f := strings.SplitN(arg, "=", 2)
+
+	name := strings.ToLower(strings.TrimSpace(f[0]))
+	value := strings.TrimSpace(f[1])
+
+	filters.Add(name, value)
+
+	return filters, nil
+}
+
+// ErrBadFormat is an error returned in case of bad format for a filter.
+var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
+
+// ToParam packs the Args into a string for easy transport from client to server.
+func ToParam(a Args) (string, error) {
+	// this way we don't URL encode {}, just empty space
+	if a.Len() == 0 {
+		return "", nil
+	}
+
+	buf, err := json.Marshal(a.fields)
+	if err != nil {
+		return "", err
+	}
+	return string(buf), nil
+}
+
+// ToParamWithVersion packs the Args into a string for easy transport from client to server.
+// The generated string will depend on the specified version (corresponding to the API version).
+func ToParamWithVersion(version string, a Args) (string, error) {
+	// this way we don't URL encode {}, just empty space
+	if a.Len() == 0 {
+		return "", nil
+	}
+
+	// for daemons older than v1.10, filter must be of the form map[string][]string
+	buf := []byte{}
+	err := errors.New("")
+	if version != "" && versions.LessThan(version, "1.22") {
+		buf, err = json.Marshal(convertArgsToSlice(a.fields))
+	} else {
+		buf, err = json.Marshal(a.fields)
+	}
+	if err != nil {
+		return "", err
+	}
+	return string(buf), nil
+}
+
+// FromParam unpacks the filter Args.
+func FromParam(p string) (Args, error) {
+	if len(p) == 0 {
+		return NewArgs(), nil
+	}
+
+	r := strings.NewReader(p)
+	d := json.NewDecoder(r)
+
+	m := map[string]map[string]bool{}
+	if err := d.Decode(&m); err != nil {
+		r.Seek(0, 0)
+
+		// Allow parsing old arguments in slice format.
+		// Because other libraries might be sending them in this format.
+		deprecated := map[string][]string{}
+		if deprecatedErr := d.Decode(&deprecated); deprecatedErr == nil {
+			m = deprecatedArgs(deprecated)
+		} else {
+			return NewArgs(), err
+		}
+	}
+	return Args{m}, nil
+}
+
+// Get returns the list of values associates with a field.
+// It returns a slice of strings to keep backwards compatibility with old code.
+func (filters Args) Get(field string) []string {
+	values := filters.fields[field]
+	if values == nil {
+		return make([]string, 0)
+	}
+	slice := make([]string, 0, len(values))
+	for key := range values {
+		slice = append(slice, key)
+	}
+	return slice
+}
+
+// Add adds a new value to a filter field.
+func (filters Args) Add(name, value string) {
+	if _, ok := filters.fields[name]; ok {
+		filters.fields[name][value] = true
+	} else {
+		filters.fields[name] = map[string]bool{value: true}
+	}
+}
+
+// Del removes a value from a filter field.
+func (filters Args) Del(name, value string) {
+	if _, ok := filters.fields[name]; ok {
+		delete(filters.fields[name], value)
+	}
+}
+
+// Len returns the number of fields in the arguments.
+func (filters Args) Len() int {
+	return len(filters.fields)
+}
+
+// MatchKVList returns true if the values for the specified field matches the ones
+// from the sources.
+// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
+//      field is 'label' and sources are {'label1': '1', 'label2': '2'}
+//      it returns true.
+func (filters Args) MatchKVList(field string, sources map[string]string) bool {
+	fieldValues := filters.fields[field]
+
+	//do not filter if there is no filter set or cannot determine filter
+	if len(fieldValues) == 0 {
+		return true
+	}
+
+	if sources == nil || len(sources) == 0 {
+		return false
+	}
+
+	for name2match := range fieldValues {
+		testKV := strings.SplitN(name2match, "=", 2)
+
+		v, ok := sources[testKV[0]]
+		if !ok {
+			return false
+		}
+		if len(testKV) == 2 && testKV[1] != v {
+			return false
+		}
+	}
+
+	return true
+}
+
+// Match returns true if the values for the specified field matches the source string
+// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
+//      field is 'image.name' and source is 'ubuntu'
+//      it returns true.
+func (filters Args) Match(field, source string) bool {
+	if filters.ExactMatch(field, source) {
+		return true
+	}
+
+	fieldValues := filters.fields[field]
+	for name2match := range fieldValues {
+		match, err := regexp.MatchString(name2match, source)
+		if err != nil {
+			continue
+		}
+		if match {
+			return true
+		}
+	}
+	return false
+}
+
+// ExactMatch returns true if the source matches exactly one of the filters.
+func (filters Args) ExactMatch(field, source string) bool {
+	fieldValues, ok := filters.fields[field]
+	//do not filter if there is no filter set or cannot determine filter
+	if !ok || len(fieldValues) == 0 {
+		return true
+	}
+
+	// try to match full name value to avoid O(N) regular expression matching
+	return fieldValues[source]
+}
+
+// UniqueExactMatch returns true if there is only one filter and the source matches exactly this one.
+func (filters Args) UniqueExactMatch(field, source string) bool {
+	fieldValues := filters.fields[field]
+	//do not filter if there is no filter set or cannot determine filter
+	if len(fieldValues) == 0 {
+		return true
+	}
+	if len(filters.fields[field]) != 1 {
+		return false
+	}
+
+	// try to match full name value to avoid O(N) regular expression matching
+	return fieldValues[source]
+}
+
+// FuzzyMatch returns true if the source matches exactly one of the filters,
+// or the source has one of the filters as a prefix.
+func (filters Args) FuzzyMatch(field, source string) bool {
+	if filters.ExactMatch(field, source) {
+		return true
+	}
+
+	fieldValues := filters.fields[field]
+	for prefix := range fieldValues {
+		if strings.HasPrefix(source, prefix) {
+			return true
+		}
+	}
+	return false
+}
+
+// Include returns true if the name of the field to filter is in the filters.
+func (filters Args) Include(field string) bool {
+	_, ok := filters.fields[field]
+	return ok
+}
+
+// Validate ensures that all the fields in the filter are valid.
+// It returns an error as soon as it finds an invalid field.
+func (filters Args) Validate(accepted map[string]bool) error {
+	for name := range filters.fields {
+		if !accepted[name] {
+			return fmt.Errorf("Invalid filter '%s'", name)
+		}
+	}
+	return nil
+}
+
+// WalkValues iterates over the list of filtered values for a field.
+// It stops the iteration if it finds an error and it returns that error.
+func (filters Args) WalkValues(field string, op func(value string) error) error {
+	if _, ok := filters.fields[field]; !ok {
+		return nil
+	}
+	for v := range filters.fields[field] {
+		if err := op(v); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
+	m := map[string]map[string]bool{}
+	for k, v := range d {
+		values := map[string]bool{}
+		for _, vv := range v {
+			values[vv] = true
+		}
+		m[k] = values
+	}
+	return m
+}
+
+func convertArgsToSlice(f map[string]map[string]bool) map[string][]string {
+	m := map[string][]string{}
+	for k, v := range f {
+		values := []string{}
+		for kk := range v {
+			if v[kk] {
+				values = append(values, kk)
+			}
+		}
+		m[k] = values
+	}
+	return m
+}
diff --git a/vendor/github.com/docker/engine-api/types/network/network.go b/vendor/github.com/docker/engine-api/types/network/network.go
new file mode 100644
index 00000000..47080b65
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/network/network.go
@@ -0,0 +1,53 @@
+package network
+
+// Address represents an IP address
+type Address struct {
+	Addr      string
+	PrefixLen int
+}
+
+// IPAM represents IP Address Management
+type IPAM struct {
+	Driver  string
+	Options map[string]string //Per network IPAM driver options
+	Config  []IPAMConfig
+}
+
+// IPAMConfig represents IPAM configurations
+type IPAMConfig struct {
+	Subnet     string            `json:",omitempty"`
+	IPRange    string            `json:",omitempty"`
+	Gateway    string            `json:",omitempty"`
+	AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
+}
+
+// EndpointIPAMConfig represents IPAM configurations for the endpoint
+type EndpointIPAMConfig struct {
+	IPv4Address  string   `json:",omitempty"`
+	IPv6Address  string   `json:",omitempty"`
+	LinkLocalIPs []string `json:",omitempty"`
+}
+
+// EndpointSettings stores the network endpoint details
+type EndpointSettings struct {
+	// Configurations
+	IPAMConfig *EndpointIPAMConfig
+	Links      []string
+	Aliases    []string
+	// Operational data
+	NetworkID           string
+	EndpointID          string
+	Gateway             string
+	IPAddress           string
+	IPPrefixLen         int
+	IPv6Gateway         string
+	GlobalIPv6Address   string
+	GlobalIPv6PrefixLen int
+	MacAddress          string
+}
+
+// NetworkingConfig represents the container's networking configuration for each of its interfaces
+// Carries the networking configs specified in the `docker run` and `docker network connect` commands
+type NetworkingConfig struct {
+	EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network
+}
diff --git a/vendor/github.com/docker/engine-api/types/plugin.go b/vendor/github.com/docker/engine-api/types/plugin.go
new file mode 100644
index 00000000..05030ff3
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/plugin.go
@@ -0,0 +1,169 @@
+// +build experimental
+
+package types
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+// PluginInstallOptions holds parameters to install a plugin.
+type PluginInstallOptions struct {
+	Disabled              bool
+	AcceptAllPermissions  bool
+	RegistryAuth          string // RegistryAuth is the base64 encoded credentials for the registry
+	PrivilegeFunc         RequestPrivilegeFunc
+	AcceptPermissionsFunc func(PluginPrivileges) (bool, error)
+}
+
+// PluginConfig represents the values of settings potentially modifiable by a user
+type PluginConfig struct {
+	Mounts  []PluginMount
+	Env     []string
+	Args    []string
+	Devices []PluginDevice
+}
+
+// Plugin represents a Docker plugin for the remote API
+type Plugin struct {
+	ID       string `json:"Id,omitempty"`
+	Name     string
+	Tag      string
+	Active   bool
+	Config   PluginConfig
+	Manifest PluginManifest
+}
+
+// PluginsListResponse contains the response for the remote API
+type PluginsListResponse []*Plugin
+
+const (
+	authzDriver   = "AuthzDriver"
+	graphDriver   = "GraphDriver"
+	ipamDriver    = "IpamDriver"
+	networkDriver = "NetworkDriver"
+	volumeDriver  = "VolumeDriver"
+)
+
+// PluginInterfaceType represents a type that a plugin implements.
+type PluginInterfaceType struct {
+	Prefix     string // This is always "docker"
+	Capability string // Capability should be validated against the above list.
+	Version    string // Plugin API version. Depends on the capability
+}
+
+// UnmarshalJSON implements json.Unmarshaler for PluginInterfaceType
+func (t *PluginInterfaceType) UnmarshalJSON(p []byte) error {
+	versionIndex := len(p)
+	prefixIndex := 0
+	if len(p) < 2 || p[0] != '"' || p[len(p)-1] != '"' {
+		return fmt.Errorf("%q is not a plugin interface type", p)
+	}
+	p = p[1 : len(p)-1]
+loop:
+	for i, b := range p {
+		switch b {
+		case '.':
+			prefixIndex = i
+		case '/':
+			versionIndex = i
+			break loop
+		}
+	}
+	t.Prefix = string(p[:prefixIndex])
+	t.Capability = string(p[prefixIndex+1 : versionIndex])
+	if versionIndex < len(p) {
+		t.Version = string(p[versionIndex+1:])
+	}
+	return nil
+}
+
+// MarshalJSON implements json.Marshaler for PluginInterfaceType
+func (t *PluginInterfaceType) MarshalJSON() ([]byte, error) {
+	return json.Marshal(t.String())
+}
+
+// String implements fmt.Stringer for PluginInterfaceType
+func (t PluginInterfaceType) String() string {
+	return fmt.Sprintf("%s.%s/%s", t.Prefix, t.Capability, t.Version)
+}
+
+// PluginInterface describes the interface between Docker and plugin
+type PluginInterface struct {
+	Types  []PluginInterfaceType
+	Socket string
+}
+
+// PluginSetting is to be embedded in other structs, if they are supposed to be
+// modifiable by the user.
+type PluginSetting struct {
+	Name        string
+	Description string
+	Settable    []string
+}
+
+// PluginNetwork represents the network configuration for a plugin
+type PluginNetwork struct {
+	Type string
+}
+
+// PluginMount represents the mount configuration for a plugin
+type PluginMount struct {
+	PluginSetting
+	Source      *string
+	Destination string
+	Type        string
+	Options     []string
+}
+
+// PluginEnv represents an environment variable for a plugin
+type PluginEnv struct {
+	PluginSetting
+	Value *string
+}
+
+// PluginArgs represents the command line arguments for a plugin
+type PluginArgs struct {
+	PluginSetting
+	Value []string
+}
+
+// PluginDevice represents a device for a plugin
+type PluginDevice struct {
+	PluginSetting
+	Path *string
+}
+
+// PluginUser represents the user for the plugin's process
+type PluginUser struct {
+	UID uint32 `json:"Uid,omitempty"`
+	GID uint32 `json:"Gid,omitempty"`
+}
+
+// PluginManifest represents the manifest of a plugin
+type PluginManifest struct {
+	ManifestVersion string
+	Description     string
+	Documentation   string
+	Interface       PluginInterface
+	Entrypoint      []string
+	Workdir         string
+	User            PluginUser `json:",omitempty"`
+	Network         PluginNetwork
+	Capabilities    []string
+	Mounts          []PluginMount
+	Devices         []PluginDevice
+	Env             []PluginEnv
+	Args            PluginArgs
+}
+
+// PluginPrivilege describes a permission the user has to accept
+// upon installing a plugin.
+type PluginPrivilege struct {
+	Name        string
+	Description string
+	Value       []string
+}
+
+// PluginPrivileges is a list of PluginPrivilege
+type PluginPrivileges []PluginPrivilege
diff --git a/vendor/github.com/docker/engine-api/types/reference/image_reference.go b/vendor/github.com/docker/engine-api/types/reference/image_reference.go
new file mode 100644
index 00000000..be9cf8eb
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/reference/image_reference.go
@@ -0,0 +1,34 @@
+package reference
+
+import (
+	distreference "github.com/docker/distribution/reference"
+)
+
+// Parse parses the given references and returns the repository and
+// tag (if present) from it. If there is an error during parsing, it will
+// return an error.
+func Parse(ref string) (string, string, error) {
+	distributionRef, err := distreference.ParseNamed(ref)
+	if err != nil {
+		return "", "", err
+	}
+
+	tag := GetTagFromNamedRef(distributionRef)
+	return distributionRef.Name(), tag, nil
+}
+
+// GetTagFromNamedRef returns a tag from the specified reference.
+// This function is necessary as long as the docker "server" api makes the distinction between repository
+// and tags.
+func GetTagFromNamedRef(ref distreference.Named) string {
+	var tag string
+	switch x := ref.(type) {
+	case distreference.Digested:
+		tag = x.Digest().String()
+	case distreference.NamedTagged:
+		tag = x.Tag()
+	default:
+		tag = "latest"
+	}
+	return tag
+}
diff --git a/vendor/github.com/docker/engine-api/types/registry/registry.go b/vendor/github.com/docker/engine-api/types/registry/registry.go
new file mode 100644
index 00000000..d2aca6f0
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/registry/registry.go
@@ -0,0 +1,99 @@
+package registry
+
+import (
+	"encoding/json"
+	"net"
+)
+
+// ServiceConfig stores daemon registry services configuration.
+type ServiceConfig struct {
+	InsecureRegistryCIDRs []*NetIPNet           `json:"InsecureRegistryCIDRs"`
+	IndexConfigs          map[string]*IndexInfo `json:"IndexConfigs"`
+	Mirrors               []string
+}
+
+// NetIPNet is the net.IPNet type, which can be marshalled and
+// unmarshalled to JSON
+type NetIPNet net.IPNet
+
+// MarshalJSON returns the JSON representation of the IPNet
+func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) {
+	return json.Marshal((*net.IPNet)(ipnet).String())
+}
+
+// UnmarshalJSON sets the IPNet from a byte array of JSON
+func (ipnet *NetIPNet) UnmarshalJSON(b []byte) (err error) {
+	var ipnetStr string
+	if err = json.Unmarshal(b, &ipnetStr); err == nil {
+		var cidr *net.IPNet
+		if _, cidr, err = net.ParseCIDR(ipnetStr); err == nil {
+			*ipnet = NetIPNet(*cidr)
+		}
+	}
+	return
+}
+
+// IndexInfo contains information about a registry
+//
+// RepositoryInfo Examples:
+// {
+//   "Index" : {
+//     "Name" : "docker.io",
+//     "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"],
+//     "Secure" : true,
+//     "Official" : true,
+//   },
+//   "RemoteName" : "library/debian",
+//   "LocalName" : "debian",
+//   "CanonicalName" : "docker.io/debian"
+//   "Official" : true,
+// }
+//
+// {
+//   "Index" : {
+//     "Name" : "127.0.0.1:5000",
+//     "Mirrors" : [],
+//     "Secure" : false,
+//     "Official" : false,
+//   },
+//   "RemoteName" : "user/repo",
+//   "LocalName" : "127.0.0.1:5000/user/repo",
+//   "CanonicalName" : "127.0.0.1:5000/user/repo",
+//   "Official" : false,
+// }
+type IndexInfo struct {
+	// Name is the name of the registry, such as "docker.io"
+	Name string
+	// Mirrors is a list of mirrors, expressed as URIs
+	Mirrors []string
+	// Secure is set to false if the registry is part of the list of
+	// insecure registries. Insecure registries accept HTTP and/or accept
+	// HTTPS with certificates from unknown CAs.
+	Secure bool
+	// Official indicates whether this is an official registry
+	Official bool
+}
+
+// SearchResult describes a search result returned from a registry
+type SearchResult struct {
+	// StarCount indicates the number of stars this repository has
+	StarCount int `json:"star_count"`
+	// IsOfficial is true if the result is from an official repository.
+	IsOfficial bool `json:"is_official"`
+	// Name is the name of the repository
+	Name string `json:"name"`
+	// IsAutomated indicates whether the result is automated
+	IsAutomated bool `json:"is_automated"`
+	// Description is a textual description of the repository
+	Description string `json:"description"`
+}
+
+// SearchResults lists a collection search results returned from a registry
+type SearchResults struct {
+	// Query contains the query string that generated the search results
+	Query string `json:"query"`
+	// NumResults indicates the number of results the query returned
+	NumResults int `json:"num_results"`
+	// Results is a slice containing the actual results for the search
+	Results []SearchResult `json:"results"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/seccomp.go b/vendor/github.com/docker/engine-api/types/seccomp.go
new file mode 100644
index 00000000..854f1c45
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/seccomp.go
@@ -0,0 +1,73 @@
+package types
+
+// Seccomp represents the config for a seccomp profile for syscall restriction.
+type Seccomp struct {
+	DefaultAction Action     `json:"defaultAction"`
+	Architectures []Arch     `json:"architectures"`
+	Syscalls      []*Syscall `json:"syscalls"`
+}
+
+// Arch used for additional architectures
+type Arch string
+
+// Additional architectures permitted to be used for system calls
+// By default only the native architecture of the kernel is permitted
+const (
+	ArchX86         Arch = "SCMP_ARCH_X86"
+	ArchX86_64      Arch = "SCMP_ARCH_X86_64"
+	ArchX32         Arch = "SCMP_ARCH_X32"
+	ArchARM         Arch = "SCMP_ARCH_ARM"
+	ArchAARCH64     Arch = "SCMP_ARCH_AARCH64"
+	ArchMIPS        Arch = "SCMP_ARCH_MIPS"
+	ArchMIPS64      Arch = "SCMP_ARCH_MIPS64"
+	ArchMIPS64N32   Arch = "SCMP_ARCH_MIPS64N32"
+	ArchMIPSEL      Arch = "SCMP_ARCH_MIPSEL"
+	ArchMIPSEL64    Arch = "SCMP_ARCH_MIPSEL64"
+	ArchMIPSEL64N32 Arch = "SCMP_ARCH_MIPSEL64N32"
+	ArchPPC         Arch = "SCMP_ARCH_PPC"
+	ArchPPC64       Arch = "SCMP_ARCH_PPC64"
+	ArchPPC64LE     Arch = "SCMP_ARCH_PPC64LE"
+	ArchS390        Arch = "SCMP_ARCH_S390"
+	ArchS390X       Arch = "SCMP_ARCH_S390X"
+)
+
+// Action taken upon Seccomp rule match
+type Action string
+
+// Define actions for Seccomp rules
+const (
+	ActKill  Action = "SCMP_ACT_KILL"
+	ActTrap  Action = "SCMP_ACT_TRAP"
+	ActErrno Action = "SCMP_ACT_ERRNO"
+	ActTrace Action = "SCMP_ACT_TRACE"
+	ActAllow Action = "SCMP_ACT_ALLOW"
+)
+
+// Operator used to match syscall arguments in Seccomp
+type Operator string
+
+// Define operators for syscall arguments in Seccomp
+const (
+	OpNotEqual     Operator = "SCMP_CMP_NE"
+	OpLessThan     Operator = "SCMP_CMP_LT"
+	OpLessEqual    Operator = "SCMP_CMP_LE"
+	OpEqualTo      Operator = "SCMP_CMP_EQ"
+	OpGreaterEqual Operator = "SCMP_CMP_GE"
+	OpGreaterThan  Operator = "SCMP_CMP_GT"
+	OpMaskedEqual  Operator = "SCMP_CMP_MASKED_EQ"
+)
+
+// Arg used for matching specific syscall arguments in Seccomp
+type Arg struct {
+	Index    uint     `json:"index"`
+	Value    uint64   `json:"value"`
+	ValueTwo uint64   `json:"valueTwo"`
+	Op       Operator `json:"op"`
+}
+
+// Syscall is used to match a syscall in Seccomp
+type Syscall struct {
+	Name   string `json:"name"`
+	Action Action `json:"action"`
+	Args   []*Arg `json:"args"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/stats.go b/vendor/github.com/docker/engine-api/types/stats.go
new file mode 100644
index 00000000..b420ebe7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/stats.go
@@ -0,0 +1,115 @@
+// Package types is used for API stability in the types and response to the
+// consumers of the API stats endpoint.
+package types
+
+import "time"
+
+// ThrottlingData stores CPU throttling stats of one running container
+type ThrottlingData struct {
+	// Number of periods with throttling active
+	Periods uint64 `json:"periods"`
+	// Number of periods when the container hits its throttling limit.
+	ThrottledPeriods uint64 `json:"throttled_periods"`
+	// Aggregate time the container was throttled for in nanoseconds.
+	ThrottledTime uint64 `json:"throttled_time"`
+}
+
+// CPUUsage stores All CPU stats aggregated since container inception.
+type CPUUsage struct {
+	// Total CPU time consumed.
+	// Units: nanoseconds.
+	TotalUsage uint64 `json:"total_usage"`
+	// Total CPU time consumed per core.
+	// Units: nanoseconds.
+	PercpuUsage []uint64 `json:"percpu_usage"`
+	// Time spent by tasks of the cgroup in kernel mode.
+	// Units: nanoseconds.
+	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
+	// Time spent by tasks of the cgroup in user mode.
+	// Units: nanoseconds.
+	UsageInUsermode uint64 `json:"usage_in_usermode"`
+}
+
+// CPUStats aggregates and wraps all CPU related info of container
+type CPUStats struct {
+	CPUUsage       CPUUsage       `json:"cpu_usage"`
+	SystemUsage    uint64         `json:"system_cpu_usage"`
+	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
+}
+
+// MemoryStats aggregates All memory stats since container inception
+type MemoryStats struct {
+	// current res_counter usage for memory
+	Usage uint64 `json:"usage"`
+	// maximum usage ever recorded.
+	MaxUsage uint64 `json:"max_usage"`
+	// TODO(vishh): Export these as stronger types.
+	// all the stats exported via memory.stat.
+	Stats map[string]uint64 `json:"stats"`
+	// number of times memory usage hits limits.
+	Failcnt uint64 `json:"failcnt"`
+	Limit   uint64 `json:"limit"`
+}
+
+// BlkioStatEntry is one small entity to store a piece of Blkio stats
+// TODO Windows: This can be factored out
+type BlkioStatEntry struct {
+	Major uint64 `json:"major"`
+	Minor uint64 `json:"minor"`
+	Op    string `json:"op"`
+	Value uint64 `json:"value"`
+}
+
+// BlkioStats stores All IO service stats for data read and write
+// TODO Windows: This can be factored out
+type BlkioStats struct {
+	// number of bytes transferred to and from the block device
+	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
+	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
+	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
+	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
+	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
+	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
+	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
+	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
+}
+
+// NetworkStats aggregates All network stats of one container
+// TODO Windows: This will require refactoring
+type NetworkStats struct {
+	RxBytes   uint64 `json:"rx_bytes"`
+	RxPackets uint64 `json:"rx_packets"`
+	RxErrors  uint64 `json:"rx_errors"`
+	RxDropped uint64 `json:"rx_dropped"`
+	TxBytes   uint64 `json:"tx_bytes"`
+	TxPackets uint64 `json:"tx_packets"`
+	TxErrors  uint64 `json:"tx_errors"`
+	TxDropped uint64 `json:"tx_dropped"`
+}
+
+// PidsStats contains the stats of a container's pids
+type PidsStats struct {
+	// Current is the number of pids in the cgroup
+	Current uint64 `json:"current,omitempty"`
+	// Limit is the hard limit on the number of pids in the cgroup.
+	// A "Limit" of 0 means that there is no limit.
+	Limit uint64 `json:"limit,omitempty"`
+}
+
+// Stats is Ultimate struct aggregating all types of stats of one container
+type Stats struct {
+	Read        time.Time   `json:"read"`
+	PreCPUStats CPUStats    `json:"precpu_stats,omitempty"`
+	CPUStats    CPUStats    `json:"cpu_stats,omitempty"`
+	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
+	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
+	PidsStats   PidsStats   `json:"pids_stats,omitempty"`
+}
+
+// StatsJSON is newly used Networks
+type StatsJSON struct {
+	Stats
+
+	// Networks request version >=1.21
+	Networks map[string]NetworkStats `json:"networks,omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/strslice/strslice.go b/vendor/github.com/docker/engine-api/types/strslice/strslice.go
new file mode 100644
index 00000000..bad493fb
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/strslice/strslice.go
@@ -0,0 +1,30 @@
+package strslice
+
+import "encoding/json"
+
+// StrSlice represents a string or an array of strings.
+// We need to override the json decoder to accept both options.
+type StrSlice []string
+
+// UnmarshalJSON decodes the byte slice whether it's a string or an array of
+// strings. This method is needed to implement json.Unmarshaler.
+func (e *StrSlice) UnmarshalJSON(b []byte) error {
+	if len(b) == 0 {
+		// With no input, we preserve the existing value by returning nil and
+		// leaving the target alone. This allows defining default values for
+		// the type.
+		return nil
+	}
+
+	p := make([]string, 0, 1)
+	if err := json.Unmarshal(b, &p); err != nil {
+		var s string
+		if err := json.Unmarshal(b, &s); err != nil {
+			return err
+		}
+		p = append(p, s)
+	}
+
+	*e = p
+	return nil
+}
diff --git a/vendor/github.com/docker/engine-api/types/swarm/common.go b/vendor/github.com/docker/engine-api/types/swarm/common.go
new file mode 100644
index 00000000..b87f5453
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/common.go
@@ -0,0 +1,21 @@
+package swarm
+
+import "time"
+
+// Version represent the internal object version.
+type Version struct {
+	Index uint64 `json:",omitempty"`
+}
+
+// Meta is  base object inherited by most of the other once.
+type Meta struct {
+	Version   Version   `json:",omitempty"`
+	CreatedAt time.Time `json:",omitempty"`
+	UpdatedAt time.Time `json:",omitempty"`
+}
+
+// Annotations represents how to describe an object.
+type Annotations struct {
+	Name   string            `json:",omitempty"`
+	Labels map[string]string `json:",omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/swarm/container.go b/vendor/github.com/docker/engine-api/types/swarm/container.go
new file mode 100644
index 00000000..29f2e8a6
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/container.go
@@ -0,0 +1,67 @@
+package swarm
+
+import "time"
+
+// ContainerSpec represents the spec of a container.
+type ContainerSpec struct {
+	Image           string            `json:",omitempty"`
+	Labels          map[string]string `json:",omitempty"`
+	Command         []string          `json:",omitempty"`
+	Args            []string          `json:",omitempty"`
+	Env             []string          `json:",omitempty"`
+	Dir             string            `json:",omitempty"`
+	User            string            `json:",omitempty"`
+	Mounts          []Mount           `json:",omitempty"`
+	StopGracePeriod *time.Duration    `json:",omitempty"`
+}
+
+// MountType represents the type of a mount.
+type MountType string
+
+const (
+	// MountTypeBind BIND
+	MountTypeBind MountType = "bind"
+	// MountTypeVolume VOLUME
+	MountTypeVolume MountType = "volume"
+)
+
+// Mount represents a mount (volume).
+type Mount struct {
+	Type     MountType `json:",omitempty"`
+	Source   string    `json:",omitempty"`
+	Target   string    `json:",omitempty"`
+	ReadOnly bool      `json:",omitempty"`
+
+	BindOptions   *BindOptions   `json:",omitempty"`
+	VolumeOptions *VolumeOptions `json:",omitempty"`
+}
+
+// MountPropagation represents the propagation of a mount.
+type MountPropagation string
+
+const (
+	// MountPropagationRPrivate RPRIVATE
+	MountPropagationRPrivate MountPropagation = "rprivate"
+	// MountPropagationPrivate PRIVATE
+	MountPropagationPrivate MountPropagation = "private"
+	// MountPropagationRShared RSHARED
+	MountPropagationRShared MountPropagation = "rshared"
+	// MountPropagationShared SHARED
+	MountPropagationShared MountPropagation = "shared"
+	// MountPropagationRSlave RSLAVE
+	MountPropagationRSlave MountPropagation = "rslave"
+	// MountPropagationSlave SLAVE
+	MountPropagationSlave MountPropagation = "slave"
+)
+
+// BindOptions defines options specific to mounts of type "bind".
+type BindOptions struct {
+	Propagation MountPropagation `json:",omitempty"`
+}
+
+// VolumeOptions represents the options for a mount of type volume.
+type VolumeOptions struct {
+	NoCopy       bool              `json:",omitempty"`
+	Labels       map[string]string `json:",omitempty"`
+	DriverConfig *Driver           `json:",omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/swarm/network.go b/vendor/github.com/docker/engine-api/types/swarm/network.go
new file mode 100644
index 00000000..84804da2
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/network.go
@@ -0,0 +1,99 @@
+package swarm
+
+// Endpoint represents an endpoint.
+type Endpoint struct {
+	Spec       EndpointSpec        `json:",omitempty"`
+	Ports      []PortConfig        `json:",omitempty"`
+	VirtualIPs []EndpointVirtualIP `json:",omitempty"`
+}
+
+// EndpointSpec represents the spec of an endpoint.
+type EndpointSpec struct {
+	Mode  ResolutionMode `json:",omitempty"`
+	Ports []PortConfig   `json:",omitempty"`
+}
+
+// ResolutionMode represents a resolution mode.
+type ResolutionMode string
+
+const (
+	// ResolutionModeVIP VIP
+	ResolutionModeVIP ResolutionMode = "vip"
+	// ResolutionModeDNSRR DNSRR
+	ResolutionModeDNSRR ResolutionMode = "dnsrr"
+)
+
+// PortConfig represents the config of a port.
+type PortConfig struct {
+	Name          string             `json:",omitempty"`
+	Protocol      PortConfigProtocol `json:",omitempty"`
+	TargetPort    uint32             `json:",omitempty"`
+	PublishedPort uint32             `json:",omitempty"`
+}
+
+// PortConfigProtocol represents the protocol of a port.
+type PortConfigProtocol string
+
+const (
+	// TODO(stevvooe): These should be used generally, not just for PortConfig.
+
+	// PortConfigProtocolTCP TCP
+	PortConfigProtocolTCP PortConfigProtocol = "tcp"
+	// PortConfigProtocolUDP UDP
+	PortConfigProtocolUDP PortConfigProtocol = "udp"
+)
+
+// EndpointVirtualIP represents the virtual ip of a port.
+type EndpointVirtualIP struct {
+	NetworkID string `json:",omitempty"`
+	Addr      string `json:",omitempty"`
+}
+
+// Network represents a network.
+type Network struct {
+	ID string
+	Meta
+	Spec        NetworkSpec  `json:",omitempty"`
+	DriverState Driver       `json:",omitempty"`
+	IPAMOptions *IPAMOptions `json:",omitempty"`
+}
+
+// NetworkSpec represents the spec of a network.
+type NetworkSpec struct {
+	Annotations
+	DriverConfiguration *Driver      `json:",omitempty"`
+	IPv6Enabled         bool         `json:",omitempty"`
+	Internal            bool         `json:",omitempty"`
+	IPAMOptions         *IPAMOptions `json:",omitempty"`
+}
+
+// NetworkAttachmentConfig represents the configuration of a network attachment.
+type NetworkAttachmentConfig struct {
+	Target  string   `json:",omitempty"`
+	Aliases []string `json:",omitempty"`
+}
+
+// NetworkAttachment represents a network attachment.
+type NetworkAttachment struct {
+	Network   Network  `json:",omitempty"`
+	Addresses []string `json:",omitempty"`
+}
+
+// IPAMOptions represents ipam options.
+type IPAMOptions struct {
+	Driver  Driver       `json:",omitempty"`
+	Configs []IPAMConfig `json:",omitempty"`
+}
+
+// IPAMConfig represents ipam configuration.
+type IPAMConfig struct {
+	Subnet  string `json:",omitempty"`
+	Range   string `json:",omitempty"`
+	Gateway string `json:",omitempty"`
+}
+
+// Driver represents a driver (network/volume).
+type Driver struct {
+	Name    string            `json:",omitempty"`
+	Options map[string]string `json:",omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/swarm/node.go b/vendor/github.com/docker/engine-api/types/swarm/node.go
new file mode 100644
index 00000000..9987662a
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/node.go
@@ -0,0 +1,107 @@
+package swarm
+
+// Node represents a node.
+type Node struct {
+	ID string
+	Meta
+
+	Spec          NodeSpec        `json:",omitempty"`
+	Description   NodeDescription `json:",omitempty"`
+	Status        NodeStatus      `json:",omitempty"`
+	ManagerStatus *ManagerStatus  `json:",omitempty"`
+}
+
+// NodeSpec represents the spec of a node.
+type NodeSpec struct {
+	Annotations
+	Role         NodeRole         `json:",omitempty"`
+	Availability NodeAvailability `json:",omitempty"`
+}
+
+// NodeRole represents the role of a node.
+type NodeRole string
+
+const (
+	// NodeRoleWorker WORKER
+	NodeRoleWorker NodeRole = "worker"
+	// NodeRoleManager MANAGER
+	NodeRoleManager NodeRole = "manager"
+)
+
+// NodeAvailability represents the availability of a node.
+type NodeAvailability string
+
+const (
+	// NodeAvailabilityActive ACTIVE
+	NodeAvailabilityActive NodeAvailability = "active"
+	// NodeAvailabilityPause PAUSE
+	NodeAvailabilityPause NodeAvailability = "pause"
+	// NodeAvailabilityDrain DRAIN
+	NodeAvailabilityDrain NodeAvailability = "drain"
+)
+
+// NodeDescription represents the description of a node.
+type NodeDescription struct {
+	Hostname  string            `json:",omitempty"`
+	Platform  Platform          `json:",omitempty"`
+	Resources Resources         `json:",omitempty"`
+	Engine    EngineDescription `json:",omitempty"`
+}
+
+// Platform represents the platfrom (Arch/OS).
+type Platform struct {
+	Architecture string `json:",omitempty"`
+	OS           string `json:",omitempty"`
+}
+
+// EngineDescription represents the description of an engine.
+type EngineDescription struct {
+	EngineVersion string              `json:",omitempty"`
+	Labels        map[string]string   `json:",omitempty"`
+	Plugins       []PluginDescription `json:",omitempty"`
+}
+
+// PluginDescription represents the description of an engine plugin.
+type PluginDescription struct {
+	Type string `json:",omitempty"`
+	Name string `json:",omitempty"`
+}
+
+// NodeStatus represents the status of a node.
+type NodeStatus struct {
+	State   NodeState `json:",omitempty"`
+	Message string    `json:",omitempty"`
+}
+
+// Reachability represents the reachability of a node.
+type Reachability string
+
+const (
+	// ReachabilityUnknown UNKNOWN
+	ReachabilityUnknown Reachability = "unknown"
+	// ReachabilityUnreachable UNREACHABLE
+	ReachabilityUnreachable Reachability = "unreachable"
+	// ReachabilityReachable REACHABLE
+	ReachabilityReachable Reachability = "reachable"
+)
+
+// ManagerStatus represents the status of a manager.
+type ManagerStatus struct {
+	Leader       bool         `json:",omitempty"`
+	Reachability Reachability `json:",omitempty"`
+	Addr         string       `json:",omitempty"`
+}
+
+// NodeState represents the state of a node.
+type NodeState string
+
+const (
+	// NodeStateUnknown UNKNOWN
+	NodeStateUnknown NodeState = "unknown"
+	// NodeStateDown DOWN
+	NodeStateDown NodeState = "down"
+	// NodeStateReady READY
+	NodeStateReady NodeState = "ready"
+	// NodeStateDisconnected DISCONNECTED
+	NodeStateDisconnected NodeState = "disconnected"
+)
diff --git a/vendor/github.com/docker/engine-api/types/swarm/service.go b/vendor/github.com/docker/engine-api/types/swarm/service.go
new file mode 100644
index 00000000..676fc0e0
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/service.go
@@ -0,0 +1,73 @@
+package swarm
+
+import "time"
+
+// Service represents a service.
+type Service struct {
+	ID string
+	Meta
+	Spec         ServiceSpec  `json:",omitempty"`
+	Endpoint     Endpoint     `json:",omitempty"`
+	UpdateStatus UpdateStatus `json:",omitempty"`
+}
+
+// ServiceSpec represents the spec of a service.
+type ServiceSpec struct {
+	Annotations
+
+	// TaskTemplate defines how the service should construct new tasks when
+	// orchestrating this service.
+	TaskTemplate TaskSpec                  `json:",omitempty"`
+	Mode         ServiceMode               `json:",omitempty"`
+	UpdateConfig *UpdateConfig             `json:",omitempty"`
+	Networks     []NetworkAttachmentConfig `json:",omitempty"`
+	EndpointSpec *EndpointSpec             `json:",omitempty"`
+}
+
+// ServiceMode represents the mode of a service.
+type ServiceMode struct {
+	Replicated *ReplicatedService `json:",omitempty"`
+	Global     *GlobalService     `json:",omitempty"`
+}
+
+// UpdateState is the state of a service update.
+type UpdateState string
+
+const (
+	// UpdateStateUpdating is the updating state.
+	UpdateStateUpdating UpdateState = "updating"
+	// UpdateStatePaused is the paused state.
+	UpdateStatePaused UpdateState = "paused"
+	// UpdateStateCompleted is the completed state.
+	UpdateStateCompleted UpdateState = "completed"
+)
+
+// UpdateStatus reports the status of a service update.
+type UpdateStatus struct {
+	State       UpdateState `json:",omitempty"`
+	StartedAt   time.Time   `json:",omitempty"`
+	CompletedAt time.Time   `json:",omitempty"`
+	Message     string      `json:",omitempty"`
+}
+
+// ReplicatedService is a kind of ServiceMode.
+type ReplicatedService struct {
+	Replicas *uint64 `json:",omitempty"`
+}
+
+// GlobalService is a kind of ServiceMode.
+type GlobalService struct{}
+
+const (
+	// UpdateFailureActionPause PAUSE
+	UpdateFailureActionPause = "pause"
+	// UpdateFailureActionContinue CONTINUE
+	UpdateFailureActionContinue = "continue"
+)
+
+// UpdateConfig represents the update configuration.
+type UpdateConfig struct {
+	Parallelism   uint64        `json:",omitempty"`
+	Delay         time.Duration `json:",omitempty"`
+	FailureAction string        `json:",omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/swarm/swarm.go b/vendor/github.com/docker/engine-api/types/swarm/swarm.go
new file mode 100644
index 00000000..0a541410
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/swarm.go
@@ -0,0 +1,141 @@
+package swarm
+
+import "time"
+
+// ClusterInfo represents info about a the cluster for outputing in "info"
+// it contains the same information as "Swarm", but without the JoinTokens
+type ClusterInfo struct {
+	ID string
+	Meta
+	Spec Spec
+}
+
+// Swarm represents a swarm.
+type Swarm struct {
+	ClusterInfo
+	JoinTokens JoinTokens
+}
+
+// JoinTokens contains the tokens workers and managers need to join the swarm.
+type JoinTokens struct {
+	Worker  string
+	Manager string
+}
+
+// Spec represents the spec of a swarm.
+type Spec struct {
+	Annotations
+
+	Orchestration OrchestrationConfig `json:",omitempty"`
+	Raft          RaftConfig          `json:",omitempty"`
+	Dispatcher    DispatcherConfig    `json:",omitempty"`
+	CAConfig      CAConfig            `json:",omitempty"`
+	TaskDefaults  TaskDefaults        `json:",omitempty"`
+}
+
+// OrchestrationConfig represents orchestration configuration.
+type OrchestrationConfig struct {
+	TaskHistoryRetentionLimit int64 `json:",omitempty"`
+}
+
+// TaskDefaults parameterizes cluster-level task creation with default values.
+type TaskDefaults struct {
+	// LogDriver selects the log driver to use for tasks created in the
+	// orchestrator if unspecified by a service.
+	//
+	// Updating this value will only have an affect on new tasks. Old tasks
+	// will continue use their previously configured log driver until
+	// recreated.
+	LogDriver *Driver `json:",omitempty"`
+}
+
+// RaftConfig represents raft configuration.
+type RaftConfig struct {
+	SnapshotInterval           uint64 `json:",omitempty"`
+	KeepOldSnapshots           uint64 `json:",omitempty"`
+	LogEntriesForSlowFollowers uint64 `json:",omitempty"`
+	HeartbeatTick              uint32 `json:",omitempty"`
+	ElectionTick               uint32 `json:",omitempty"`
+}
+
+// DispatcherConfig represents dispatcher configuration.
+type DispatcherConfig struct {
+	HeartbeatPeriod uint64 `json:",omitempty"`
+}
+
+// CAConfig represents CA configuration.
+type CAConfig struct {
+	NodeCertExpiry time.Duration `json:",omitempty"`
+	ExternalCAs    []*ExternalCA `json:",omitempty"`
+}
+
+// ExternalCAProtocol represents type of external CA.
+type ExternalCAProtocol string
+
+// ExternalCAProtocolCFSSL CFSSL
+const ExternalCAProtocolCFSSL ExternalCAProtocol = "cfssl"
+
+// ExternalCA defines external CA to be used by the cluster.
+type ExternalCA struct {
+	Protocol ExternalCAProtocol
+	URL      string
+	Options  map[string]string `json:",omitempty"`
+}
+
+// InitRequest is the request used to init a swarm.
+type InitRequest struct {
+	ListenAddr      string
+	AdvertiseAddr   string
+	ForceNewCluster bool
+	Spec            Spec
+}
+
+// JoinRequest is the request used to join a swarm.
+type JoinRequest struct {
+	ListenAddr    string
+	AdvertiseAddr string
+	RemoteAddrs   []string
+	JoinToken     string // accept by secret
+}
+
+// LocalNodeState represents the state of the local node.
+type LocalNodeState string
+
+const (
+	// LocalNodeStateInactive INACTIVE
+	LocalNodeStateInactive LocalNodeState = "inactive"
+	// LocalNodeStatePending PENDING
+	LocalNodeStatePending LocalNodeState = "pending"
+	// LocalNodeStateActive ACTIVE
+	LocalNodeStateActive LocalNodeState = "active"
+	// LocalNodeStateError ERROR
+	LocalNodeStateError LocalNodeState = "error"
+)
+
+// Info represents generic information about swarm.
+type Info struct {
+	NodeID   string
+	NodeAddr string
+
+	LocalNodeState   LocalNodeState
+	ControlAvailable bool
+	Error            string
+
+	RemoteManagers []Peer
+	Nodes          int
+	Managers       int
+
+	Cluster ClusterInfo
+}
+
+// Peer represents a peer.
+type Peer struct {
+	NodeID string
+	Addr   string
+}
+
+// UpdateFlags contains flags for SwarmUpdate.
+type UpdateFlags struct {
+	RotateWorkerToken  bool
+	RotateManagerToken bool
+}
diff --git a/vendor/github.com/docker/engine-api/types/swarm/task.go b/vendor/github.com/docker/engine-api/types/swarm/task.go
new file mode 100644
index 00000000..fa8228a4
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/swarm/task.go
@@ -0,0 +1,115 @@
+package swarm
+
+import "time"
+
+// TaskState represents the state of a task.
+type TaskState string
+
+const (
+	// TaskStateNew NEW
+	TaskStateNew TaskState = "new"
+	// TaskStateAllocated ALLOCATED
+	TaskStateAllocated TaskState = "allocated"
+	// TaskStatePending PENDING
+	TaskStatePending TaskState = "pending"
+	// TaskStateAssigned ASSIGNED
+	TaskStateAssigned TaskState = "assigned"
+	// TaskStateAccepted ACCEPTED
+	TaskStateAccepted TaskState = "accepted"
+	// TaskStatePreparing PREPARING
+	TaskStatePreparing TaskState = "preparing"
+	// TaskStateReady READY
+	TaskStateReady TaskState = "ready"
+	// TaskStateStarting STARTING
+	TaskStateStarting TaskState = "starting"
+	// TaskStateRunning RUNNING
+	TaskStateRunning TaskState = "running"
+	// TaskStateComplete COMPLETE
+	TaskStateComplete TaskState = "complete"
+	// TaskStateShutdown SHUTDOWN
+	TaskStateShutdown TaskState = "shutdown"
+	// TaskStateFailed FAILED
+	TaskStateFailed TaskState = "failed"
+	// TaskStateRejected REJECTED
+	TaskStateRejected TaskState = "rejected"
+)
+
+// Task represents a task.
+type Task struct {
+	ID string
+	Meta
+
+	Spec                TaskSpec            `json:",omitempty"`
+	ServiceID           string              `json:",omitempty"`
+	Slot                int                 `json:",omitempty"`
+	NodeID              string              `json:",omitempty"`
+	Status              TaskStatus          `json:",omitempty"`
+	DesiredState        TaskState           `json:",omitempty"`
+	NetworksAttachments []NetworkAttachment `json:",omitempty"`
+}
+
+// TaskSpec represents the spec of a task.
+type TaskSpec struct {
+	ContainerSpec ContainerSpec         `json:",omitempty"`
+	Resources     *ResourceRequirements `json:",omitempty"`
+	RestartPolicy *RestartPolicy        `json:",omitempty"`
+	Placement     *Placement            `json:",omitempty"`
+
+	// LogDriver specifies the LogDriver to use for tasks created from this
+	// spec. If not present, the one on cluster default on swarm.Spec will be
+	// used, finally falling back to the engine default if not specified.
+	LogDriver *Driver `json:",omitempty"`
+}
+
+// Resources represents resources (CPU/Memory).
+type Resources struct {
+	NanoCPUs    int64 `json:",omitempty"`
+	MemoryBytes int64 `json:",omitempty"`
+}
+
+// ResourceRequirements represents resources requirements.
+type ResourceRequirements struct {
+	Limits       *Resources `json:",omitempty"`
+	Reservations *Resources `json:",omitempty"`
+}
+
+// Placement represents orchestration parameters.
+type Placement struct {
+	Constraints []string `json:",omitempty"`
+}
+
+// RestartPolicy represents the restart policy.
+type RestartPolicy struct {
+	Condition   RestartPolicyCondition `json:",omitempty"`
+	Delay       *time.Duration         `json:",omitempty"`
+	MaxAttempts *uint64                `json:",omitempty"`
+	Window      *time.Duration         `json:",omitempty"`
+}
+
+// RestartPolicyCondition represents when to restart.
+type RestartPolicyCondition string
+
+const (
+	// RestartPolicyConditionNone NONE
+	RestartPolicyConditionNone RestartPolicyCondition = "none"
+	// RestartPolicyConditionOnFailure ON_FAILURE
+	RestartPolicyConditionOnFailure RestartPolicyCondition = "on-failure"
+	// RestartPolicyConditionAny ANY
+	RestartPolicyConditionAny RestartPolicyCondition = "any"
+)
+
+// TaskStatus represents the status of a task.
+type TaskStatus struct {
+	Timestamp       time.Time       `json:",omitempty"`
+	State           TaskState       `json:",omitempty"`
+	Message         string          `json:",omitempty"`
+	Err             string          `json:",omitempty"`
+	ContainerStatus ContainerStatus `json:",omitempty"`
+}
+
+// ContainerStatus represents the status of a container.
+type ContainerStatus struct {
+	ContainerID string `json:",omitempty"`
+	PID         int    `json:",omitempty"`
+	ExitCode    int    `json:",omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/time/duration_convert.go b/vendor/github.com/docker/engine-api/types/time/duration_convert.go
new file mode 100644
index 00000000..63e1eec1
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/time/duration_convert.go
@@ -0,0 +1,12 @@
+package time
+
+import (
+	"strconv"
+	"time"
+)
+
+// DurationToSecondsString converts the specified duration to the number
+// seconds it represents, formatted as a string.
+func DurationToSecondsString(duration time.Duration) string {
+	return strconv.FormatFloat(duration.Seconds(), 'f', 0, 64)
+}
diff --git a/vendor/github.com/docker/engine-api/types/time/timestamp.go b/vendor/github.com/docker/engine-api/types/time/timestamp.go
new file mode 100644
index 00000000..d3695ba7
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/time/timestamp.go
@@ -0,0 +1,124 @@
+package time
+
+import (
+	"fmt"
+	"math"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// These are additional predefined layouts for use in Time.Format and Time.Parse
+// with --since and --until parameters for `docker logs` and `docker events`
+const (
+	rFC3339Local     = "2006-01-02T15:04:05"           // RFC3339 with local timezone
+	rFC3339NanoLocal = "2006-01-02T15:04:05.999999999" // RFC3339Nano with local timezone
+	dateWithZone     = "2006-01-02Z07:00"              // RFC3339 with time at 00:00:00
+	dateLocal        = "2006-01-02"                    // RFC3339 with local timezone and time at 00:00:00
+)
+
+// GetTimestamp tries to parse given string as golang duration,
+// then RFC3339 time and finally as a Unix timestamp. If
+// any of these were successful, it returns a Unix timestamp
+// as string otherwise returns the given value back.
+// In case of duration input, the returned timestamp is computed
+// as the given reference time minus the amount of the duration.
+func GetTimestamp(value string, reference time.Time) (string, error) {
+	if d, err := time.ParseDuration(value); value != "0" && err == nil {
+		return strconv.FormatInt(reference.Add(-d).Unix(), 10), nil
+	}
+
+	var format string
+	var parseInLocation bool
+
+	// if the string has a Z or a + or three dashes use parse otherwise use parseinlocation
+	parseInLocation = !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3)
+
+	if strings.Contains(value, ".") {
+		if parseInLocation {
+			format = rFC3339NanoLocal
+		} else {
+			format = time.RFC3339Nano
+		}
+	} else if strings.Contains(value, "T") {
+		// we want the number of colons in the T portion of the timestamp
+		tcolons := strings.Count(value, ":")
+		// if parseInLocation is off and we have a +/- zone offset (not Z) then
+		// there will be an extra colon in the input for the tz offset subtract that
+		// colon from the tcolons count
+		if !parseInLocation && !strings.ContainsAny(value, "zZ") && tcolons > 0 {
+			tcolons--
+		}
+		if parseInLocation {
+			switch tcolons {
+			case 0:
+				format = "2006-01-02T15"
+			case 1:
+				format = "2006-01-02T15:04"
+			default:
+				format = rFC3339Local
+			}
+		} else {
+			switch tcolons {
+			case 0:
+				format = "2006-01-02T15Z07:00"
+			case 1:
+				format = "2006-01-02T15:04Z07:00"
+			default:
+				format = time.RFC3339
+			}
+		}
+	} else if parseInLocation {
+		format = dateLocal
+	} else {
+		format = dateWithZone
+	}
+
+	var t time.Time
+	var err error
+
+	if parseInLocation {
+		t, err = time.ParseInLocation(format, value, time.FixedZone(reference.Zone()))
+	} else {
+		t, err = time.Parse(format, value)
+	}
+
+	if err != nil {
+		// if there is a `-` then its an RFC3339 like timestamp otherwise assume unixtimestamp
+		if strings.Contains(value, "-") {
+			return "", err // was probably an RFC3339 like timestamp but the parser failed with an error
+		}
+		return value, nil // unixtimestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server)
+	}
+
+	return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil
+}
+
+// ParseTimestamps returns seconds and nanoseconds from a timestamp that has the
+// format "%d.%09d", time.Unix(), int64(time.Nanosecond()))
+// if the incoming nanosecond portion is longer or shorter than 9 digits it is
+// converted to nanoseconds.  The expectation is that the seconds and
+// seconds will be used to create a time variable.  For example:
+//     seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0)
+//     if err == nil since := time.Unix(seconds, nanoseconds)
+// returns seconds as def(aultSeconds) if value == ""
+func ParseTimestamps(value string, def int64) (int64, int64, error) {
+	if value == "" {
+		return def, 0, nil
+	}
+	sa := strings.SplitN(value, ".", 2)
+	s, err := strconv.ParseInt(sa[0], 10, 64)
+	if err != nil {
+		return s, 0, err
+	}
+	if len(sa) != 2 {
+		return s, 0, nil
+	}
+	n, err := strconv.ParseInt(sa[1], 10, 64)
+	if err != nil {
+		return s, n, err
+	}
+	// should already be in nanoseconds but just in case convert n to nanoseonds
+	n = int64(float64(n) * math.Pow(float64(10), float64(9-len(sa[1]))))
+	return s, n, nil
+}
diff --git a/vendor/github.com/docker/engine-api/types/types.go b/vendor/github.com/docker/engine-api/types/types.go
new file mode 100644
index 00000000..b6f91259
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/types.go
@@ -0,0 +1,515 @@
+package types
+
+import (
+	"os"
+	"time"
+
+	"github.com/docker/engine-api/types/container"
+	"github.com/docker/engine-api/types/network"
+	"github.com/docker/engine-api/types/registry"
+	"github.com/docker/engine-api/types/swarm"
+	"github.com/docker/go-connections/nat"
+)
+
+// ContainerCreateResponse contains the information returned to a client on the
+// creation of a new container.
+type ContainerCreateResponse struct {
+	// ID is the ID of the created container.
+	ID string `json:"Id"`
+
+	// Warnings are any warnings encountered during the creation of the container.
+	Warnings []string `json:"Warnings"`
+}
+
+// ContainerExecCreateResponse contains response of Remote API:
+// POST "/containers/{name:.*}/exec"
+type ContainerExecCreateResponse struct {
+	// ID is the exec ID.
+	ID string `json:"Id"`
+}
+
+// ContainerUpdateResponse contains response of Remote API:
+// POST "/containers/{name:.*}/update"
+type ContainerUpdateResponse struct {
+	// Warnings are any warnings encountered during the updating of the container.
+	Warnings []string `json:"Warnings"`
+}
+
+// AuthResponse contains response of Remote API:
+// POST "/auth"
+type AuthResponse struct {
+	// Status is the authentication status
+	Status string `json:"Status"`
+
+	// IdentityToken is an opaque token used for authenticating
+	// a user after a successful login.
+	IdentityToken string `json:"IdentityToken,omitempty"`
+}
+
+// ContainerWaitResponse contains response of Remote API:
+// POST "/containers/"+containerID+"/wait"
+type ContainerWaitResponse struct {
+	// StatusCode is the status code of the wait job
+	StatusCode int `json:"StatusCode"`
+}
+
+// ContainerCommitResponse contains response of Remote API:
+// POST "/commit?container="+containerID
+type ContainerCommitResponse struct {
+	ID string `json:"Id"`
+}
+
+// ContainerChange contains response of Remote API:
+// GET "/containers/{name:.*}/changes"
+type ContainerChange struct {
+	Kind int
+	Path string
+}
+
+// ImageHistory contains response of Remote API:
+// GET "/images/{name:.*}/history"
+type ImageHistory struct {
+	ID        string `json:"Id"`
+	Created   int64
+	CreatedBy string
+	Tags      []string
+	Size      int64
+	Comment   string
+}
+
+// ImageDelete contains response of Remote API:
+// DELETE "/images/{name:.*}"
+type ImageDelete struct {
+	Untagged string `json:",omitempty"`
+	Deleted  string `json:",omitempty"`
+}
+
+// Image contains response of Remote API:
+// GET "/images/json"
+type Image struct {
+	ID          string `json:"Id"`
+	ParentID    string `json:"ParentId"`
+	RepoTags    []string
+	RepoDigests []string
+	Created     int64
+	Size        int64
+	VirtualSize int64
+	Labels      map[string]string
+}
+
+// GraphDriverData returns Image's graph driver config info
+// when calling inspect command
+type GraphDriverData struct {
+	Name string
+	Data map[string]string
+}
+
+// RootFS returns Image's RootFS description including the layer IDs.
+type RootFS struct {
+	Type      string
+	Layers    []string `json:",omitempty"`
+	BaseLayer string   `json:",omitempty"`
+}
+
+// ImageInspect contains response of Remote API:
+// GET "/images/{name:.*}/json"
+type ImageInspect struct {
+	ID              string `json:"Id"`
+	RepoTags        []string
+	RepoDigests     []string
+	Parent          string
+	Comment         string
+	Created         string
+	Container       string
+	ContainerConfig *container.Config
+	DockerVersion   string
+	Author          string
+	Config          *container.Config
+	Architecture    string
+	Os              string
+	Size            int64
+	VirtualSize     int64
+	GraphDriver     GraphDriverData
+	RootFS          RootFS
+}
+
+// Port stores open ports info of container
+// e.g. {"PrivatePort": 8080, "PublicPort": 80, "Type": "tcp"}
+type Port struct {
+	IP          string `json:",omitempty"`
+	PrivatePort int
+	PublicPort  int `json:",omitempty"`
+	Type        string
+}
+
+// Container contains response of Remote API:
+// GET "/containers/json"
+type Container struct {
+	ID         string `json:"Id"`
+	Names      []string
+	Image      string
+	ImageID    string
+	Command    string
+	Created    int64
+	Ports      []Port
+	SizeRw     int64 `json:",omitempty"`
+	SizeRootFs int64 `json:",omitempty"`
+	Labels     map[string]string
+	State      string
+	Status     string
+	HostConfig struct {
+		NetworkMode string `json:",omitempty"`
+	}
+	NetworkSettings *SummaryNetworkSettings
+	Mounts          []MountPoint
+}
+
+// CopyConfig contains request body of Remote API:
+// POST "/containers/"+containerID+"/copy"
+type CopyConfig struct {
+	Resource string
+}
+
+// ContainerPathStat is used to encode the header from
+// GET "/containers/{name:.*}/archive"
+// "Name" is the file or directory name.
+type ContainerPathStat struct {
+	Name       string      `json:"name"`
+	Size       int64       `json:"size"`
+	Mode       os.FileMode `json:"mode"`
+	Mtime      time.Time   `json:"mtime"`
+	LinkTarget string      `json:"linkTarget"`
+}
+
+// ContainerProcessList contains response of Remote API:
+// GET "/containers/{name:.*}/top"
+type ContainerProcessList struct {
+	Processes [][]string
+	Titles    []string
+}
+
+// Version contains response of Remote API:
+// GET "/version"
+type Version struct {
+	Version       string
+	APIVersion    string `json:"ApiVersion"`
+	GitCommit     string
+	GoVersion     string
+	Os            string
+	Arch          string
+	KernelVersion string `json:",omitempty"`
+	Experimental  bool   `json:",omitempty"`
+	BuildTime     string `json:",omitempty"`
+}
+
+// Info contains response of Remote API:
+// GET "/info"
+type Info struct {
+	ID                 string
+	Containers         int
+	ContainersRunning  int
+	ContainersPaused   int
+	ContainersStopped  int
+	Images             int
+	Driver             string
+	DriverStatus       [][2]string
+	SystemStatus       [][2]string
+	Plugins            PluginsInfo
+	MemoryLimit        bool
+	SwapLimit          bool
+	KernelMemory       bool
+	CPUCfsPeriod       bool `json:"CpuCfsPeriod"`
+	CPUCfsQuota        bool `json:"CpuCfsQuota"`
+	CPUShares          bool
+	CPUSet             bool
+	IPv4Forwarding     bool
+	BridgeNfIptables   bool
+	BridgeNfIP6tables  bool `json:"BridgeNfIp6tables"`
+	Debug              bool
+	NFd                int
+	OomKillDisable     bool
+	NGoroutines        int
+	SystemTime         string
+	ExecutionDriver    string
+	LoggingDriver      string
+	CgroupDriver       string
+	NEventsListener    int
+	KernelVersion      string
+	OperatingSystem    string
+	OSType             string
+	Architecture       string
+	IndexServerAddress string
+	RegistryConfig     *registry.ServiceConfig
+	NCPU               int
+	MemTotal           int64
+	DockerRootDir      string
+	HTTPProxy          string `json:"HttpProxy"`
+	HTTPSProxy         string `json:"HttpsProxy"`
+	NoProxy            string
+	Name               string
+	Labels             []string
+	ExperimentalBuild  bool
+	ServerVersion      string
+	ClusterStore       string
+	ClusterAdvertise   string
+	SecurityOptions    []string
+	Runtimes           map[string]Runtime
+	DefaultRuntime     string
+	Swarm              swarm.Info
+	// LiveRestoreEnabled determines whether containers should be kept
+	// running when the daemon is shutdown or upon daemon start if
+	// running containers are detected
+	LiveRestoreEnabled bool
+}
+
+// PluginsInfo is a temp struct holding Plugins name
+// registered with docker daemon. It is used by Info struct
+type PluginsInfo struct {
+	// List of Volume plugins registered
+	Volume []string
+	// List of Network plugins registered
+	Network []string
+	// List of Authorization plugins registered
+	Authorization []string
+}
+
+// ExecStartCheck is a temp struct used by execStart
+// Config fields is part of ExecConfig in runconfig package
+type ExecStartCheck struct {
+	// ExecStart will first check if it's detached
+	Detach bool
+	// Check if there's a tty
+	Tty bool
+}
+
+// HealthcheckResult stores information about a single run of a healthcheck probe
+type HealthcheckResult struct {
+	Start    time.Time // Start is the time this check started
+	End      time.Time // End is the time this check ended
+	ExitCode int       // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe
+	Output   string    // Output from last check
+}
+
+// Health states
+const (
+	Starting  = "starting"  // Starting indicates that the container is not yet ready
+	Healthy   = "healthy"   // Healthy indicates that the container is running correctly
+	Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem
+)
+
+// Health stores information about the container's healthcheck results
+type Health struct {
+	Status        string               // Status is one of Starting, Healthy or Unhealthy
+	FailingStreak int                  // FailingStreak is the number of consecutive failures
+	Log           []*HealthcheckResult // Log contains the last few results (oldest first)
+}
+
+// ContainerState stores container's running state
+// it's part of ContainerJSONBase and will return by "inspect" command
+type ContainerState struct {
+	Status     string
+	Running    bool
+	Paused     bool
+	Restarting bool
+	OOMKilled  bool
+	Dead       bool
+	Pid        int
+	ExitCode   int
+	Error      string
+	StartedAt  string
+	FinishedAt string
+	Health     *Health `json:",omitempty"`
+}
+
+// ContainerNode stores information about the node that a container
+// is running on.  It's only available in Docker Swarm
+type ContainerNode struct {
+	ID        string
+	IPAddress string `json:"IP"`
+	Addr      string
+	Name      string
+	Cpus      int
+	Memory    int64
+	Labels    map[string]string
+}
+
+// ContainerJSONBase contains response of Remote API:
+// GET "/containers/{name:.*}/json"
+type ContainerJSONBase struct {
+	ID              string `json:"Id"`
+	Created         string
+	Path            string
+	Args            []string
+	State           *ContainerState
+	Image           string
+	ResolvConfPath  string
+	HostnamePath    string
+	HostsPath       string
+	LogPath         string
+	Node            *ContainerNode `json:",omitempty"`
+	Name            string
+	RestartCount    int
+	Driver          string
+	MountLabel      string
+	ProcessLabel    string
+	AppArmorProfile string
+	ExecIDs         []string
+	HostConfig      *container.HostConfig
+	GraphDriver     GraphDriverData
+	SizeRw          *int64 `json:",omitempty"`
+	SizeRootFs      *int64 `json:",omitempty"`
+}
+
+// ContainerJSON is newly used struct along with MountPoint
+type ContainerJSON struct {
+	*ContainerJSONBase
+	Mounts          []MountPoint
+	Config          *container.Config
+	NetworkSettings *NetworkSettings
+}
+
+// NetworkSettings exposes the network settings in the api
+type NetworkSettings struct {
+	NetworkSettingsBase
+	DefaultNetworkSettings
+	Networks map[string]*network.EndpointSettings
+}
+
+// SummaryNetworkSettings provides a summary of container's networks
+// in /containers/json
+type SummaryNetworkSettings struct {
+	Networks map[string]*network.EndpointSettings
+}
+
+// NetworkSettingsBase holds basic information about networks
+type NetworkSettingsBase struct {
+	Bridge                 string      // Bridge is the Bridge name the network uses(e.g. `docker0`)
+	SandboxID              string      // SandboxID uniquely represents a container's network stack
+	HairpinMode            bool        // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface
+	LinkLocalIPv6Address   string      // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix
+	LinkLocalIPv6PrefixLen int         // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address
+	Ports                  nat.PortMap // Ports is a collection of PortBinding indexed by Port
+	SandboxKey             string      // SandboxKey identifies the sandbox
+	SecondaryIPAddresses   []network.Address
+	SecondaryIPv6Addresses []network.Address
+}
+
+// DefaultNetworkSettings holds network information
+// during the 2 release deprecation period.
+// It will be removed in Docker 1.11.
+type DefaultNetworkSettings struct {
+	EndpointID          string // EndpointID uniquely represents a service endpoint in a Sandbox
+	Gateway             string // Gateway holds the gateway address for the network
+	GlobalIPv6Address   string // GlobalIPv6Address holds network's global IPv6 address
+	GlobalIPv6PrefixLen int    // GlobalIPv6PrefixLen represents mask length of network's global IPv6 address
+	IPAddress           string // IPAddress holds the IPv4 address for the network
+	IPPrefixLen         int    // IPPrefixLen represents mask length of network's IPv4 address
+	IPv6Gateway         string // IPv6Gateway holds gateway address specific for IPv6
+	MacAddress          string // MacAddress holds the MAC address for the network
+}
+
+// MountPoint represents a mount point configuration inside the container.
+type MountPoint struct {
+	Name        string `json:",omitempty"`
+	Source      string
+	Destination string
+	Driver      string `json:",omitempty"`
+	Mode        string
+	RW          bool
+	Propagation string
+}
+
+// Volume represents the configuration of a volume for the remote API
+type Volume struct {
+	Name       string                 // Name is the name of the volume
+	Driver     string                 // Driver is the Driver name used to create the volume
+	Mountpoint string                 // Mountpoint is the location on disk of the volume
+	Status     map[string]interface{} `json:",omitempty"` // Status provides low-level status information about the volume
+	Labels     map[string]string      // Labels is metadata specific to the volume
+	Scope      string                 // Scope describes the level at which the volume exists (e.g. `global` for cluster-wide or `local` for machine level)
+}
+
+// VolumesListResponse contains the response for the remote API:
+// GET "/volumes"
+type VolumesListResponse struct {
+	Volumes  []*Volume // Volumes is the list of volumes being returned
+	Warnings []string  // Warnings is a list of warnings that occurred when getting the list from the volume drivers
+}
+
+// VolumeCreateRequest contains the response for the remote API:
+// POST "/volumes/create"
+type VolumeCreateRequest struct {
+	Name       string            // Name is the requested name of the volume
+	Driver     string            // Driver is the name of the driver that should be used to create the volume
+	DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume.
+	Labels     map[string]string // Labels holds metadata specific to the volume being created.
+}
+
+// NetworkResource is the body of the "get network" http response message
+type NetworkResource struct {
+	Name       string                      // Name is the requested name of the network
+	ID         string                      `json:"Id"` // ID uniquely identifies a network on a single machine
+	Scope      string                      // Scope describes the level at which the network exists (e.g. `global` for cluster-wide or `local` for machine level)
+	Driver     string                      // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`)
+	EnableIPv6 bool                        // EnableIPv6 represents whether to enable IPv6
+	IPAM       network.IPAM                // IPAM is the network's IP Address Management
+	Internal   bool                        // Internal represents if the network is used internal only
+	Containers map[string]EndpointResource // Containers contains endpoints belonging to the network
+	Options    map[string]string           // Options holds the network specific options to use for when creating the network
+	Labels     map[string]string           // Labels holds metadata specific to the network being created
+}
+
+// EndpointResource contains network resources allocated and used for a container in a network
+type EndpointResource struct {
+	Name        string
+	EndpointID  string
+	MacAddress  string
+	IPv4Address string
+	IPv6Address string
+}
+
+// NetworkCreate is the expected body of the "create network" http request message
+type NetworkCreate struct {
+	CheckDuplicate bool
+	Driver         string
+	EnableIPv6     bool
+	IPAM           network.IPAM
+	Internal       bool
+	Options        map[string]string
+	Labels         map[string]string
+}
+
+// NetworkCreateRequest is the request message sent to the server for network create call.
+type NetworkCreateRequest struct {
+	NetworkCreate
+	Name string
+}
+
+// NetworkCreateResponse is the response message sent by the server for network create call
+type NetworkCreateResponse struct {
+	ID      string `json:"Id"`
+	Warning string
+}
+
+// NetworkConnect represents the data to be used to connect a container to the network
+type NetworkConnect struct {
+	Container      string
+	EndpointConfig *network.EndpointSettings `json:",omitempty"`
+}
+
+// NetworkDisconnect represents the data to be used to disconnect a container from the network
+type NetworkDisconnect struct {
+	Container string
+	Force     bool
+}
+
+// Checkpoint represents the details of a checkpoint
+type Checkpoint struct {
+	Name string // Name is the name of the checkpoint
+}
+
+// Runtime describes an OCI runtime
+type Runtime struct {
+	Path string   `json:"path"`
+	Args []string `json:"runtimeArgs,omitempty"`
+}
diff --git a/vendor/github.com/docker/engine-api/types/versions/README.md b/vendor/github.com/docker/engine-api/types/versions/README.md
new file mode 100644
index 00000000..cdac50a5
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/versions/README.md
@@ -0,0 +1,14 @@
+## Legacy API type versions
+
+This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`.
+
+Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`.
+
+### Package name conventions
+
+The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention:
+
+1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`.
+2. We cannot use `_` because golint complains about it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`.
+
+For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`.
diff --git a/vendor/github.com/docker/engine-api/types/versions/compare.go b/vendor/github.com/docker/engine-api/types/versions/compare.go
new file mode 100644
index 00000000..611d4fed
--- /dev/null
+++ b/vendor/github.com/docker/engine-api/types/versions/compare.go
@@ -0,0 +1,62 @@
+package versions
+
+import (
+	"strconv"
+	"strings"
+)
+
+// compare compares two version strings
+// returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
+func compare(v1, v2 string) int {
+	var (
+		currTab  = strings.Split(v1, ".")
+		otherTab = strings.Split(v2, ".")
+	)
+
+	max := len(currTab)
+	if len(otherTab) > max {
+		max = len(otherTab)
+	}
+	for i := 0; i < max; i++ {
+		var currInt, otherInt int
+
+		if len(currTab) > i {
+			currInt, _ = strconv.Atoi(currTab[i])
+		}
+		if len(otherTab) > i {
+			otherInt, _ = strconv.Atoi(otherTab[i])
+		}
+		if currInt > otherInt {
+			return 1
+		}
+		if otherInt > currInt {
+			return -1
+		}
+	}
+	return 0
+}
+
+// LessThan checks if a version is less than another
+func LessThan(v, other string) bool {
+	return compare(v, other) == -1
+}
+
+// LessThanOrEqualTo checks if a version is less than or equal to another
+func LessThanOrEqualTo(v, other string) bool {
+	return compare(v, other) <= 0
+}
+
+// GreaterThan checks if a version is greater than another
+func GreaterThan(v, other string) bool {
+	return compare(v, other) == 1
+}
+
+// GreaterThanOrEqualTo checks if a version is greater than or equal to another
+func GreaterThanOrEqualTo(v, other string) bool {
+	return compare(v, other) >= 0
+}
+
+// Equal checks if a version is equal to another
+func Equal(v, other string) bool {
+	return compare(v, other) == 0
+}
diff --git a/vendor/github.com/docker/go-connections/nat/nat.go b/vendor/github.com/docker/go-connections/nat/nat.go
new file mode 100644
index 00000000..3d469165
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/nat/nat.go
@@ -0,0 +1,223 @@
+// Package nat is a convenience package for manipulation of strings describing network ports.
+package nat
+
+import (
+	"fmt"
+	"net"
+	"strconv"
+	"strings"
+)
+
+const (
+	// portSpecTemplate is the expected format for port specifications
+	portSpecTemplate = "ip:hostPort:containerPort"
+)
+
+// PortBinding represents a binding between a Host IP address and a Host Port
+type PortBinding struct {
+	// HostIP is the host IP Address
+	HostIP string `json:"HostIp"`
+	// HostPort is the host port number
+	HostPort string
+}
+
+// PortMap is a collection of PortBinding indexed by Port
+type PortMap map[Port][]PortBinding
+
+// PortSet is a collection of structs indexed by Port
+type PortSet map[Port]struct{}
+
+// Port is a string containing port number and protocol in the format "80/tcp"
+type Port string
+
+// NewPort creates a new instance of a Port given a protocol and port number or port range
+func NewPort(proto, port string) (Port, error) {
+	// Check for parsing issues on "port" now so we can avoid having
+	// to check it later on.
+
+	portStartInt, portEndInt, err := ParsePortRangeToInt(port)
+	if err != nil {
+		return "", err
+	}
+
+	if portStartInt == portEndInt {
+		return Port(fmt.Sprintf("%d/%s", portStartInt, proto)), nil
+	}
+	return Port(fmt.Sprintf("%d-%d/%s", portStartInt, portEndInt, proto)), nil
+}
+
+// ParsePort parses the port number string and returns an int
+func ParsePort(rawPort string) (int, error) {
+	if len(rawPort) == 0 {
+		return 0, nil
+	}
+	port, err := strconv.ParseUint(rawPort, 10, 16)
+	if err != nil {
+		return 0, err
+	}
+	return int(port), nil
+}
+
+// ParsePortRangeToInt parses the port range string and returns start/end ints
+func ParsePortRangeToInt(rawPort string) (int, int, error) {
+	if len(rawPort) == 0 {
+		return 0, 0, nil
+	}
+	start, end, err := ParsePortRange(rawPort)
+	if err != nil {
+		return 0, 0, err
+	}
+	return int(start), int(end), nil
+}
+
+// Proto returns the protocol of a Port
+func (p Port) Proto() string {
+	proto, _ := SplitProtoPort(string(p))
+	return proto
+}
+
+// Port returns the port number of a Port
+func (p Port) Port() string {
+	_, port := SplitProtoPort(string(p))
+	return port
+}
+
+// Int returns the port number of a Port as an int
+func (p Port) Int() int {
+	portStr := p.Port()
+	if len(portStr) == 0 {
+		return 0
+	}
+
+	// We don't need to check for an error because we're going to
+	// assume that any error would have been found, and reported, in NewPort()
+	port, _ := strconv.ParseUint(portStr, 10, 16)
+	return int(port)
+}
+
+// Range returns the start/end port numbers of a Port range as ints
+func (p Port) Range() (int, int, error) {
+	return ParsePortRangeToInt(p.Port())
+}
+
+// SplitProtoPort splits a port in the format of proto/port
+func SplitProtoPort(rawPort string) (string, string) {
+	parts := strings.Split(rawPort, "/")
+	l := len(parts)
+	if len(rawPort) == 0 || l == 0 || len(parts[0]) == 0 {
+		return "", ""
+	}
+	if l == 1 {
+		return "tcp", rawPort
+	}
+	if len(parts[1]) == 0 {
+		return "tcp", parts[0]
+	}
+	return parts[1], parts[0]
+}
+
+func validateProto(proto string) bool {
+	for _, availableProto := range []string{"tcp", "udp"} {
+		if availableProto == proto {
+			return true
+		}
+	}
+	return false
+}
+
+// ParsePortSpecs receives port specs in the format of ip:public:private/proto and parses
+// these in to the internal types
+func ParsePortSpecs(ports []string) (map[Port]struct{}, map[Port][]PortBinding, error) {
+	var (
+		exposedPorts = make(map[Port]struct{}, len(ports))
+		bindings     = make(map[Port][]PortBinding)
+	)
+
+	for _, rawPort := range ports {
+		proto := "tcp"
+
+		if i := strings.LastIndex(rawPort, "/"); i != -1 {
+			proto = rawPort[i+1:]
+			rawPort = rawPort[:i]
+		}
+		if !strings.Contains(rawPort, ":") {
+			rawPort = fmt.Sprintf("::%s", rawPort)
+		} else if len(strings.Split(rawPort, ":")) == 2 {
+			rawPort = fmt.Sprintf(":%s", rawPort)
+		}
+
+		parts, err := PartParser(portSpecTemplate, rawPort)
+		if err != nil {
+			return nil, nil, err
+		}
+
+		var (
+			containerPort = parts["containerPort"]
+			rawIP         = parts["ip"]
+			hostPort      = parts["hostPort"]
+		)
+
+		if rawIP != "" && net.ParseIP(rawIP) == nil {
+			return nil, nil, fmt.Errorf("Invalid ip address: %s", rawIP)
+		}
+		if containerPort == "" {
+			return nil, nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
+		}
+
+		startPort, endPort, err := ParsePortRange(containerPort)
+		if err != nil {
+			return nil, nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
+		}
+
+		var startHostPort, endHostPort uint64 = 0, 0
+		if len(hostPort) > 0 {
+			startHostPort, endHostPort, err = ParsePortRange(hostPort)
+			if err != nil {
+				return nil, nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
+			}
+		}
+
+		if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
+			// Allow host port range iff containerPort is not a range.
+			// In this case, use the host port range as the dynamic
+			// host port range to allocate into.
+			if endPort != startPort {
+				return nil, nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
+			}
+		}
+
+		if !validateProto(strings.ToLower(proto)) {
+			return nil, nil, fmt.Errorf("Invalid proto: %s", proto)
+		}
+
+		for i := uint64(0); i <= (endPort - startPort); i++ {
+			containerPort = strconv.FormatUint(startPort+i, 10)
+			if len(hostPort) > 0 {
+				hostPort = strconv.FormatUint(startHostPort+i, 10)
+			}
+			// Set hostPort to a range only if there is a single container port
+			// and a dynamic host port.
+			if startPort == endPort && startHostPort != endHostPort {
+				hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
+			}
+			port, err := NewPort(strings.ToLower(proto), containerPort)
+			if err != nil {
+				return nil, nil, err
+			}
+			if _, exists := exposedPorts[port]; !exists {
+				exposedPorts[port] = struct{}{}
+			}
+
+			binding := PortBinding{
+				HostIP:   rawIP,
+				HostPort: hostPort,
+			}
+			bslice, exists := bindings[port]
+			if !exists {
+				bslice = []PortBinding{}
+			}
+			bindings[port] = append(bslice, binding)
+		}
+	}
+	return exposedPorts, bindings, nil
+}
diff --git a/vendor/github.com/docker/go-connections/nat/parse.go b/vendor/github.com/docker/go-connections/nat/parse.go
new file mode 100644
index 00000000..87205020
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/nat/parse.go
@@ -0,0 +1,56 @@
+package nat
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// PartParser parses and validates the specified string (data) using the specified template
+// e.g. ip:public:private -> 192.168.0.1:80:8000
+func PartParser(template, data string) (map[string]string, error) {
+	// ip:public:private
+	var (
+		templateParts = strings.Split(template, ":")
+		parts         = strings.Split(data, ":")
+		out           = make(map[string]string, len(templateParts))
+	)
+	if len(parts) != len(templateParts) {
+		return nil, fmt.Errorf("Invalid format to parse. %s should match template %s", data, template)
+	}
+
+	for i, t := range templateParts {
+		value := ""
+		if len(parts) > i {
+			value = parts[i]
+		}
+		out[t] = value
+	}
+	return out, nil
+}
+
+// ParsePortRange parses and validates the specified string as a port-range (8000-9000)
+func ParsePortRange(ports string) (uint64, uint64, error) {
+	if ports == "" {
+		return 0, 0, fmt.Errorf("Empty string specified for ports.")
+	}
+	if !strings.Contains(ports, "-") {
+		start, err := strconv.ParseUint(ports, 10, 16)
+		end := start
+		return start, end, err
+	}
+
+	parts := strings.Split(ports, "-")
+	start, err := strconv.ParseUint(parts[0], 10, 16)
+	if err != nil {
+		return 0, 0, err
+	}
+	end, err := strconv.ParseUint(parts[1], 10, 16)
+	if err != nil {
+		return 0, 0, err
+	}
+	if end < start {
+		return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports)
+	}
+	return start, end, nil
+}
diff --git a/vendor/github.com/docker/go-connections/nat/sort.go b/vendor/github.com/docker/go-connections/nat/sort.go
new file mode 100644
index 00000000..ce950171
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/nat/sort.go
@@ -0,0 +1,96 @@
+package nat
+
+import (
+	"sort"
+	"strings"
+)
+
+type portSorter struct {
+	ports []Port
+	by    func(i, j Port) bool
+}
+
+func (s *portSorter) Len() int {
+	return len(s.ports)
+}
+
+func (s *portSorter) Swap(i, j int) {
+	s.ports[i], s.ports[j] = s.ports[j], s.ports[i]
+}
+
+func (s *portSorter) Less(i, j int) bool {
+	ip := s.ports[i]
+	jp := s.ports[j]
+
+	return s.by(ip, jp)
+}
+
+// Sort sorts a list of ports using the provided predicate
+// This function should compare `i` and `j`, returning true if `i` is
+// considered to be less than `j`
+func Sort(ports []Port, predicate func(i, j Port) bool) {
+	s := &portSorter{ports, predicate}
+	sort.Sort(s)
+}
+
+type portMapEntry struct {
+	port    Port
+	binding PortBinding
+}
+
+type portMapSorter []portMapEntry
+
+func (s portMapSorter) Len() int      { return len(s) }
+func (s portMapSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// sort the port so that the order is:
+// 1. port with larger specified bindings
+// 2. larger port
+// 3. port with tcp protocol
+func (s portMapSorter) Less(i, j int) bool {
+	pi, pj := s[i].port, s[j].port
+	hpi, hpj := toInt(s[i].binding.HostPort), toInt(s[j].binding.HostPort)
+	return hpi > hpj || pi.Int() > pj.Int() || (pi.Int() == pj.Int() && strings.ToLower(pi.Proto()) == "tcp")
+}
+
+// SortPortMap sorts the list of ports and their respected mapping. The ports
+// will explicit HostPort will be placed first.
+func SortPortMap(ports []Port, bindings PortMap) {
+	s := portMapSorter{}
+	for _, p := range ports {
+		if binding, ok := bindings[p]; ok {
+			for _, b := range binding {
+				s = append(s, portMapEntry{port: p, binding: b})
+			}
+			bindings[p] = []PortBinding{}
+		} else {
+			s = append(s, portMapEntry{port: p})
+		}
+	}
+
+	sort.Sort(s)
+	var (
+		i  int
+		pm = make(map[Port]struct{})
+	)
+	// reorder ports
+	for _, entry := range s {
+		if _, ok := pm[entry.port]; !ok {
+			ports[i] = entry.port
+			pm[entry.port] = struct{}{}
+			i++
+		}
+		// reorder bindings for this port
+		if _, ok := bindings[entry.port]; ok {
+			bindings[entry.port] = append(bindings[entry.port], entry.binding)
+		}
+	}
+}
+
+func toInt(s string) uint64 {
+	i, _, err := ParsePortRange(s)
+	if err != nil {
+		i = 0
+	}
+	return i
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/README.md b/vendor/github.com/docker/go-connections/sockets/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/vendor/github.com/docker/go-connections/sockets/inmem_socket.go b/vendor/github.com/docker/go-connections/sockets/inmem_socket.go
new file mode 100644
index 00000000..3395e402
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/inmem_socket.go
@@ -0,0 +1,89 @@
+package sockets
+
+import (
+	"errors"
+	"net"
+	"sync"
+)
+
+var errClosed = errors.New("use of closed network connection")
+
+// InmemSocket implements net.Listener using in-memory only connections.
+type InmemSocket struct {
+	chConn  chan net.Conn
+	chClose chan struct{}
+	addr    string
+	mu      sync.Mutex
+}
+
+// dummyAddr is used to satisfy net.Addr for the in-mem socket
+// it is just stored as a string and returns the string for all calls
+type dummyAddr string
+
+// NewInmemSocket creates an in-memory only net.Listener
+// The addr argument can be any string, but is used to satisfy the `Addr()` part
+// of the net.Listener interface
+func NewInmemSocket(addr string, bufSize int) *InmemSocket {
+	return &InmemSocket{
+		chConn:  make(chan net.Conn, bufSize),
+		chClose: make(chan struct{}),
+		addr:    addr,
+	}
+}
+
+// Addr returns the socket's addr string to satisfy net.Listener
+func (s *InmemSocket) Addr() net.Addr {
+	return dummyAddr(s.addr)
+}
+
+// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
+func (s *InmemSocket) Accept() (net.Conn, error) {
+	select {
+	case conn := <-s.chConn:
+		return conn, nil
+	case <-s.chClose:
+		return nil, errClosed
+	}
+}
+
+// Close closes the listener. It will be unavailable for use once closed.
+func (s *InmemSocket) Close() error {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	select {
+	case <-s.chClose:
+	default:
+		close(s.chClose)
+	}
+	return nil
+}
+
+// Dial is used to establish a connection with the in-mem server
+func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) {
+	srvConn, clientConn := net.Pipe()
+	select {
+	case s.chConn <- srvConn:
+	case <-s.chClose:
+		return nil, errClosed
+	}
+
+	return clientConn, nil
+}
+
+// Network returns the addr string, satisfies net.Addr
+func (a dummyAddr) Network() string {
+	return string(a)
+}
+
+// String returns the string form
+func (a dummyAddr) String() string {
+	return string(a)
+}
+
+// timeoutError is used when there is a timeout with a connection
+// this implements the net.Error interface
+type timeoutError struct{}
+
+func (e *timeoutError) Error() string   { return "i/o timeout" }
+func (e *timeoutError) Timeout() bool   { return true }
+func (e *timeoutError) Temporary() bool { return true }
diff --git a/vendor/github.com/docker/go-connections/sockets/proxy.go b/vendor/github.com/docker/go-connections/sockets/proxy.go
new file mode 100644
index 00000000..98e9a1dc
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/proxy.go
@@ -0,0 +1,51 @@
+package sockets
+
+import (
+	"net"
+	"net/url"
+	"os"
+	"strings"
+
+	"golang.org/x/net/proxy"
+)
+
+// GetProxyEnv allows access to the uppercase and the lowercase forms of
+// proxy-related variables.  See the Go specification for details on these
+// variables. https://golang.org/pkg/net/http/
+func GetProxyEnv(key string) string {
+	proxyValue := os.Getenv(strings.ToUpper(key))
+	if proxyValue == "" {
+		return os.Getenv(strings.ToLower(key))
+	}
+	return proxyValue
+}
+
+// DialerFromEnvironment takes in a "direct" *net.Dialer and returns a
+// proxy.Dialer which will route the connections through the proxy using the
+// given dialer.
+func DialerFromEnvironment(direct *net.Dialer) (proxy.Dialer, error) {
+	allProxy := GetProxyEnv("all_proxy")
+	if len(allProxy) == 0 {
+		return direct, nil
+	}
+
+	proxyURL, err := url.Parse(allProxy)
+	if err != nil {
+		return direct, err
+	}
+
+	proxyFromURL, err := proxy.FromURL(proxyURL, direct)
+	if err != nil {
+		return direct, err
+	}
+
+	noProxy := GetProxyEnv("no_proxy")
+	if len(noProxy) == 0 {
+		return proxyFromURL, nil
+	}
+
+	perHost := proxy.NewPerHost(proxyFromURL, direct)
+	perHost.AddFromString(noProxy)
+
+	return perHost, nil
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets.go b/vendor/github.com/docker/go-connections/sockets/sockets.go
new file mode 100644
index 00000000..1739cecf
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/sockets.go
@@ -0,0 +1,42 @@
+// Package sockets provides helper functions to create and configure Unix or TCP sockets.
+package sockets
+
+import (
+	"net"
+	"net/http"
+	"time"
+)
+
+// Why 32? See https://github.com/docker/docker/pull/8035.
+const defaultTimeout = 32 * time.Second
+
+// ConfigureTransport configures the specified Transport according to the
+// specified proto and addr.
+// If the proto is unix (using a unix socket to communicate) or npipe the
+// compression is disabled.
+func ConfigureTransport(tr *http.Transport, proto, addr string) error {
+	switch proto {
+	case "unix":
+		// No need for compression in local communications.
+		tr.DisableCompression = true
+		tr.Dial = func(_, _ string) (net.Conn, error) {
+			return net.DialTimeout(proto, addr, defaultTimeout)
+		}
+	case "npipe":
+		// No need for compression in local communications.
+		tr.DisableCompression = true
+		tr.Dial = func(_, _ string) (net.Conn, error) {
+			return DialPipe(addr, defaultTimeout)
+		}
+	default:
+		tr.Proxy = http.ProxyFromEnvironment
+		dialer, err := DialerFromEnvironment(&net.Dialer{
+			Timeout: defaultTimeout,
+		})
+		if err != nil {
+			return err
+		}
+		tr.Dial = dialer.Dial
+	}
+	return nil
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
new file mode 100644
index 00000000..b255ac9a
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
@@ -0,0 +1,15 @@
+// +build !windows
+
+package sockets
+
+import (
+	"net"
+	"syscall"
+	"time"
+)
+
+// DialPipe connects to a Windows named pipe.
+// This is not supported on other OSes.
+func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
+	return nil, syscall.EAFNOSUPPORT
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
new file mode 100644
index 00000000..1f3540b2
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
@@ -0,0 +1,13 @@
+package sockets
+
+import (
+	"net"
+	"time"
+
+	"github.com/Microsoft/go-winio"
+)
+
+// DialPipe connects to a Windows named pipe.
+func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
+	return winio.DialPipe(addr, &timeout)
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/tcp_socket.go b/vendor/github.com/docker/go-connections/sockets/tcp_socket.go
new file mode 100644
index 00000000..8a82727d
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/tcp_socket.go
@@ -0,0 +1,22 @@
+// Package sockets provides helper functions to create and configure Unix or TCP sockets.
+package sockets
+
+import (
+	"crypto/tls"
+	"net"
+)
+
+// NewTCPSocket creates a TCP socket listener with the specified address and
+// and the specified tls configuration. If TLSConfig is set, will encapsulate the
+// TCP listener inside a TLS one.
+func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
+	l, err := net.Listen("tcp", addr)
+	if err != nil {
+		return nil, err
+	}
+	if tlsConfig != nil {
+		tlsConfig.NextProtos = []string{"http/1.1"}
+		l = tls.NewListener(l, tlsConfig)
+	}
+	return l, nil
+}
diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket.go b/vendor/github.com/docker/go-connections/sockets/unix_socket.go
new file mode 100644
index 00000000..d1627349
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/sockets/unix_socket.go
@@ -0,0 +1,80 @@
+// +build linux freebsd solaris
+
+package sockets
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"strconv"
+	"syscall"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/opencontainers/runc/libcontainer/user"
+)
+
+// NewUnixSocket creates a unix socket with the specified path and group.
+func NewUnixSocket(path, group string) (net.Listener, error) {
+	if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
+		return nil, err
+	}
+	mask := syscall.Umask(0777)
+	defer syscall.Umask(mask)
+	l, err := net.Listen("unix", path)
+	if err != nil {
+		return nil, err
+	}
+	if err := setSocketGroup(path, group); err != nil {
+		l.Close()
+		return nil, err
+	}
+	if err := os.Chmod(path, 0660); err != nil {
+		l.Close()
+		return nil, err
+	}
+	return l, nil
+}
+
+func setSocketGroup(path, group string) error {
+	if group == "" {
+		return nil
+	}
+	if err := changeGroup(path, group); err != nil {
+		if group != "docker" {
+			return err
+		}
+		logrus.Debugf("Warning: could not change group %s to docker: %v", path, err)
+	}
+	return nil
+}
+
+func changeGroup(path string, nameOrGid string) error {
+	gid, err := lookupGidByName(nameOrGid)
+	if err != nil {
+		return err
+	}
+	logrus.Debugf("%s group found. gid: %d", nameOrGid, gid)
+	return os.Chown(path, 0, gid)
+}
+
+func lookupGidByName(nameOrGid string) (int, error) {
+	groupFile, err := user.GetGroupPath()
+	if err != nil {
+		return -1, err
+	}
+	groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool {
+		return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid
+	})
+	if err != nil {
+		return -1, err
+	}
+	if groups != nil && len(groups) > 0 {
+		return groups[0].Gid, nil
+	}
+	gid, err := strconv.Atoi(nameOrGid)
+	if err == nil {
+		logrus.Warnf("Could not find GID %d", gid)
+		return gid, nil
+	}
+	return -1, fmt.Errorf("Group %s not found", nameOrGid)
+}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config.go b/vendor/github.com/docker/go-connections/tlsconfig/config.go
new file mode 100644
index 00000000..9378c358
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/tlsconfig/config.go
@@ -0,0 +1,127 @@
+// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
+//
+// As a reminder from https://golang.org/pkg/crypto/tls/#Config:
+//	A Config structure is used to configure a TLS client or server. After one has been passed to a TLS function it must not be modified.
+//	A Config may be reused; the tls package will also not modify it.
+package tlsconfig
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"fmt"
+	"io/ioutil"
+	"os"
+
+	"github.com/Sirupsen/logrus"
+)
+
+// Options represents the information needed to create client and server TLS configurations.
+type Options struct {
+	CAFile string
+
+	// If either CertFile or KeyFile is empty, Client() will not load them
+	// preventing the client from authenticating to the server.
+	// However, Server() requires them and will error out if they are empty.
+	CertFile string
+	KeyFile  string
+
+	// client-only option
+	InsecureSkipVerify bool
+	// server-only option
+	ClientAuth tls.ClientAuthType
+}
+
+// Extra (server-side) accepted CBC cipher suites - will phase out in the future
+var acceptedCBCCiphers = []uint16{
+	tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+	tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+	tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+	tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+	tls.TLS_RSA_WITH_AES_128_CBC_SHA,
+}
+
+// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls
+// options struct but wants to use a commonly accepted set of TLS cipher suites, with
+// known weak algorithms removed.
+var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
+
+// ServerDefault is a secure-enough TLS configuration for the server TLS configuration.
+var ServerDefault = tls.Config{
+	// Avoid fallback to SSL protocols < TLS1.0
+	MinVersion:               tls.VersionTLS10,
+	PreferServerCipherSuites: true,
+	CipherSuites:             DefaultServerAcceptedCiphers,
+}
+
+// ClientDefault is a secure-enough TLS configuration for the client TLS configuration.
+var ClientDefault = tls.Config{
+	// Prefer TLS1.2 as the client minimum
+	MinVersion:   tls.VersionTLS12,
+	CipherSuites: clientCipherSuites,
+}
+
+// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
+func certPool(caFile string) (*x509.CertPool, error) {
+	// If we should verify the server, we need to load a trusted ca
+	certPool := x509.NewCertPool()
+	pem, err := ioutil.ReadFile(caFile)
+	if err != nil {
+		return nil, fmt.Errorf("Could not read CA certificate %q: %v", caFile, err)
+	}
+	if !certPool.AppendCertsFromPEM(pem) {
+		return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
+	}
+	s := certPool.Subjects()
+	subjects := make([]string, len(s))
+	for i, subject := range s {
+		subjects[i] = string(subject)
+	}
+	logrus.Debugf("Trusting certs with subjects: %v", subjects)
+	return certPool, nil
+}
+
+// Client returns a TLS configuration meant to be used by a client.
+func Client(options Options) (*tls.Config, error) {
+	tlsConfig := ClientDefault
+	tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
+	if !options.InsecureSkipVerify && options.CAFile != "" {
+		CAs, err := certPool(options.CAFile)
+		if err != nil {
+			return nil, err
+		}
+		tlsConfig.RootCAs = CAs
+	}
+
+	if options.CertFile != "" || options.KeyFile != "" {
+		tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
+		if err != nil {
+			return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err)
+		}
+		tlsConfig.Certificates = []tls.Certificate{tlsCert}
+	}
+
+	return &tlsConfig, nil
+}
+
+// Server returns a TLS configuration meant to be used by a server.
+func Server(options Options) (*tls.Config, error) {
+	tlsConfig := ServerDefault
+	tlsConfig.ClientAuth = options.ClientAuth
+	tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return nil, fmt.Errorf("Could not load X509 key pair (cert: %q, key: %q): %v", options.CertFile, options.KeyFile, err)
+		}
+		return nil, fmt.Errorf("Error reading X509 key pair (cert: %q, key: %q): %v. Make sure the key is not encrypted.", options.CertFile, options.KeyFile, err)
+	}
+	tlsConfig.Certificates = []tls.Certificate{tlsCert}
+	if options.ClientAuth >= tls.VerifyClientCertIfGiven {
+		CAs, err := certPool(options.CAFile)
+		if err != nil {
+			return nil, err
+		}
+		tlsConfig.ClientCAs = CAs
+	}
+	return &tlsConfig, nil
+}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
new file mode 100644
index 00000000..6b4c6a7c
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
@@ -0,0 +1,17 @@
+// +build go1.5
+
+// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
+//
+package tlsconfig
+
+import (
+	"crypto/tls"
+)
+
+// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
+var clientCipherSuites = []uint16{
+	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go b/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go
new file mode 100644
index 00000000..ee22df47
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go
@@ -0,0 +1,15 @@
+// +build !go1.5
+
+// Package tlsconfig provides primitives to retrieve secure-enough TLS configurations for both clients and servers.
+//
+package tlsconfig
+
+import (
+	"crypto/tls"
+)
+
+// Client TLS cipher suites (dropping CBC ciphers for client preferred suite set)
+var clientCipherSuites = []uint16{
+	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+}
diff --git a/vendor/github.com/docker/go-units/README.md b/vendor/github.com/docker/go-units/README.md
new file mode 100644
index 00000000..e2fb4051
--- /dev/null
+++ b/vendor/github.com/docker/go-units/README.md
@@ -0,0 +1,13 @@
+[![GoDoc](https://godoc.org/github.com/docker/go-units?status.svg)](https://godoc.org/github.com/docker/go-units)
+
+# Introduction
+
+go-units is a library to transform human friendly measurements into machine friendly values.
+
+## Usage
+
+See the [docs in godoc](https://godoc.org/github.com/docker/go-units) for examples and documentation.
+
+## License
+
+go-units is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text.
diff --git a/vendor/github.com/docker/go-units/circle.yml b/vendor/github.com/docker/go-units/circle.yml
new file mode 100644
index 00000000..9043b354
--- /dev/null
+++ b/vendor/github.com/docker/go-units/circle.yml
@@ -0,0 +1,11 @@
+dependencies:
+  post:
+    # install golint
+    - go get github.com/golang/lint/golint
+
+test:
+  pre:
+    # run analysis before tests
+    - go vet ./...
+    - test -z "$(golint ./... | tee /dev/stderr)"
+    - test -z "$(gofmt -s -l . | tee /dev/stderr)"
diff --git a/vendor/github.com/docker/go-units/duration.go b/vendor/github.com/docker/go-units/duration.go
new file mode 100644
index 00000000..c219a8a9
--- /dev/null
+++ b/vendor/github.com/docker/go-units/duration.go
@@ -0,0 +1,33 @@
+// Package units provides helper function to parse and print size and time units
+// in human-readable format.
+package units
+
+import (
+	"fmt"
+	"time"
+)
+
+// HumanDuration returns a human-readable approximation of a duration
+// (eg. "About a minute", "4 hours ago", etc.).
+func HumanDuration(d time.Duration) string {
+	if seconds := int(d.Seconds()); seconds < 1 {
+		return "Less than a second"
+	} else if seconds < 60 {
+		return fmt.Sprintf("%d seconds", seconds)
+	} else if minutes := int(d.Minutes()); minutes == 1 {
+		return "About a minute"
+	} else if minutes < 60 {
+		return fmt.Sprintf("%d minutes", minutes)
+	} else if hours := int(d.Hours()); hours == 1 {
+		return "About an hour"
+	} else if hours < 48 {
+		return fmt.Sprintf("%d hours", hours)
+	} else if hours < 24*7*2 {
+		return fmt.Sprintf("%d days", hours/24)
+	} else if hours < 24*30*3 {
+		return fmt.Sprintf("%d weeks", hours/24/7)
+	} else if hours < 24*365*2 {
+		return fmt.Sprintf("%d months", hours/24/30)
+	}
+	return fmt.Sprintf("%d years", int(d.Hours())/24/365)
+}
diff --git a/vendor/github.com/docker/go-units/size.go b/vendor/github.com/docker/go-units/size.go
new file mode 100644
index 00000000..3b59daff
--- /dev/null
+++ b/vendor/github.com/docker/go-units/size.go
@@ -0,0 +1,95 @@
+package units
+
+import (
+	"fmt"
+	"regexp"
+	"strconv"
+	"strings"
+)
+
+// See: http://en.wikipedia.org/wiki/Binary_prefix
+const (
+	// Decimal
+
+	KB = 1000
+	MB = 1000 * KB
+	GB = 1000 * MB
+	TB = 1000 * GB
+	PB = 1000 * TB
+
+	// Binary
+
+	KiB = 1024
+	MiB = 1024 * KiB
+	GiB = 1024 * MiB
+	TiB = 1024 * GiB
+	PiB = 1024 * TiB
+)
+
+type unitMap map[string]int64
+
+var (
+	decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB}
+	binaryMap  = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB}
+	sizeRegex  = regexp.MustCompile(`^(\d+)([kKmMgGtTpP])?[bB]?$`)
+)
+
+var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
+var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
+
+// CustomSize returns a human-readable approximation of a size
+// using custom format.
+func CustomSize(format string, size float64, base float64, _map []string) string {
+	i := 0
+	for size >= base {
+		size = size / base
+		i++
+	}
+	return fmt.Sprintf(format, size, _map[i])
+}
+
+// HumanSize returns a human-readable approximation of a size
+// capped at 4 valid numbers (eg. "2.746 MB", "796 KB").
+func HumanSize(size float64) string {
+	return CustomSize("%.4g %s", size, 1000.0, decimapAbbrs)
+}
+
+// BytesSize returns a human-readable size in bytes, kibibytes,
+// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB").
+func BytesSize(size float64) string {
+	return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs)
+}
+
+// FromHumanSize returns an integer from a human-readable specification of a
+// size using SI standard (eg. "44kB", "17MB").
+func FromHumanSize(size string) (int64, error) {
+	return parseSize(size, decimalMap)
+}
+
+// RAMInBytes parses a human-readable string representing an amount of RAM
+// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and
+// returns the number of bytes, or -1 if the string is unparseable.
+// Units are case-insensitive, and the 'b' suffix is optional.
+func RAMInBytes(size string) (int64, error) {
+	return parseSize(size, binaryMap)
+}
+
+// Parses the human-readable size string into the amount it represents.
+func parseSize(sizeStr string, uMap unitMap) (int64, error) {
+	matches := sizeRegex.FindStringSubmatch(sizeStr)
+	if len(matches) != 3 {
+		return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
+	}
+
+	size, err := strconv.ParseInt(matches[1], 10, 0)
+	if err != nil {
+		return -1, err
+	}
+
+	unitPrefix := strings.ToLower(matches[2])
+	if mul, ok := uMap[unitPrefix]; ok {
+		size *= mul
+	}
+
+	return size, nil
+}
diff --git a/vendor/github.com/docker/go-units/ulimit.go b/vendor/github.com/docker/go-units/ulimit.go
new file mode 100644
index 00000000..f0a7be29
--- /dev/null
+++ b/vendor/github.com/docker/go-units/ulimit.go
@@ -0,0 +1,109 @@
+package units
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// Ulimit is a human friendly version of Rlimit.
+type Ulimit struct {
+	Name string
+	Hard int64
+	Soft int64
+}
+
+// Rlimit specifies the resource limits, such as max open files.
+type Rlimit struct {
+	Type int    `json:"type,omitempty"`
+	Hard uint64 `json:"hard,omitempty"`
+	Soft uint64 `json:"soft,omitempty"`
+}
+
+const (
+	// magic numbers for making the syscall
+	// some of these are defined in the syscall package, but not all.
+	// Also since Windows client doesn't get access to the syscall package, need to
+	//	define these here
+	rlimitAs         = 9
+	rlimitCore       = 4
+	rlimitCPU        = 0
+	rlimitData       = 2
+	rlimitFsize      = 1
+	rlimitLocks      = 10
+	rlimitMemlock    = 8
+	rlimitMsgqueue   = 12
+	rlimitNice       = 13
+	rlimitNofile     = 7
+	rlimitNproc      = 6
+	rlimitRss        = 5
+	rlimitRtprio     = 14
+	rlimitRttime     = 15
+	rlimitSigpending = 11
+	rlimitStack      = 3
+)
+
+var ulimitNameMapping = map[string]int{
+	//"as":         rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
+	"core":       rlimitCore,
+	"cpu":        rlimitCPU,
+	"data":       rlimitData,
+	"fsize":      rlimitFsize,
+	"locks":      rlimitLocks,
+	"memlock":    rlimitMemlock,
+	"msgqueue":   rlimitMsgqueue,
+	"nice":       rlimitNice,
+	"nofile":     rlimitNofile,
+	"nproc":      rlimitNproc,
+	"rss":        rlimitRss,
+	"rtprio":     rlimitRtprio,
+	"rttime":     rlimitRttime,
+	"sigpending": rlimitSigpending,
+	"stack":      rlimitStack,
+}
+
+// ParseUlimit parses and returns a Ulimit from the specified string.
+func ParseUlimit(val string) (*Ulimit, error) {
+	parts := strings.SplitN(val, "=", 2)
+	if len(parts) != 2 {
+		return nil, fmt.Errorf("invalid ulimit argument: %s", val)
+	}
+
+	if _, exists := ulimitNameMapping[parts[0]]; !exists {
+		return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
+	}
+
+	limitVals := strings.SplitN(parts[1], ":", 2)
+	if len(limitVals) > 2 {
+		return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
+	}
+
+	soft, err := strconv.ParseInt(limitVals[0], 10, 64)
+	if err != nil {
+		return nil, err
+	}
+
+	hard := soft // in case no hard was set
+	if len(limitVals) == 2 {
+		hard, err = strconv.ParseInt(limitVals[1], 10, 64)
+	}
+	if soft > hard {
+		return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, hard)
+	}
+
+	return &Ulimit{Name: parts[0], Soft: soft, Hard: hard}, nil
+}
+
+// GetRlimit returns the RLimit corresponding to Ulimit.
+func (u *Ulimit) GetRlimit() (*Rlimit, error) {
+	t, exists := ulimitNameMapping[u.Name]
+	if !exists {
+		return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
+	}
+
+	return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
+}
+
+func (u *Ulimit) String() string {
+	return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
+}
diff --git a/vendor/golang.org/x/net/proxy/direct.go b/vendor/golang.org/x/net/proxy/direct.go
new file mode 100644
index 00000000..4c5ad88b
--- /dev/null
+++ b/vendor/golang.org/x/net/proxy/direct.go
@@ -0,0 +1,18 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package proxy
+
+import (
+	"net"
+)
+
+type direct struct{}
+
+// Direct is a direct proxy: one that makes network connections directly.
+var Direct = direct{}
+
+func (direct) Dial(network, addr string) (net.Conn, error) {
+	return net.Dial(network, addr)
+}
diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go
new file mode 100644
index 00000000..f540b196
--- /dev/null
+++ b/vendor/golang.org/x/net/proxy/per_host.go
@@ -0,0 +1,140 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package proxy
+
+import (
+	"net"
+	"strings"
+)
+
+// A PerHost directs connections to a default Dialer unless the hostname
+// requested matches one of a number of exceptions.
+type PerHost struct {
+	def, bypass Dialer
+
+	bypassNetworks []*net.IPNet
+	bypassIPs      []net.IP
+	bypassZones    []string
+	bypassHosts    []string
+}
+
+// NewPerHost returns a PerHost Dialer that directs connections to either
+// defaultDialer or bypass, depending on whether the connection matches one of
+// the configured rules.
+func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
+	return &PerHost{
+		def:    defaultDialer,
+		bypass: bypass,
+	}
+}
+
+// Dial connects to the address addr on the given network through either
+// defaultDialer or bypass.
+func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	return p.dialerForRequest(host).Dial(network, addr)
+}
+
+func (p *PerHost) dialerForRequest(host string) Dialer {
+	if ip := net.ParseIP(host); ip != nil {
+		for _, net := range p.bypassNetworks {
+			if net.Contains(ip) {
+				return p.bypass
+			}
+		}
+		for _, bypassIP := range p.bypassIPs {
+			if bypassIP.Equal(ip) {
+				return p.bypass
+			}
+		}
+		return p.def
+	}
+
+	for _, zone := range p.bypassZones {
+		if strings.HasSuffix(host, zone) {
+			return p.bypass
+		}
+		if host == zone[1:] {
+			// For a zone "example.com", we match "example.com"
+			// too.
+			return p.bypass
+		}
+	}
+	for _, bypassHost := range p.bypassHosts {
+		if bypassHost == host {
+			return p.bypass
+		}
+	}
+	return p.def
+}
+
+// AddFromString parses a string that contains comma-separated values
+// specifying hosts that should use the bypass proxy. Each value is either an
+// IP address, a CIDR range, a zone (*.example.com) or a hostname
+// (localhost). A best effort is made to parse the string and errors are
+// ignored.
+func (p *PerHost) AddFromString(s string) {
+	hosts := strings.Split(s, ",")
+	for _, host := range hosts {
+		host = strings.TrimSpace(host)
+		if len(host) == 0 {
+			continue
+		}
+		if strings.Contains(host, "/") {
+			// We assume that it's a CIDR address like 127.0.0.0/8
+			if _, net, err := net.ParseCIDR(host); err == nil {
+				p.AddNetwork(net)
+			}
+			continue
+		}
+		if ip := net.ParseIP(host); ip != nil {
+			p.AddIP(ip)
+			continue
+		}
+		if strings.HasPrefix(host, "*.") {
+			p.AddZone(host[1:])
+			continue
+		}
+		p.AddHost(host)
+	}
+}
+
+// AddIP specifies an IP address that will use the bypass proxy. Note that
+// this will only take effect if a literal IP address is dialed. A connection
+// to a named host will never match an IP.
+func (p *PerHost) AddIP(ip net.IP) {
+	p.bypassIPs = append(p.bypassIPs, ip)
+}
+
+// AddNetwork specifies an IP range that will use the bypass proxy. Note that
+// this will only take effect if a literal IP address is dialed. A connection
+// to a named host will never match.
+func (p *PerHost) AddNetwork(net *net.IPNet) {
+	p.bypassNetworks = append(p.bypassNetworks, net)
+}
+
+// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
+// "example.com" matches "example.com" and all of its subdomains.
+func (p *PerHost) AddZone(zone string) {
+	if strings.HasSuffix(zone, ".") {
+		zone = zone[:len(zone)-1]
+	}
+	if !strings.HasPrefix(zone, ".") {
+		zone = "." + zone
+	}
+	p.bypassZones = append(p.bypassZones, zone)
+}
+
+// AddHost specifies a hostname that will use the bypass proxy.
+func (p *PerHost) AddHost(host string) {
+	if strings.HasSuffix(host, ".") {
+		host = host[:len(host)-1]
+	}
+	p.bypassHosts = append(p.bypassHosts, host)
+}
diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go
new file mode 100644
index 00000000..78a8b7be
--- /dev/null
+++ b/vendor/golang.org/x/net/proxy/proxy.go
@@ -0,0 +1,94 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package proxy provides support for a variety of protocols to proxy network
+// data.
+package proxy // import "golang.org/x/net/proxy"
+
+import (
+	"errors"
+	"net"
+	"net/url"
+	"os"
+)
+
+// A Dialer is a means to establish a connection.
+type Dialer interface {
+	// Dial connects to the given address via the proxy.
+	Dial(network, addr string) (c net.Conn, err error)
+}
+
+// Auth contains authentication parameters that specific Dialers may require.
+type Auth struct {
+	User, Password string
+}
+
+// FromEnvironment returns the dialer specified by the proxy related variables in
+// the environment.
+func FromEnvironment() Dialer {
+	allProxy := os.Getenv("all_proxy")
+	if len(allProxy) == 0 {
+		return Direct
+	}
+
+	proxyURL, err := url.Parse(allProxy)
+	if err != nil {
+		return Direct
+	}
+	proxy, err := FromURL(proxyURL, Direct)
+	if err != nil {
+		return Direct
+	}
+
+	noProxy := os.Getenv("no_proxy")
+	if len(noProxy) == 0 {
+		return proxy
+	}
+
+	perHost := NewPerHost(proxy, Direct)
+	perHost.AddFromString(noProxy)
+	return perHost
+}
+
+// proxySchemes is a map from URL schemes to a function that creates a Dialer
+// from a URL with such a scheme.
+var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
+
+// RegisterDialerType takes a URL scheme and a function to generate Dialers from
+// a URL with that scheme and a forwarding Dialer. Registered schemes are used
+// by FromURL.
+func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
+	if proxySchemes == nil {
+		proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
+	}
+	proxySchemes[scheme] = f
+}
+
+// FromURL returns a Dialer given a URL specification and an underlying
+// Dialer for it to make network requests.
+func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
+	var auth *Auth
+	if u.User != nil {
+		auth = new(Auth)
+		auth.User = u.User.Username()
+		if p, ok := u.User.Password(); ok {
+			auth.Password = p
+		}
+	}
+
+	switch u.Scheme {
+	case "socks5":
+		return SOCKS5("tcp", u.Host, auth, forward)
+	}
+
+	// If the scheme doesn't match any of the built-in schemes, see if it
+	// was registered by another package.
+	if proxySchemes != nil {
+		if f, ok := proxySchemes[u.Scheme]; ok {
+			return f(u, forward)
+		}
+	}
+
+	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
+}
diff --git a/vendor/golang.org/x/net/proxy/socks5.go b/vendor/golang.org/x/net/proxy/socks5.go
new file mode 100644
index 00000000..9b962823
--- /dev/null
+++ b/vendor/golang.org/x/net/proxy/socks5.go
@@ -0,0 +1,210 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package proxy
+
+import (
+	"errors"
+	"io"
+	"net"
+	"strconv"
+)
+
+// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
+// with an optional username and password. See RFC 1928.
+func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) {
+	s := &socks5{
+		network: network,
+		addr:    addr,
+		forward: forward,
+	}
+	if auth != nil {
+		s.user = auth.User
+		s.password = auth.Password
+	}
+
+	return s, nil
+}
+
+type socks5 struct {
+	user, password string
+	network, addr  string
+	forward        Dialer
+}
+
+const socks5Version = 5
+
+const (
+	socks5AuthNone     = 0
+	socks5AuthPassword = 2
+)
+
+const socks5Connect = 1
+
+const (
+	socks5IP4    = 1
+	socks5Domain = 3
+	socks5IP6    = 4
+)
+
+var socks5Errors = []string{
+	"",
+	"general failure",
+	"connection forbidden",
+	"network unreachable",
+	"host unreachable",
+	"connection refused",
+	"TTL expired",
+	"command not supported",
+	"address type not supported",
+}
+
+// Dial connects to the address addr on the network net via the SOCKS5 proxy.
+func (s *socks5) Dial(network, addr string) (net.Conn, error) {
+	switch network {
+	case "tcp", "tcp6", "tcp4":
+	default:
+		return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
+	}
+
+	conn, err := s.forward.Dial(s.network, s.addr)
+	if err != nil {
+		return nil, err
+	}
+	closeConn := &conn
+	defer func() {
+		if closeConn != nil {
+			(*closeConn).Close()
+		}
+	}()
+
+	host, portStr, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	port, err := strconv.Atoi(portStr)
+	if err != nil {
+		return nil, errors.New("proxy: failed to parse port number: " + portStr)
+	}
+	if port < 1 || port > 0xffff {
+		return nil, errors.New("proxy: port number out of range: " + portStr)
+	}
+
+	// the size here is just an estimate
+	buf := make([]byte, 0, 6+len(host))
+
+	buf = append(buf, socks5Version)
+	if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
+		buf = append(buf, 2 /* num auth methods */, socks5AuthNone, socks5AuthPassword)
+	} else {
+		buf = append(buf, 1 /* num auth methods */, socks5AuthNone)
+	}
+
+	if _, err := conn.Write(buf); err != nil {
+		return nil, errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
+		return nil, errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+	if buf[0] != 5 {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
+	}
+	if buf[1] == 0xff {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
+	}
+
+	if buf[1] == socks5AuthPassword {
+		buf = buf[:0]
+		buf = append(buf, 1 /* password protocol version */)
+		buf = append(buf, uint8(len(s.user)))
+		buf = append(buf, s.user...)
+		buf = append(buf, uint8(len(s.password)))
+		buf = append(buf, s.password...)
+
+		if _, err := conn.Write(buf); err != nil {
+			return nil, errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+
+		if _, err := io.ReadFull(conn, buf[:2]); err != nil {
+			return nil, errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+
+		if buf[1] != 0 {
+			return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
+		}
+	}
+
+	buf = buf[:0]
+	buf = append(buf, socks5Version, socks5Connect, 0 /* reserved */)
+
+	if ip := net.ParseIP(host); ip != nil {
+		if ip4 := ip.To4(); ip4 != nil {
+			buf = append(buf, socks5IP4)
+			ip = ip4
+		} else {
+			buf = append(buf, socks5IP6)
+		}
+		buf = append(buf, ip...)
+	} else {
+		if len(host) > 255 {
+			return nil, errors.New("proxy: destination hostname too long: " + host)
+		}
+		buf = append(buf, socks5Domain)
+		buf = append(buf, byte(len(host)))
+		buf = append(buf, host...)
+	}
+	buf = append(buf, byte(port>>8), byte(port))
+
+	if _, err := conn.Write(buf); err != nil {
+		return nil, errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	if _, err := io.ReadFull(conn, buf[:4]); err != nil {
+		return nil, errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	failure := "unknown error"
+	if int(buf[1]) < len(socks5Errors) {
+		failure = socks5Errors[buf[1]]
+	}
+
+	if len(failure) > 0 {
+		return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
+	}
+
+	bytesToDiscard := 0
+	switch buf[3] {
+	case socks5IP4:
+		bytesToDiscard = net.IPv4len
+	case socks5IP6:
+		bytesToDiscard = net.IPv6len
+	case socks5Domain:
+		_, err := io.ReadFull(conn, buf[:1])
+		if err != nil {
+			return nil, errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+		}
+		bytesToDiscard = int(buf[0])
+	default:
+		return nil, errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
+	}
+
+	if cap(buf) < bytesToDiscard {
+		buf = make([]byte, bytesToDiscard)
+	} else {
+		buf = buf[:bytesToDiscard]
+	}
+	if _, err := io.ReadFull(conn, buf); err != nil {
+		return nil, errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	// Also need to discard the port number
+	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
+		return nil, errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
+	}
+
+	closeConn = nil
+	return conn, nil
+}