mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Vendor engine-api, go-connections and go-winio.
Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
1ae6da75c8
commit
d8355ead9e
37 changed files with 642 additions and 163 deletions
|
@ -7,7 +7,7 @@ source 'hack/.vendor-helpers.sh'
|
|||
|
||||
# the following lines are in sorted order, FYI
|
||||
clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe
|
||||
clone git github.com/Microsoft/go-winio 2b085935f02c272e7a1855df6f8fe03029ffcadd
|
||||
clone git github.com/Microsoft/go-winio eb176a9831c54b88eaf9eb4fbc24b94080d910ad
|
||||
clone git github.com/Sirupsen/logrus v0.9.0 # logrus is a common dependency among multiple deps
|
||||
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1
|
||||
|
@ -23,8 +23,8 @@ clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
|
|||
clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://github.com/golang/net.git
|
||||
clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git
|
||||
clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
|
||||
clone git github.com/docker/go-connections v0.1.2
|
||||
clone git github.com/docker/engine-api bdbab71ec21209ef56dffdbe42c9d21843c30862
|
||||
clone git github.com/docker/go-connections v0.1.3
|
||||
clone git github.com/docker/engine-api 9a940e4ead265e18d4feb9e3c515428966a08278
|
||||
clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
|
||||
clone git github.com/imdario/mergo 0.2.1
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ func LookupSidByName(name string) (sid string, err error) {
|
|||
if err != nil {
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
sid = syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(strBuffer))[:])
|
||||
sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
|
||||
localFree(uintptr(unsafe.Pointer(strBuffer)))
|
||||
return sid, nil
|
||||
}
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/engine-api/client/transport"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
)
|
||||
|
||||
|
@ -21,17 +19,13 @@ type Client struct {
|
|||
proto string
|
||||
// addr holds the client address.
|
||||
addr string
|
||||
// basePath holds the path to prepend to the requests
|
||||
// basePath holds the path to prepend to the requests.
|
||||
basePath string
|
||||
// scheme holds the scheme of the client i.e. https.
|
||||
scheme string
|
||||
// tlsConfig holds the tls configuration to use in hijacked requests.
|
||||
tlsConfig *tls.Config
|
||||
// httpClient holds the client transport instance. Exported to keep the old code running.
|
||||
httpClient *http.Client
|
||||
// transport is the interface to sends request with, it implements transport.Client.
|
||||
transport transport.Client
|
||||
// version of the server to talk to.
|
||||
version string
|
||||
// custom http headers configured by users
|
||||
// custom http headers configured by users.
|
||||
customHTTPHeaders map[string]string
|
||||
}
|
||||
|
||||
|
@ -41,7 +35,7 @@ type Client struct {
|
|||
// 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 transport *http.Transport
|
||||
var client *http.Client
|
||||
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
|
||||
options := tlsconfig.Options{
|
||||
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
|
||||
|
@ -54,8 +48,10 @@ func NewEnvClient() (*Client, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
transport = &http.Transport{
|
||||
TLSClientConfig: tlsc,
|
||||
client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsc,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,42 +59,29 @@ func NewEnvClient() (*Client, error) {
|
|||
if host == "" {
|
||||
host = DefaultDockerHost
|
||||
}
|
||||
return NewClient(host, os.Getenv("DOCKER_API_VERSION"), transport, nil)
|
||||
return NewClient(host, os.Getenv("DOCKER_API_VERSION"), client, nil)
|
||||
}
|
||||
|
||||
// NewClient initializes a new API client for the given host and API version.
|
||||
// It won't send any version information if the version number is empty.
|
||||
// It uses the transport to create a new http client.
|
||||
// It uses the given http client as transport.
|
||||
// It also initializes the custom http headers to add to each request.
|
||||
func NewClient(host string, version string, transport *http.Transport, httpHeaders map[string]string) (*Client, error) {
|
||||
var (
|
||||
basePath string
|
||||
scheme = "http"
|
||||
protoAddrParts = strings.SplitN(host, "://", 2)
|
||||
proto, addr = protoAddrParts[0], protoAddrParts[1]
|
||||
)
|
||||
|
||||
if proto == "tcp" {
|
||||
parsed, err := url.Parse("tcp://" + addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr = parsed.Host
|
||||
basePath = parsed.Path
|
||||
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 = configureTransport(transport, proto, addr)
|
||||
if transport.TLSClientConfig != nil {
|
||||
scheme = "https"
|
||||
transport, err := transport.NewTransportWithHTTP(proto, addr, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
proto: proto,
|
||||
addr: addr,
|
||||
basePath: basePath,
|
||||
scheme: scheme,
|
||||
tlsConfig: transport.TLSClientConfig,
|
||||
httpClient: &http.Client{Transport: transport},
|
||||
transport: transport,
|
||||
version: version,
|
||||
customHTTPHeaders: httpHeaders,
|
||||
}, nil
|
||||
|
@ -127,23 +110,22 @@ func (cli *Client) ClientVersion() string {
|
|||
return cli.version
|
||||
}
|
||||
|
||||
func configureTransport(tr *http.Transport, proto, addr string) *http.Transport {
|
||||
if tr == nil {
|
||||
tr = &http.Transport{}
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Why 32? See https://github.com/docker/docker/pull/8035.
|
||||
timeout := 32 * time.Second
|
||||
if proto == "unix" {
|
||||
// No need for compression in local communications.
|
||||
tr.DisableCompression = true
|
||||
tr.Dial = func(_, _ string) (net.Conn, error) {
|
||||
return net.DialTimeout(proto, addr, timeout)
|
||||
var basePath string
|
||||
proto, addr := protoAddrParts[0], protoAddrParts[1]
|
||||
if proto == "tcp" {
|
||||
parsed, err := url.Parse("tcp://" + addr)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
} else {
|
||||
tr.Proxy = http.ProxyFromEnvironment
|
||||
tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
|
||||
addr = parsed.Host
|
||||
basePath = parsed.Path
|
||||
}
|
||||
|
||||
return tr
|
||||
return proto, addr, basePath, nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +build linux freebsd
|
||||
// +build linux freebsd solaris
|
||||
|
||||
package client
|
||||
|
||||
|
|
|
@ -3,18 +3,20 @@ 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(containerID string, stream bool) (io.ReadCloser, error) {
|
||||
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("/containers/"+containerID+"/stats", query, nil)
|
||||
resp, err := cli.getWithContext(ctx, "/containers/"+containerID+"/stats", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
|
@ -28,7 +30,7 @@ func (cli *Client) ContainerStatPath(containerID, path string) (types.ContainerP
|
|||
}
|
||||
|
||||
// CopyToContainer copies content into the container filesystem.
|
||||
func (cli *Client) CopyToContainer(options types.CopyToContainerOptions) error {
|
||||
func (cli *Client) CopyToContainer(ctx context.Context, options types.CopyToContainerOptions) error {
|
||||
query := url.Values{}
|
||||
query.Set("path", filepath.ToSlash(options.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.
|
||||
|
@ -38,7 +40,7 @@ func (cli *Client) CopyToContainer(options types.CopyToContainerOptions) error {
|
|||
|
||||
path := fmt.Sprintf("/containers/%s/archive", options.ContainerID)
|
||||
|
||||
response, err := cli.putRaw(path, query, options.Content, nil)
|
||||
response, err := cli.putRawWithContext(ctx, path, query, options.Content, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -53,12 +55,12 @@ func (cli *Client) CopyToContainer(options types.CopyToContainerOptions) error {
|
|||
|
||||
// CopyFromContainer get the content from the container and return it as a Reader
|
||||
// to manipulate it in the host. It's up to the caller to close the reader.
|
||||
func (cli *Client) CopyFromContainer(containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
|
||||
func (cli *Client) CopyFromContainer(ctx context.Context, containerID, 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", containerID)
|
||||
response, err := cli.get(apiPath, query, nil)
|
||||
response, err := cli.getWithContext(ctx, apiPath, query, nil)
|
||||
if err != nil {
|
||||
return nil, types.ContainerPathStat{}, err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"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"
|
||||
|
@ -12,7 +14,7 @@ import (
|
|||
|
||||
// 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(options types.EventsOptions) (io.ReadCloser, error) {
|
||||
func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
ref := time.Now()
|
||||
|
||||
|
@ -38,7 +40,7 @@ func (cli *Client) Events(options types.EventsOptions) (io.ReadCloser, error) {
|
|||
query.Set("filters", filterJSON)
|
||||
}
|
||||
|
||||
serverResponse, err := cli.get("/events", query, nil)
|
||||
serverResponse, err := cli.getWithContext(ctx, "/events", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,13 +3,15 @@ package client
|
|||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ContainerExport retrieves the raw contents of a container
|
||||
// and returns them as a io.ReadCloser. It's up to the caller
|
||||
// to close the stream.
|
||||
func (cli *Client) ContainerExport(containerID string) (io.ReadCloser, error) {
|
||||
serverResp, err := cli.get("/containers/"+containerID+"/export", url.Values{}, nil)
|
||||
func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) {
|
||||
serverResp, err := cli.getWithContext(ctx, "/containers/"+containerID+"/export", url.Values{}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
)
|
||||
|
||||
// tlsClientCon holds tls information and a dialed connection.
|
||||
|
@ -44,7 +45,7 @@ func (cli *Client) postHijacked(path string, query url.Values, body interface{},
|
|||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Header.Set("Upgrade", "tcp")
|
||||
|
||||
conn, err := dial(cli.proto, cli.addr, cli.tlsConfig)
|
||||
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?")
|
||||
|
@ -156,9 +157,12 @@ func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Con
|
|||
}
|
||||
|
||||
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
|
||||
if tlsConfig != nil && proto != "unix" {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
)
|
||||
|
@ -18,7 +20,7 @@ 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(options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
||||
func (cli *Client) ImageBuild(ctx context.Context, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
||||
query, err := imageBuildOptionsToQuery(options)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
|
@ -32,7 +34,7 @@ func (cli *Client) ImageBuild(options types.ImageBuildOptions) (types.ImageBuild
|
|||
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
||||
headers.Set("Content-Type", "application/tar")
|
||||
|
||||
serverResp, err := cli.postRaw("/build", query, options.Context, headers)
|
||||
serverResp, err := cli.postRaw(ctx, "/build", query, options.Context, headers)
|
||||
if err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
|
|
|
@ -4,23 +4,25 @@ import (
|
|||
"io"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
// ImageCreate creates a new image based in the parent options.
|
||||
// It returns the JSON content in the response body.
|
||||
func (cli *Client) ImageCreate(options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
func (cli *Client) ImageCreate(ctx context.Context, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("fromImage", options.Parent)
|
||||
query.Set("tag", options.Tag)
|
||||
resp, err := cli.tryImageCreate(query, options.RegistryAuth)
|
||||
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tryImageCreate(query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
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("/images/create", query, nil, headers)
|
||||
return cli.postWithContext(ctx, "/images/create", query, nil, headers)
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ import (
|
|||
"io"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"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(options types.ImageImportOptions) (io.ReadCloser, error) {
|
||||
func (cli *Client) ImageImport(ctx context.Context, options types.ImageImportOptions) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("fromSrc", options.SourceName)
|
||||
query.Set("repo", options.RepositoryName)
|
||||
|
@ -19,7 +21,7 @@ func (cli *Client) ImageImport(options types.ImageImportOptions) (io.ReadCloser,
|
|||
query.Add("changes", change)
|
||||
}
|
||||
|
||||
resp, err := cli.postRaw("/images/create", query, options.Source, nil)
|
||||
resp, err := cli.postRaw(ctx, "/images/create", query, options.Source, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -4,14 +4,21 @@ 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 returned by
|
||||
// this function.
|
||||
func (cli *Client) ImageLoad(input io.Reader) (types.ImageLoadResponse, error) {
|
||||
resp, err := cli.postRaw("/images/load", url.Values{}, input, nil)
|
||||
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")
|
||||
}
|
||||
resp, err := cli.postRaw(ctx, "/images/load", v, input, nil)
|
||||
if err != nil {
|
||||
return types.ImageLoadResponse{}, err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
|
@ -12,20 +14,20 @@ import (
|
|||
// 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) ImagePull(options types.ImagePullOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
||||
func (cli *Client) ImagePull(ctx context.Context, options types.ImagePullOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("fromImage", options.ImageID)
|
||||
if options.Tag != "" {
|
||||
query.Set("tag", options.Tag)
|
||||
}
|
||||
|
||||
resp, err := cli.tryImageCreate(query, options.RegistryAuth)
|
||||
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized {
|
||||
newAuthHeader, privilegeErr := privilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImageCreate(query, newAuthHeader)
|
||||
resp, err = cli.tryImageCreate(ctx, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
|
@ -12,17 +14,17 @@ import (
|
|||
// 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(options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
||||
func (cli *Client) ImagePush(ctx context.Context, options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
query.Set("tag", options.Tag)
|
||||
|
||||
resp, err := cli.tryImagePush(options.ImageID, query, options.RegistryAuth)
|
||||
resp, err := cli.tryImagePush(ctx, options.ImageID, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized {
|
||||
newAuthHeader, privilegeErr := privilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
}
|
||||
resp, err = cli.tryImagePush(options.ImageID, query, newAuthHeader)
|
||||
resp, err = cli.tryImagePush(ctx, options.ImageID, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -30,7 +32,7 @@ func (cli *Client) ImagePush(options types.ImagePushOptions, privilegeFunc Reque
|
|||
return resp.body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tryImagePush(imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
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("/images/"+imageID+"/push", query, nil, headers)
|
||||
return cli.postWithContext(ctx, "/images/"+imageID+"/push", query, nil, headers)
|
||||
}
|
||||
|
|
|
@ -3,16 +3,18 @@ package client
|
|||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ImageSave retrieves one or more images from the docker host as a io.ReadCloser.
|
||||
// It's up to the caller to store the images and close the stream.
|
||||
func (cli *Client) ImageSave(imageIDs []string) (io.ReadCloser, error) {
|
||||
func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) {
|
||||
query := url.Values{
|
||||
"names": imageIDs,
|
||||
}
|
||||
|
||||
resp, err := cli.get("/images/get", query, nil)
|
||||
resp, err := cli.getWithContext(ctx, "/images/get", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package client
|
|||
import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
"github.com/docker/engine-api/types/filters"
|
||||
|
@ -22,40 +24,40 @@ type APIClient interface {
|
|||
ContainerExecInspect(execID string) (types.ContainerExecInspect, error)
|
||||
ContainerExecResize(options types.ResizeOptions) error
|
||||
ContainerExecStart(execID string, config types.ExecStartCheck) error
|
||||
ContainerExport(containerID string) (io.ReadCloser, error)
|
||||
ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error)
|
||||
ContainerInspect(containerID string) (types.ContainerJSON, error)
|
||||
ContainerInspectWithRaw(containerID string, getSize bool) (types.ContainerJSON, []byte, error)
|
||||
ContainerKill(containerID, signal string) error
|
||||
ContainerList(options types.ContainerListOptions) ([]types.Container, error)
|
||||
ContainerLogs(options types.ContainerLogsOptions) (io.ReadCloser, error)
|
||||
ContainerLogs(ctx context.Context, options types.ContainerLogsOptions) (io.ReadCloser, error)
|
||||
ContainerPause(containerID string) error
|
||||
ContainerRemove(options types.ContainerRemoveOptions) error
|
||||
ContainerRename(containerID, newContainerName string) error
|
||||
ContainerResize(options types.ResizeOptions) error
|
||||
ContainerRestart(containerID string, timeout int) error
|
||||
ContainerStatPath(containerID, path string) (types.ContainerPathStat, error)
|
||||
ContainerStats(containerID string, stream bool) (io.ReadCloser, error)
|
||||
ContainerStats(ctx context.Context, containerID string, stream bool) (io.ReadCloser, error)
|
||||
ContainerStart(containerID string) error
|
||||
ContainerStop(containerID string, timeout int) error
|
||||
ContainerTop(containerID string, arguments []string) (types.ContainerProcessList, error)
|
||||
ContainerUnpause(containerID string) error
|
||||
ContainerUpdate(containerID string, updateConfig container.UpdateConfig) error
|
||||
ContainerWait(containerID string) (int, error)
|
||||
CopyFromContainer(containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
|
||||
CopyToContainer(options types.CopyToContainerOptions) error
|
||||
Events(options types.EventsOptions) (io.ReadCloser, error)
|
||||
ImageBuild(options types.ImageBuildOptions) (types.ImageBuildResponse, error)
|
||||
ImageCreate(options types.ImageCreateOptions) (io.ReadCloser, error)
|
||||
ContainerWait(ctx context.Context, containerID string) (int, error)
|
||||
CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
|
||||
CopyToContainer(ctx context.Context, options types.CopyToContainerOptions) error
|
||||
Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error)
|
||||
ImageBuild(ctx context.Context, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
|
||||
ImageCreate(ctx context.Context, options types.ImageCreateOptions) (io.ReadCloser, error)
|
||||
ImageHistory(imageID string) ([]types.ImageHistory, error)
|
||||
ImageImport(options types.ImageImportOptions) (io.ReadCloser, error)
|
||||
ImageImport(ctx context.Context, options types.ImageImportOptions) (io.ReadCloser, error)
|
||||
ImageInspectWithRaw(imageID string, getSize bool) (types.ImageInspect, []byte, error)
|
||||
ImageList(options types.ImageListOptions) ([]types.Image, error)
|
||||
ImageLoad(input io.Reader) (types.ImageLoadResponse, error)
|
||||
ImagePull(options types.ImagePullOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error)
|
||||
ImagePush(options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error)
|
||||
ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
|
||||
ImagePull(ctx context.Context, options types.ImagePullOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error)
|
||||
ImagePush(ctx context.Context, options types.ImagePushOptions, privilegeFunc RequestPrivilegeFunc) (io.ReadCloser, error)
|
||||
ImageRemove(options types.ImageRemoveOptions) ([]types.ImageDelete, error)
|
||||
ImageSearch(options types.ImageSearchOptions, privilegeFunc RequestPrivilegeFunc) ([]registry.SearchResult, error)
|
||||
ImageSave(imageIDs []string) (io.ReadCloser, error)
|
||||
ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error)
|
||||
ImageTag(options types.ImageTagOptions) error
|
||||
Info() (types.Info, error)
|
||||
NetworkConnect(networkID, containerID string, config *network.EndpointSettings) error
|
||||
|
|
|
@ -5,13 +5,15 @@ import (
|
|||
"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(options types.ContainerLogsOptions) (io.ReadCloser, error) {
|
||||
func (cli *Client) ContainerLogs(ctx context.Context, options types.ContainerLogsOptions) (io.ReadCloser, error) {
|
||||
query := url.Values{}
|
||||
if options.ShowStdout {
|
||||
query.Set("stdout", "1")
|
||||
|
@ -38,7 +40,7 @@ func (cli *Client) ContainerLogs(options types.ContainerLogsOptions) (io.ReadClo
|
|||
}
|
||||
query.Set("tail", options.Tail)
|
||||
|
||||
resp, err := cli.get("/containers/"+options.ContainerID+"/logs", query, nil)
|
||||
resp, err := cli.getWithContext(ctx, "/containers/"+options.ContainerID+"/logs", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/engine-api/client/transport/cancellable"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// serverResponse is a wrapper for http API responses.
|
||||
|
@ -20,40 +24,55 @@ type serverResponse struct {
|
|||
|
||||
// head sends an http request to the docker API using the method HEAD.
|
||||
func (cli *Client) head(path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest("HEAD", path, query, nil, headers)
|
||||
return cli.sendRequest(context.Background(), "HEAD", path, query, nil, headers)
|
||||
}
|
||||
|
||||
// get sends an http request to the docker API using the method GET.
|
||||
func (cli *Client) get(path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest("GET", path, query, nil, headers)
|
||||
return cli.getWithContext(context.Background(), path, query, headers)
|
||||
}
|
||||
|
||||
// getWithContext sends an http request to the docker API using the method GET with a specific go context.
|
||||
func (cli *Client) getWithContext(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest(ctx, "GET", path, query, nil, headers)
|
||||
}
|
||||
|
||||
// post sends an http request to the docker API using the method POST.
|
||||
func (cli *Client) post(path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest("POST", path, query, body, headers)
|
||||
return cli.postWithContext(context.Background(), path, query, body, headers)
|
||||
}
|
||||
|
||||
// postRaw sends the raw input to the docker API using the method POST.
|
||||
func (cli *Client) postRaw(path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendClientRequest("POST", path, query, body, headers)
|
||||
// postWithContext sends an http request to the docker API using the method POST with a specific go context.
|
||||
func (cli *Client) postWithContext(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest(ctx, "POST", path, query, body, headers)
|
||||
}
|
||||
|
||||
// postRaw sends the raw input to the docker API using the method POST with a specific go context.
|
||||
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(path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest("PUT", path, query, body, headers)
|
||||
return cli.sendRequest(context.Background(), "PUT", path, query, body, headers)
|
||||
}
|
||||
|
||||
// putRaw sends the raw input to the docker API using the method PUT.
|
||||
func (cli *Client) putRaw(path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendClientRequest("PUT", path, query, body, headers)
|
||||
return cli.putRawWithContext(context.Background(), path, query, body, headers)
|
||||
}
|
||||
|
||||
// putRawWithContext sends the raw input to the docker API using the method PUT with a specific go context.
|
||||
func (cli *Client) putRawWithContext(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(path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
||||
return cli.sendRequest("DELETE", path, query, nil, headers)
|
||||
return cli.sendRequest(context.Background(), "DELETE", path, query, nil, headers)
|
||||
}
|
||||
|
||||
func (cli *Client) sendRequest(method, path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
||||
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
||||
params, err := encodeData(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -66,10 +85,10 @@ func (cli *Client) sendRequest(method, path string, query url.Values, body inter
|
|||
headers["Content-Type"] = []string{"application/json"}
|
||||
}
|
||||
|
||||
return cli.sendClientRequest(method, path, query, params, headers)
|
||||
return cli.sendClientRequest(ctx, method, path, query, params, headers)
|
||||
}
|
||||
|
||||
func (cli *Client) sendClientRequest(method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
||||
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,
|
||||
|
@ -82,13 +101,13 @@ func (cli *Client) sendClientRequest(method, path string, query url.Values, body
|
|||
|
||||
req, err := cli.newRequest(method, path, query, body, headers)
|
||||
req.URL.Host = cli.addr
|
||||
req.URL.Scheme = cli.scheme
|
||||
req.URL.Scheme = cli.transport.Scheme()
|
||||
|
||||
if expectedPayload && req.Header.Get("Content-Type") == "" {
|
||||
req.Header.Set("Content-Type", "text/plain")
|
||||
}
|
||||
|
||||
resp, err := cli.httpClient.Do(req)
|
||||
resp, err := cancellable.Do(ctx, cli.transport, req)
|
||||
if resp != nil {
|
||||
serverResp.statusCode = resp.StatusCode
|
||||
}
|
||||
|
@ -98,10 +117,10 @@ func (cli *Client) sendClientRequest(method, path string, query url.Values, body
|
|||
return serverResp, ErrConnectionFailed
|
||||
}
|
||||
|
||||
if cli.scheme == "http" && strings.Contains(err.Error(), "malformed HTTP response") {
|
||||
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.scheme == "https" && strings.Contains(err.Error(), "remote error: bad certificate") {
|
||||
if cli.transport.Secure() && strings.Contains(err.Error(), "remote error: bad certificate") {
|
||||
return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
|
||||
}
|
||||
|
||||
|
|
23
vendor/src/github.com/docker/engine-api/client/transport/cancellable/canceler.go
vendored
Normal file
23
vendor/src/github.com/docker/engine-api/client/transport/cancellable/canceler.go
vendored
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
27
vendor/src/github.com/docker/engine-api/client/transport/cancellable/canceler_go14.go
vendored
Normal file
27
vendor/src/github.com/docker/engine-api/client/transport/cancellable/canceler_go14.go
vendored
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
113
vendor/src/github.com/docker/engine-api/client/transport/cancellable/cancellable.go
vendored
Normal file
113
vendor/src/github.com/docker/engine-api/client/transport/cancellable/cancellable.go
vendored
Normal file
|
@ -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 funcion 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 = ¬ifyingReader{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
|
||||
}
|
47
vendor/src/github.com/docker/engine-api/client/transport/client.go
vendored
Normal file
47
vendor/src/github.com/docker/engine-api/client/transport/client.go
vendored
Normal file
|
@ -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
|
||||
}
|
26
vendor/src/github.com/docker/engine-api/client/transport/client_mock.go
vendored
Normal file
26
vendor/src/github.com/docker/engine-api/client/transport/client_mock.go
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
// +build test
|
||||
|
||||
package transport
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type mockClient struct {
|
||||
*tlsInfo
|
||||
do func(*http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// NewMockClient returns a mocked client that runs the function supplied as `client.Do` call
|
||||
func NewMockClient(tlsConfig *tls.Config, doer func(*http.Request) (*http.Response, error)) Client {
|
||||
return mockClient{
|
||||
tlsInfo: &tlsInfo{tlsConfig},
|
||||
do: doer,
|
||||
}
|
||||
}
|
||||
|
||||
// Do executes the supplied function for the mock.
|
||||
func (m mockClient) Do(req *http.Request) (*http.Response, error) {
|
||||
return m.do(req)
|
||||
}
|
57
vendor/src/github.com/docker/engine-api/client/transport/transport.go
vendored
Normal file
57
vendor/src/github.com/docker/engine-api/client/transport/transport.go
vendored
Normal file
|
@ -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{}
|
|
@ -3,13 +3,15 @@ package client
|
|||
import (
|
||||
"encoding/json"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
)
|
||||
|
||||
// ContainerWait pauses execution util a container is exits.
|
||||
// It returns the API status code as response of its readiness.
|
||||
func (cli *Client) ContainerWait(containerID string) (int, error) {
|
||||
resp, err := cli.post("/containers/"+containerID+"/wait", nil, nil, nil)
|
||||
func (cli *Client) ContainerWait(ctx context.Context, containerID string) (int, error) {
|
||||
resp, err := cli.postWithContext(ctx, "/containers/"+containerID+"/wait", nil, nil, nil)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
|
|
@ -72,12 +72,6 @@ func (n NetworkMode) IsUserDefined() bool {
|
|||
return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
|
||||
}
|
||||
|
||||
// IsPreDefinedNetwork indicates if a network is predefined by the daemon
|
||||
func IsPreDefinedNetwork(network string) bool {
|
||||
n := NetworkMode(network)
|
||||
return n.IsBridge() || n.IsHost() || n.IsNone()
|
||||
}
|
||||
|
||||
//UserDefined indicates user-created network
|
||||
func (n NetworkMode) UserDefined() string {
|
||||
if n.IsUserDefined() {
|
||||
|
|
|
@ -49,11 +49,6 @@ func (n NetworkMode) NetworkName() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// IsPreDefinedNetwork indicates if a network is predefined by the daemon
|
||||
func IsPreDefinedNetwork(network string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidateNetMode ensures that the various combinations of requested
|
||||
// network settings are valid.
|
||||
func ValidateNetMode(c *Config, hc *HostConfig) error {
|
||||
|
|
|
@ -387,6 +387,7 @@ type NetworkResource struct {
|
|||
ID string `json:"Id"`
|
||||
Scope string
|
||||
Driver string
|
||||
EnableIPv6 bool
|
||||
IPAM network.IPAM
|
||||
Internal bool
|
||||
Containers map[string]EndpointResource
|
||||
|
@ -407,6 +408,7 @@ type NetworkCreate struct {
|
|||
Name string
|
||||
CheckDuplicate bool
|
||||
Driver string
|
||||
EnableIPv6 bool
|
||||
IPAM network.IPAM
|
||||
Internal bool
|
||||
Options map[string]string
|
||||
|
|
89
vendor/src/github.com/docker/go-connections/sockets/inmem_socket.go
vendored
Normal file
89
vendor/src/github.com/docker/go-connections/sockets/inmem_socket.go
vendored
Normal file
|
@ -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 }
|
35
vendor/src/github.com/docker/go-connections/sockets/sockets.go
vendored
Normal file
35
vendor/src/github.com/docker/go-connections/sockets/sockets.go
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// 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 defaulTimeout = 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) the compression
|
||||
// is disabled.
|
||||
func ConfigureTransport(tr *http.Transport, proto, addr string) {
|
||||
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, defaulTimeout)
|
||||
}
|
||||
case "npipe":
|
||||
// No need for compression in local communications.
|
||||
tr.DisableCompression = true
|
||||
tr.Dial = func(_, _ string) (net.Conn, error) {
|
||||
return DialPipe(addr, defaulTimeout)
|
||||
}
|
||||
default:
|
||||
tr.Proxy = http.ProxyFromEnvironment
|
||||
tr.Dial = (&net.Dialer{Timeout: defaulTimeout}).Dial
|
||||
}
|
||||
}
|
15
vendor/src/github.com/docker/go-connections/sockets/sockets_unix.go
vendored
Normal file
15
vendor/src/github.com/docker/go-connections/sockets/sockets_unix.go
vendored
Normal file
|
@ -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
|
||||
}
|
13
vendor/src/github.com/docker/go-connections/sockets/sockets_windows.go
vendored
Normal file
13
vendor/src/github.com/docker/go-connections/sockets/sockets_windows.go
vendored
Normal file
|
@ -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)
|
||||
}
|
|
@ -4,8 +4,6 @@ package sockets
|
|||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewTCPSocket creates a TCP socket listener with the specified address and
|
||||
|
@ -22,22 +20,3 @@ func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) {
|
|||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// ConfigureTCPTransport configures the specified Transport according to the
|
||||
// specified proto and addr.
|
||||
// If the proto is unix (using a unix socket to communicate) the compression
|
||||
// is disabled.
|
||||
func ConfigureTCPTransport(tr *http.Transport, proto, addr string) {
|
||||
// Why 32? See https://github.com/docker/docker/pull/8035.
|
||||
timeout := 32 * time.Second
|
||||
if proto == "unix" {
|
||||
// No need for compression in local communications.
|
||||
tr.DisableCompression = true
|
||||
tr.Dial = func(_, _ string) (net.Conn, error) {
|
||||
return net.DialTimeout(proto, addr, timeout)
|
||||
}
|
||||
} else {
|
||||
tr.Proxy = http.ProxyFromEnvironment
|
||||
tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,12 +41,6 @@ var acceptedCBCCiphers = []uint16{
|
|||
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -91,7 +85,7 @@ func certPool(caFile string) (*x509.CertPool, error) {
|
|||
func Client(options Options) (*tls.Config, error) {
|
||||
tlsConfig := ClientDefault
|
||||
tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
|
||||
if !options.InsecureSkipVerify {
|
||||
if !options.InsecureSkipVerify && options.CAFile != "" {
|
||||
CAs, err := certPool(options.CAFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -99,7 +93,7 @@ func Client(options Options) (*tls.Config, error) {
|
|||
tlsConfig.RootCAs = CAs
|
||||
}
|
||||
|
||||
if options.CertFile != "" && options.KeyFile != "" {
|
||||
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)
|
||||
|
|
17
vendor/src/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
vendored
Normal file
17
vendor/src/github.com/docker/go-connections/tlsconfig/config_client_ciphers.go
vendored
Normal file
|
@ -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,
|
||||
}
|
15
vendor/src/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go
vendored
Normal file
15
vendor/src/github.com/docker/go-connections/tlsconfig/config_legacy_client_ciphers.go
vendored
Normal file
|
@ -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,
|
||||
}
|
Loading…
Reference in a new issue