All checks were successful
continuous-integration/drone/push Build is passing
This is an attempt to set sensible timeouts on abra connections. This might not be the last word on this but it seems that SSH connections now bail out correctly and other kinds of commands don't explode (e.g. logs). Closes coop-cloud/organising#222. Closes coop-cloud/organising#218.
83 lines
2.4 KiB
Go
83 lines
2.4 KiB
Go
package commandconn
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/url"
|
|
|
|
"github.com/docker/cli/cli/connhelper"
|
|
"github.com/docker/cli/cli/connhelper/ssh"
|
|
"github.com/docker/cli/cli/context/docker"
|
|
dCliContextStore "github.com/docker/cli/cli/context/store"
|
|
dClient "github.com/docker/docker/client"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// GetConnectionHelper returns Docker-specific connection helper for the given URL.
|
|
// GetConnectionHelper returns nil without error when no helper is registered for the scheme.
|
|
//
|
|
// ssh://<user>@<host> URL requires Docker 18.09 or later on the remote host.
|
|
func GetConnectionHelper(daemonURL string) (*connhelper.ConnectionHelper, error) {
|
|
return getConnectionHelper(daemonURL, []string{"-o ConnectTimeout=5"})
|
|
}
|
|
|
|
func getConnectionHelper(daemonURL string, sshFlags []string) (*connhelper.ConnectionHelper, error) {
|
|
u, err := url.Parse(daemonURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch scheme := u.Scheme; scheme {
|
|
case "ssh":
|
|
sp, err := ssh.ParseURL(daemonURL)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "ssh host connection is not valid")
|
|
}
|
|
return &connhelper.ConnectionHelper{
|
|
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return New(ctx, "ssh", append(sshFlags, sp.Args("docker", "system", "dial-stdio")...)...)
|
|
},
|
|
Host: "http://docker.example.com",
|
|
}, nil
|
|
}
|
|
// Future version may support plugins via ~/.docker/config.json. e.g. "dind"
|
|
// See docker/cli#889 for the previous discussion.
|
|
return nil, err
|
|
}
|
|
|
|
func NewConnectionHelper(daemonURL string) *connhelper.ConnectionHelper {
|
|
helper, err := GetConnectionHelper(daemonURL)
|
|
if err != nil {
|
|
logrus.Fatal(err)
|
|
}
|
|
|
|
return helper
|
|
}
|
|
|
|
func getDockerEndpoint(host string) (docker.Endpoint, error) {
|
|
skipTLSVerify := false
|
|
ep := docker.Endpoint{
|
|
EndpointMeta: docker.EndpointMeta{
|
|
Host: host,
|
|
SkipTLSVerify: skipTLSVerify,
|
|
},
|
|
}
|
|
// try to resolve a docker client, validating the configuration
|
|
opts, err := ep.ClientOpts()
|
|
if err != nil {
|
|
return docker.Endpoint{}, err
|
|
}
|
|
if _, err := dClient.NewClientWithOpts(opts...); err != nil {
|
|
return docker.Endpoint{}, err
|
|
}
|
|
return ep, nil
|
|
}
|
|
|
|
func GetDockerEndpointMetadataAndTLS(host string) (docker.EndpointMeta, *dCliContextStore.EndpointTLSData, error) {
|
|
ep, err := getDockerEndpoint(host)
|
|
if err != nil {
|
|
return docker.EndpointMeta{}, nil, err
|
|
}
|
|
return ep.EndpointMeta, ep.TLSData.ToStoreTLSData(), nil
|
|
}
|