github.com/cspotcode/docker-cli@v20.10.0-rc1.0.20201201121459-3faad7acc5b8+incompatible/cli/connhelper/connhelper.go (about)

     1  // Package connhelper provides helpers for connecting to a remote daemon host with custom logic.
     2  package connhelper
     3  
     4  import (
     5  	"context"
     6  	"net"
     7  	"net/url"
     8  
     9  	"github.com/docker/cli/cli/connhelper/commandconn"
    10  	"github.com/docker/cli/cli/connhelper/ssh"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // ConnectionHelper allows to connect to a remote host with custom stream provider binary.
    15  type ConnectionHelper struct {
    16  	Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
    17  	Host   string // dummy URL used for HTTP requests. e.g. "http://docker"
    18  }
    19  
    20  // GetConnectionHelper returns Docker-specific connection helper for the given URL.
    21  // GetConnectionHelper returns nil without error when no helper is registered for the scheme.
    22  //
    23  // ssh://<user>@<host> URL requires Docker 18.09 or later on the remote host.
    24  func GetConnectionHelper(daemonURL string) (*ConnectionHelper, error) {
    25  	return getConnectionHelper(daemonURL, nil)
    26  }
    27  
    28  // GetConnectionHelperWithSSHOpts returns Docker-specific connection helper for
    29  // the given URL, and accepts additional options for ssh connections. It returns
    30  // nil without error when no helper is registered for the scheme.
    31  //
    32  // Requires Docker 18.09 or later on the remote host.
    33  func GetConnectionHelperWithSSHOpts(daemonURL string, sshFlags []string) (*ConnectionHelper, error) {
    34  	return getConnectionHelper(daemonURL, sshFlags)
    35  }
    36  
    37  func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper, error) {
    38  	u, err := url.Parse(daemonURL)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	switch scheme := u.Scheme; scheme {
    43  	case "ssh":
    44  		sp, err := ssh.ParseURL(daemonURL)
    45  		if err != nil {
    46  			return nil, errors.Wrap(err, "ssh host connection is not valid")
    47  		}
    48  		return &ConnectionHelper{
    49  			Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
    50  				return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args("docker", "system", "dial-stdio")...)...)
    51  			},
    52  			Host: "http://docker",
    53  		}, nil
    54  	}
    55  	// Future version may support plugins via ~/.docker/config.json. e.g. "dind"
    56  	// See docker/cli#889 for the previous discussion.
    57  	return nil, err
    58  }
    59  
    60  // GetCommandConnectionHelper returns Docker-specific connection helper constructed from an arbitrary command.
    61  func GetCommandConnectionHelper(cmd string, flags ...string) (*ConnectionHelper, error) {
    62  	return &ConnectionHelper{
    63  		Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
    64  			return commandconn.New(ctx, cmd, flags...)
    65  		},
    66  		Host: "http://docker",
    67  	}, nil
    68  }