in dubboctl/pkg/hub/client.go [41:131]
func NewClient(defaultHost string) (dockerClient client.CommonAPIClient, dockerHostInRemote string, err error) {
var u *url.URL
dockerHost := os.Getenv("DOCKER_HOST")
dockerHostSSHIdentity := os.Getenv("DOCKER_HOST_SSH_IDENTITY")
hostKeyCallback := fnssh.NewHostKeyCbk()
if dockerHost == "" {
u, err = url.Parse(defaultHost)
if err != nil {
return
}
_, err = os.Stat(u.Path)
switch {
case err == nil:
dockerHost = defaultHost
case err != nil && !os.IsNotExist(err):
return
}
}
if dockerHost == "" {
return nil, "", NoDockerAPIError
}
dockerHostInRemote = dockerHost
u, err = url.Parse(dockerHost)
isSSH := err == nil && u.Scheme == "ssh"
isTCP := err == nil && u.Scheme == "tcp"
isNPipe := err == nil && u.Scheme == "npipe"
isUnix := err == nil && u.Scheme == "unix"
if isTCP || isNPipe {
// With TCP or npipe, it's difficult to determine how to expose the daemon socket to lifecycle containers,
// so we are defaulting to standard docker location by returning empty string.
// This should work well most of the time.
dockerHostInRemote = ""
}
if isUnix && runtime.GOOS == "darwin" {
// A unix socket on macOS is most likely tunneled from VM,
// so it cannot be mounted under that path.
dockerHostInRemote = ""
}
if !isSSH {
opts := []client.Opt{client.FromEnv, client.WithAPIVersionNegotiation()}
if isTCP {
if httpClient := newHttpClient(); httpClient != nil {
opts = append(opts, client.WithHTTPClient(httpClient))
}
}
dockerClient, err = client.NewClientWithOpts(opts...)
return
}
credentialsConfig := fnssh.Config{
Identity: dockerHostSSHIdentity,
PassPhrase: os.Getenv("DOCKER_HOST_SSH_IDENTITY_PASSPHRASE"),
PasswordCallback: fnssh.NewPasswordCbk(),
PassPhraseCallback: fnssh.NewPassPhraseCbk(),
HostKeyCallback: hostKeyCallback,
}
contextDialer, dockerHostInRemote, err := fnssh.NewDialContext(u, credentialsConfig)
if err != nil {
return
}
httpClient := &http.Client{
Transport: &http.Transport{
DialContext: contextDialer.DialContext,
},
}
dockerClient, err = client.NewClientWithOpts(
client.WithAPIVersionNegotiation(),
client.WithHTTPClient(httpClient),
client.WithHost("tcp://placeholder/"))
if closer, ok := contextDialer.(io.Closer); ok {
dockerClient = clientWithAdditionalCleanup{
CommonAPIClient: dockerClient,
cleanUp: func() {
closer.Close()
},
}
}
return dockerClient, dockerHostInRemote, err
}