From e6fc1996f4e195a5879a0b7bdefb2f210862322d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 19 Feb 2018 18:31:29 +0900 Subject: [PATCH] support SSH connection e.g. docker -H ssh://me@server Signed-off-by: Akihiro Suda --- cli/command/cli.go | 43 ++++-- cli/command/out.go | 8 + cli/command/system/cmd.go | 1 + cli/command/system/dial_stdio.go | 100 ++++++++++++ cli/connhelper/connhelper.go | 144 ++++++++++++++++++ cli/connhelper/connhelper_linux.go | 12 ++ cli/connhelper/connhelper_nolinux.go | 10 ++ cli/connhelper/ssh.go | 77 ++++++++++ cli/flags/common.go | 3 +- docs/reference/commandline/dockerd.md | 13 ++ vendor.conf | 3 +- .../docker/api/types/volume/volume_create.go | 2 +- .../docker/api/types/volume/volume_list.go | 2 +- .../docker/docker/client/build_cancel.go | 3 +- .../github.com/docker/docker/client/client.go | 48 +++++- .../github.com/docker/docker/client/hijack.go | 11 +- .../docker/docker/client/interface.go | 1 + .../docker/docker/client/session.go | 2 +- vendor/github.com/docker/docker/vendor.conf | 24 +-- 19 files changed, 471 insertions(+), 36 deletions(-) create mode 100644 cli/command/system/dial_stdio.go create mode 100644 cli/connhelper/connhelper.go create mode 100644 cli/connhelper/connhelper_linux.go create mode 100644 cli/connhelper/connhelper_nolinux.go create mode 100644 cli/connhelper/ssh.go diff --git a/cli/command/cli.go b/cli/command/cli.go index b17aaf238f83..1e12a1ace89f 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -14,6 +14,7 @@ import ( "github.com/docker/cli/cli/config" cliconfig "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config/configfile" + "github.com/docker/cli/cli/connhelper" cliflags "github.com/docker/cli/cli/flags" manifeststore "github.com/docker/cli/cli/manifest/store" registryclient "github.com/docker/cli/cli/registry/client" @@ -248,31 +249,54 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, isTrusted bool) *DockerC // NewAPIClientFromFlags creates a new APIClient from command line flags func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.ConfigFile) (client.APIClient, error) { - host, err := getServerHost(opts.Hosts, opts.TLSOptions) + unparsedHost, err := getUnparsedServerHost(opts.Hosts) if err != nil { return &client.Client{}, err } + var clientOpts []func(*client.Client) error + helper, err := connhelper.GetConnectionHelper(unparsedHost) + if err != nil { + return &client.Client{}, err + } + if helper == nil { + clientOpts = append(clientOpts, withHTTPClient(opts.TLSOptions)) + host, err := dopts.ParseHost(opts.TLSOptions != nil, unparsedHost) + if err != nil { + return &client.Client{}, err + } + clientOpts = append(clientOpts, client.WithHost(host)) + } else { + clientOpts = append(clientOpts, func(c *client.Client) error { + httpClient := &http.Client{ + // No tls + // No proxy + Transport: &http.Transport{ + DialContext: helper.Dialer, + }, + } + return client.WithHTTPClient(httpClient)(c) + }) + clientOpts = append(clientOpts, client.WithHost(helper.Host)) + clientOpts = append(clientOpts, client.WithDialContext(helper.Dialer)) + } customHeaders := configFile.HTTPHeaders if customHeaders == nil { customHeaders = map[string]string{} } customHeaders["User-Agent"] = UserAgent() + clientOpts = append(clientOpts, client.WithHTTPHeaders(customHeaders)) verStr := api.DefaultVersion if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" { verStr = tmpStr } + clientOpts = append(clientOpts, client.WithVersion(verStr)) - return client.NewClientWithOpts( - withHTTPClient(opts.TLSOptions), - client.WithHTTPHeaders(customHeaders), - client.WithVersion(verStr), - client.WithHost(host), - ) + return client.NewClientWithOpts(clientOpts...) } -func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error) { +func getUnparsedServerHost(hosts []string) (string, error) { var host string switch len(hosts) { case 0: @@ -282,8 +306,7 @@ func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error default: return "", errors.New("Please specify only one -H") } - - return dopts.ParseHost(tlsOptions != nil, host) + return host, nil } func withHTTPClient(tlsOpts *tlsconfig.Options) func(*client.Client) error { diff --git a/cli/command/out.go b/cli/command/out.go index 89cc5d3aa12c..4aaff09c8244 100644 --- a/cli/command/out.go +++ b/cli/command/out.go @@ -19,6 +19,14 @@ func (o *OutStream) Write(p []byte) (int, error) { return o.out.Write(p) } +// Close calls o.out.Close() if available. +func (o *OutStream) Close() error { + if wc, ok := o.out.(io.Closer); ok { + return wc.Close() + } + return nil +} + // SetRawTerminal sets raw mode on the input terminal func (o *OutStream) SetRawTerminal() (err error) { if os.Getenv("NORAW") != "" || !o.CommonStream.isTerminal { diff --git a/cli/command/system/cmd.go b/cli/command/system/cmd.go index 7b9d6819c3b0..6accb98f0c4e 100644 --- a/cli/command/system/cmd.go +++ b/cli/command/system/cmd.go @@ -19,6 +19,7 @@ func NewSystemCommand(dockerCli command.Cli) *cobra.Command { NewInfoCommand(dockerCli), newDiskUsageCommand(dockerCli), newPruneCommand(dockerCli), + newDialStdioCommand(dockerCli), ) return cmd diff --git a/cli/command/system/dial_stdio.go b/cli/command/system/dial_stdio.go new file mode 100644 index 000000000000..5b593df31e19 --- /dev/null +++ b/cli/command/system/dial_stdio.go @@ -0,0 +1,100 @@ +package system + +import ( + "context" + "io" + "os" + + "github.com/docker/cli/cli" + "github.com/docker/cli/cli/command" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" +) + +type dialStdioOptions struct { +} + +// newDialStdioCommand creates a new cobra.Command for `docker system dial-stdio` +func newDialStdioCommand(dockerCli command.Cli) *cobra.Command { + var opts dialStdioOptions + + cmd := &cobra.Command{ + Use: "dial-stdio [OPTIONS]", + Short: "Proxy the stdio stream to the daemon connection. Should not be invoked manually.", + Args: cli.NoArgs, + Hidden: true, + RunE: func(cmd *cobra.Command, args []string) error { + return runDialStdio(dockerCli, opts) + }, + } + return cmd +} + +func runDialStdio(dockerCli command.Cli, opts dialStdioOptions) error { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + dialer := dockerCli.Client().Dialer() + conn, err := dialer(ctx) + if err != nil { + return errors.Wrap(err, "failed to open the raw stream connection") + } + connHalfCloser, ok := conn.(halfCloser) + if !ok { + return errors.New("the raw stream connection does not implement halfCloser") + } + stdio := &stdioHalfCloser{r: os.Stdin, w: os.Stdout} + var eg errgroup.Group + eg.Go(func() error { return copier(connHalfCloser, stdio) }) + eg.Go(func() error { return copier(stdio, connHalfCloser) }) + return eg.Wait() +} + +func copier(to halfCloser, from halfCloser) error { + if _, err := io.Copy(to, from); err != nil { + return errors.Wrapf(err, "error while Copy (to=%+v, from=%+v)", to, from) + } + if err := from.CloseRead(); err != nil { + return errors.Wrapf(err, "error while CloseRead (from=%+v)", from) + } + if err := to.CloseWrite(); err != nil { + return errors.Wrapf(err, "error while CloseWrite (to=%+v)", to) + } + return nil +} + +type halfReadCloser interface { + io.Reader + CloseRead() error +} + +type halfWriteCloser interface { + io.Writer + CloseWrite() error +} + +type halfCloser interface { + halfReadCloser + halfWriteCloser +} + +type stdioHalfCloser struct { + r io.ReadCloser + w io.WriteCloser +} + +func (x *stdioHalfCloser) Read(p []byte) (int, error) { + return x.r.Read(p) +} + +func (x *stdioHalfCloser) CloseRead() error { + return x.r.Close() +} + +func (x *stdioHalfCloser) Write(p []byte) (int, error) { + return x.w.Write(p) +} + +func (x *stdioHalfCloser) CloseWrite() error { + return x.w.Close() +} diff --git a/cli/connhelper/connhelper.go b/cli/connhelper/connhelper.go new file mode 100644 index 000000000000..612f566131ab --- /dev/null +++ b/cli/connhelper/connhelper.go @@ -0,0 +1,144 @@ +// Package connhelper provides helpers for connecting to a remote daemon host with custom logic. +package connhelper + +import ( + "context" + "fmt" + "io" + "net" + "net/url" + "os" + "os/exec" + "time" + + "github.com/sirupsen/logrus" +) + +// ConnectionHelper allows to connect to a remote host with custom stream provider binary. +type ConnectionHelper struct { + Dialer func(ctx context.Context, network, addr string) (net.Conn, error) + Host string // dummy URL used for HTTP requests. e.g. "http://docker" +} + +// GetConnectionHelper returns Docker-specific connection helper for the given URL. +// GetConnectionHelper returns nil without error when no helper is registered for the scheme. +// URL is like "ssh://me@server01". +func GetConnectionHelper(daemonURL string) (*ConnectionHelper, error) { + u, err := url.Parse(daemonURL) + if err != nil { + return nil, err + } + switch scheme := u.Scheme; scheme { + case "ssh": + return newSSHConnectionHelper(daemonURL) + } + // Future version may support plugins via ~/.docker/config.json. e.g. "dind" + // See docker/cli#889 for the previous discussion. + return nil, err +} + +func newCommandConn(ctx context.Context, cmd string, args ...string) (net.Conn, error) { + var ( + c commandConn + err error + ) + c.cmd = exec.CommandContext(ctx, cmd, args...) + // we assume that args never contains sensitive information + logrus.Debugf("connhelper (%s): starting with %v", cmd, args) + c.cmd.Env = os.Environ() + setPdeathsig(c.cmd) + c.stdin, err = c.cmd.StdinPipe() + if err != nil { + return nil, err + } + c.stdout, err = c.cmd.StdoutPipe() + if err != nil { + return nil, err + } + c.cmd.Stderr = &logrusDebugWriter{ + prefix: fmt.Sprintf("connhelper (%s):", cmd), + } + c.localAddr = dummyAddr{network: "dummy", s: "dummy-0"} + c.remoteAddr = dummyAddr{network: "dummy", s: "dummy-1"} + return &c, c.cmd.Start() +} + +// commandConn implements net.Conn +type commandConn struct { + cmd *exec.Cmd + stdin io.WriteCloser + stdout io.ReadCloser + localAddr net.Addr + remoteAddr net.Addr +} + +func (c *commandConn) CloseRead() error { + return c.stdout.Close() +} + +func (c *commandConn) Read(p []byte) (int, error) { + return c.stdout.Read(p) +} + +func (c *commandConn) CloseWrite() error { + return c.stdin.Close() +} + +func (c *commandConn) Write(p []byte) (int, error) { + return c.stdin.Write(p) +} + +func (c *commandConn) Close() error { + if err := c.cmd.Process.Kill(); err != nil { + return err + } + _, werr := c.cmd.Process.Wait() + if err := c.stdin.Close(); err != nil { + logrus.Warnf("error while closing stdin: %v", err) + } + if err := c.stdout.Close(); err != nil { + logrus.Warnf("error while closing stdout: %v", err) + } + return werr +} + +func (c *commandConn) LocalAddr() net.Addr { + return c.localAddr +} +func (c *commandConn) RemoteAddr() net.Addr { + return c.remoteAddr +} +func (c *commandConn) SetDeadline(t time.Time) error { + logrus.Debugf("unimplemented call: SetDeadline(%v)", t) + return nil +} +func (c *commandConn) SetReadDeadline(t time.Time) error { + logrus.Debugf("unimplemented call: SetReadDeadline(%v)", t) + return nil +} +func (c *commandConn) SetWriteDeadline(t time.Time) error { + logrus.Debugf("unimplemented call: SetWriteDeadline(%v)", t) + return nil +} + +type dummyAddr struct { + network string + s string +} + +func (d dummyAddr) Network() string { + return d.network +} + +func (d dummyAddr) String() string { + return d.s +} + +type logrusDebugWriter struct { + prefix string +} + +func (w *logrusDebugWriter) Write(p []byte) (int, error) { + logrus.Debugf("%s%s", w.prefix, string(p)) + return len(p), nil +} diff --git a/cli/connhelper/connhelper_linux.go b/cli/connhelper/connhelper_linux.go new file mode 100644 index 000000000000..f138f53675a5 --- /dev/null +++ b/cli/connhelper/connhelper_linux.go @@ -0,0 +1,12 @@ +package connhelper + +import ( + "os/exec" + "syscall" +) + +func setPdeathsig(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } +} diff --git a/cli/connhelper/connhelper_nolinux.go b/cli/connhelper/connhelper_nolinux.go new file mode 100644 index 000000000000..c8350d9d7727 --- /dev/null +++ b/cli/connhelper/connhelper_nolinux.go @@ -0,0 +1,10 @@ +// +build !linux + +package connhelper + +import ( + "os/exec" +) + +func setPdeathsig(cmd *exec.Cmd) { +} diff --git a/cli/connhelper/ssh.go b/cli/connhelper/ssh.go new file mode 100644 index 000000000000..2ff1d9751c7a --- /dev/null +++ b/cli/connhelper/ssh.go @@ -0,0 +1,77 @@ +package connhelper + +import ( + "context" + "net" + "net/url" + + "github.com/pkg/errors" +) + +func newSSHConnectionHelper(daemonURL string) (*ConnectionHelper, error) { + sp, err := parseSSHURL(daemonURL) + if err != nil { + return nil, err + } + sshBinary := "ssh" + sshArgs := sp.Args() + // requires Docker 18.05 or later on the remote host. + dialStdio := []string{"docker", "system", "dial-stdio"} + fullArgs := append(sshArgs, append([]string{"--"}, dialStdio...)...) + h := &ConnectionHelper{ + Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) { + return newCommandConn(ctx, sshBinary, fullArgs...) + }, + Host: "http://docker", + } + return h, nil +} + +func parseSSHURL(daemonURL string) (*sshSpec, error) { + u, err := url.Parse(daemonURL) + if err != nil { + return nil, err + } + if u.Scheme != "ssh" { + return nil, errors.Errorf("expected scheme: ssh, got %s", u.Scheme) + } + + var sp sshSpec + + if u.User != nil { + sp.user = u.User.Username() + if _, ok := u.User.Password(); ok { + return nil, errors.New("ssh does not accept plain-text password") + } + } + sp.host = u.Hostname() + sp.port = u.Port() + if u.Path != "" { + return nil, errors.Errorf("extra path: %s", u.Path) + } + if u.RawQuery != "" { + return nil, errors.Errorf("extra query: %s", u.RawQuery) + } + if u.Fragment != "" { + return nil, errors.Errorf("extra fragment: %s", u.Fragment) + } + return &sp, err +} + +type sshSpec struct { + user string + host string + port string +} + +func (sp *sshSpec) Args() []string { + var args []string + if sp.user != "" { + args = append(args, "-l", sp.user) + } + if sp.port != "" { + args = append(args, "-p", sp.port) + } + args = append(args, sp.host) + return args +} diff --git a/cli/flags/common.go b/cli/flags/common.go index 3834097c3ad4..22faf12ca634 100644 --- a/cli/flags/common.go +++ b/cli/flags/common.go @@ -67,7 +67,8 @@ func (commonOpts *CommonOptions) InstallFlags(flags *pflag.FlagSet) { flags.Var(opts.NewQuotedString(&tlsOptions.CertFile), "tlscert", "Path to TLS certificate file") flags.Var(opts.NewQuotedString(&tlsOptions.KeyFile), "tlskey", "Path to TLS key file") - hostOpt := opts.NewNamedListOptsRef("hosts", &commonOpts.Hosts, opts.ValidateHost) + // opts.ValidateHost is not used here, so as to allow connection helpers + hostOpt := opts.NewNamedListOptsRef("hosts", &commonOpts.Hosts, nil) flags.VarP(hostOpt, "host", "H", "Daemon socket(s) to connect to") } diff --git a/docs/reference/commandline/dockerd.md b/docs/reference/commandline/dockerd.md index 1afc27e8b1d2..0aabdc722c6d 100644 --- a/docs/reference/commandline/dockerd.md +++ b/docs/reference/commandline/dockerd.md @@ -181,6 +181,19 @@ The Docker client will honor the `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment variables (or the lowercase versions thereof). `HTTPS_PROXY` takes precedence over `HTTP_PROXY`. +Starting with Docker 18.05, the Docker client supports connecting to a remote +daemon via SSH: + +``` +$ docker -H ssh://me@example.com:22 ps +$ docker -H ssh://me@example.com ps +$ docker -H ssh://example.com ps +``` + +To use SSH connection, you need to set up `ssh` so that it can reach the +remote host with public key authentication. +Also, you need to have `docker` binary 18.05 or later on the daemon host. + #### Bind Docker to another host/port or a Unix socket > **Warning**: diff --git a/vendor.conf b/vendor.conf index f32af05797d7..aa1453249309 100755 --- a/vendor.conf +++ b/vendor.conf @@ -7,7 +7,8 @@ github.com/coreos/etcd v3.2.1 github.com/cpuguy83/go-md2man v1.0.8 github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5 -github.com/docker/docker b711437bbd8596312c962d4189e9ad4d2108c2dc +# https://github.com/moby/moby/pull/36630 +github.com/docker/docker 4a289b3dca24fc9c78057afc039a548a288efca4 https://github.com/AkihiroSuda/docker.git github.com/docker/docker-credential-helpers 5241b46610f2491efdf9d1c85f1ddf5b02f6d962 # the docker/go package contains a customized version of canonical/json # and is used by Notary. The package is periodically rebased on current Go versions. diff --git a/vendor/github.com/docker/docker/api/types/volume/volume_create.go b/vendor/github.com/docker/docker/api/types/volume/volume_create.go index 539e9b97d904..f12e48612c56 100644 --- a/vendor/github.com/docker/docker/api/types/volume/volume_create.go +++ b/vendor/github.com/docker/docker/api/types/volume/volume_create.go @@ -7,7 +7,7 @@ package volume // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// VolumeCreateBody +// VolumeCreateBody Volume configuration // swagger:model VolumeCreateBody type VolumeCreateBody struct { diff --git a/vendor/github.com/docker/docker/api/types/volume/volume_list.go b/vendor/github.com/docker/docker/api/types/volume/volume_list.go index 1bb279dbb3f3..020198f7371b 100644 --- a/vendor/github.com/docker/docker/api/types/volume/volume_list.go +++ b/vendor/github.com/docker/docker/api/types/volume/volume_list.go @@ -9,7 +9,7 @@ package volume import "github.com/docker/docker/api/types" -// VolumeListOKBody +// VolumeListOKBody Volume list response // swagger:model VolumeListOKBody type VolumeListOKBody struct { diff --git a/vendor/github.com/docker/docker/client/build_cancel.go b/vendor/github.com/docker/docker/client/build_cancel.go index 4cf8c980a9b5..74df49508917 100644 --- a/vendor/github.com/docker/docker/client/build_cancel.go +++ b/vendor/github.com/docker/docker/client/build_cancel.go @@ -1,9 +1,8 @@ package client // import "github.com/docker/docker/client" import ( + "context" "net/url" - - "golang.org/x/net/context" ) // BuildCancel requests the daemon to cancel ongoing build request diff --git a/vendor/github.com/docker/docker/client/client.go b/vendor/github.com/docker/docker/client/client.go index b874b3b522bb..72ddb93dab65 100644 --- a/vendor/github.com/docker/docker/client/client.go +++ b/vendor/github.com/docker/docker/client/client.go @@ -63,6 +63,9 @@ import ( // ErrRedirect is the error returned by checkRedirect when the request is non-GET. var ErrRedirect = errors.New("unexpected redirect in response") +// HijackDialer is the type used for custom hijack dialer +type HijackDialer func(ctx context.Context, network, addr string) (net.Conn, error) + // Client is the API client that performs all operations // against a docker server. type Client struct { @@ -78,6 +81,8 @@ type Client struct { basePath string // client used to send and receive http requests. client *http.Client + // dialer used for hijacking. See WithHijackDialer(). + hijackDialer HijackDialer // version of the server to talk to. version string // custom http headers configured by users. @@ -174,9 +179,15 @@ func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) err // WithDialer applies the dialer.DialContext to the client transport. This can be // used to set the Timeout and KeepAlive settings of the client. func WithDialer(dialer *net.Dialer) func(*Client) error { + return WithDialContext(dialer.DialContext) +} + +// WithDialer applies the dialer to the client transport. This can be +// used to set the Timeout and KeepAlive settings of the client. +func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) func(*Client) error { return func(c *Client) error { if transport, ok := c.client.Transport.(*http.Transport); ok { - transport.DialContext = dialer.DialContext + transport.DialContext = dialContext return nil } return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport) @@ -209,7 +220,11 @@ func WithHost(host string) func(*Client) error { } } -// WithHTTPClient overrides the client http client with the specified one +// WithHTTPClient overrides the client http client with the specified one. +// +// This function does not overrides the dialer user for hijacking. +// To overrides the hijack dialer, you may want to call +// WithHijackDialer(client.Transport.(*http.Transport).DialContext) . func WithHTTPClient(client *http.Client) func(*Client) error { return func(c *Client) error { if client != nil { @@ -219,6 +234,21 @@ func WithHTTPClient(client *http.Client) func(*Client) error { } } +// WithHijackDialer overrides the client default hijack dialer. +// The typical usecase of WithHijackDialer is to support ContainerAttach() +// and ContainerExecAttach() with a custom dialer. +// +// The hijack dialer typically corresponds to *http.Client.Transport.(*http.Tranport).DialContext . +// See http.Transport.DialContext for more information. +func WithHijackDialer(hijackDialer HijackDialer) func(*Client) error { + return func(c *Client) error { + if hijackDialer != nil { + c.hijackDialer = hijackDialer + } + return nil + } +} + // WithHTTPHeaders overrides the client default http headers func WithHTTPHeaders(headers map[string]string) func(*Client) error { return func(c *Client) error { @@ -266,7 +296,6 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) { // this to avoid breaking existing clients but this should be addressed. c.scheme = "https" } - return c, nil } @@ -400,3 +429,16 @@ func (cli *Client) CustomHTTPHeaders() map[string]string { func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) { cli.customHTTPHeaders = headers } + +// Dialer returns a dialer for a raw stream connection, with HTTP/1.1 header, that can be used for proxying the daemon connection. +// Used by `docker dial-stdio` (docker/cli#889). +func (cli *Client) Dialer() func(context.Context) (net.Conn, error) { + return func(ctx context.Context) (net.Conn, error) { + if transport, ok := cli.client.Transport.(*http.Transport); ok { + if transport.DialContext != nil { + return transport.DialContext(ctx, cli.proto, cli.addr) + } + } + return fallbackDial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport)) + } +} diff --git a/vendor/github.com/docker/docker/client/hijack.go b/vendor/github.com/docker/docker/client/hijack.go index 35f5dd86dc1e..0ac8248f2c7b 100644 --- a/vendor/github.com/docker/docker/client/hijack.go +++ b/vendor/github.com/docker/docker/client/hijack.go @@ -30,7 +30,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu } req = cli.addHeaders(req, headers) - conn, err := cli.setupHijackConn(req, "tcp") + conn, err := cli.setupHijackConn(ctx, req, "tcp") if err != nil { return types.HijackedResponse{}, err } @@ -38,7 +38,9 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err } -func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { +// fallbackDial is used when WithDialer() was not called. +// See cli.Dialer(). +func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { if tlsConfig != nil && proto != "unix" && proto != "npipe" { return tls.Dial(proto, addr, tlsConfig) } @@ -48,12 +50,13 @@ func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { return net.Dial(proto, addr) } -func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, error) { +func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, error) { req.Host = cli.addr req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", proto) - conn, err := dial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport)) + dialer := cli.Dialer() + conn, err := dialer(ctx) if err != nil { return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") } diff --git a/vendor/github.com/docker/docker/client/interface.go b/vendor/github.com/docker/docker/client/interface.go index 9250c468a6e1..663749f00854 100644 --- a/vendor/github.com/docker/docker/client/interface.go +++ b/vendor/github.com/docker/docker/client/interface.go @@ -39,6 +39,7 @@ type CommonAPIClient interface { NegotiateAPIVersion(ctx context.Context) NegotiateAPIVersionPing(types.Ping) DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) + Dialer() func(context.Context) (net.Conn, error) Close() error } diff --git a/vendor/github.com/docker/docker/client/session.go b/vendor/github.com/docker/docker/client/session.go index c247123b456d..df199f3d03ab 100644 --- a/vendor/github.com/docker/docker/client/session.go +++ b/vendor/github.com/docker/docker/client/session.go @@ -14,5 +14,5 @@ func (cli *Client) DialSession(ctx context.Context, proto string, meta map[strin } req = cli.addHeaders(req, meta) - return cli.setupHijackConn(req, proto) + return cli.setupHijackConn(ctx, req, proto) } diff --git a/vendor/github.com/docker/docker/vendor.conf b/vendor/github.com/docker/docker/vendor.conf index 33e2dc84454f..5ff20bb54e4a 100644 --- a/vendor/github.com/docker/docker/vendor.conf +++ b/vendor/github.com/docker/docker/vendor.conf @@ -7,7 +7,7 @@ github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://githu github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a github.com/gorilla/context v1.1 github.com/gorilla/mux v1.1 -github.com/Microsoft/opengcs v0.3.6 +github.com/Microsoft/opengcs v0.3.8 github.com/kr/pty 5cf931ef8f github.com/mattn/go-shellwords v1.0.3 github.com/sirupsen/logrus v1.0.3 @@ -26,7 +26,7 @@ github.com/imdario/mergo v0.3.5 golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5 # buildkit -github.com/moby/buildkit 9acf51e49185b348608e0096b2903dd72907adcb +github.com/moby/buildkit 98f1604134f945d48538ffca0e18662337b4a850 github.com/tonistiigi/fsutil 8abad97ee3969cdf5e9c367f46adba2c212b3ddb github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7 @@ -37,7 +37,7 @@ github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b #get libnetwork packages # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy accordingly -github.com/docker/libnetwork 430c00a6a6b3dfdd774f21e1abd4ad6b0216c629 +github.com/docker/libnetwork d00ceed44cc447c77f25cdf5d59e83163bdcb4c9 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec @@ -95,7 +95,7 @@ github.com/philhofer/fwd 98c11a7a6ec829d672b03833c3d69a7fae1ca972 github.com/tinylib/msgp 3b556c64540842d4f82967be066a7f7fffc3adad # fsnotify -github.com/fsnotify/fsnotify 4da3e2cfbabc9f751898f250b49f2439785783a1 +github.com/fsnotify/fsnotify v1.4.7 # awslogs deps github.com/aws/aws-sdk-go v1.12.66 @@ -114,22 +114,22 @@ github.com/googleapis/gax-go v2.0.0 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9 # containerd -github.com/containerd/containerd 08f7ee9828af1783dc98cc5cc1739e915697c667 +github.com/containerd/containerd b41633746ed4833f52c3c071e8edcfa2713e5677 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c -github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b +github.com/containerd/continuity 0377f7d767206f3a9e8881d0f02267b0d89c7a62 github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130 -github.com/containerd/console 9290d21dc56074581f619579c43d970b4514bc08 +github.com/containerd/console 5d1b48d6114b8c9666f0c8b916f871af97b0a761 github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd -github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788 -github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577 +github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 +github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef # cluster -github.com/docker/swarmkit edd5641391926a50bc5f7040e20b7efc05003c26 +github.com/docker/swarmkit 68266392a176434d282760d2d6d0ab4c68edcae6 github.com/gogo/protobuf v1.0.0 -github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a +github.com/cloudflare/cfssl 1.3.2 github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2 -github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e +github.com/google/certificate-transparency-go v1.0.20 golang.org/x/crypto 1a580b3eff7814fc9b40602fd35256c63b50f491 golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad