agent: make docker client work on windows

This commit is contained in:
Frank Schroeder 2017-07-19 11:53:38 +02:00 committed by Frank Schröder
parent 1c6e1fe5d9
commit 6d0bd1faaf
3 changed files with 56 additions and 24 deletions

View File

@ -1734,6 +1734,7 @@ func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *structs.CheckType,
a.logger.Printf("[ERR] agent: error creating docker client: %s", err)
return err
}
a.logger.Printf("[DEBUG] agent: created docker client for %s", dc.host)
a.dockerClient = dc
}

View File

@ -2,17 +2,16 @@ package agent
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"strings"
"github.com/armon/circbuf"
"github.com/docker/go-connections/sockets"
)
// DockerClient is a simplified client for the Docker Engine API
@ -21,9 +20,11 @@ import (
// a ring buffer with a fixed limit to avoid excessive resource
// consumption.
type DockerClient struct {
network string
host string
scheme string
proto string
addr string
baseurl string
basepath string
maxbuf int64
client *http.Client
}
@ -32,33 +33,63 @@ func NewDockerClient(host string, maxbuf int64) (*DockerClient, error) {
if host == "" {
host = DefaultDockerHost
}
p := strings.SplitN(host, "://", 2)
if len(p) != 2 {
return nil, fmt.Errorf("invalid docker host: %s", host)
proto, addr, basepath, err := ParseHost(host)
if err != nil {
return nil, err
}
network, addr := p[0], p[1]
basepath := "http://" + addr
if network == "unix" {
basepath = "http://unix"
transport := new(http.Transport)
sockets.ConfigureTransport(transport, proto, addr)
client := &http.Client{Transport: transport}
return &DockerClient{
host: host,
scheme: "http",
proto: proto,
addr: addr,
basepath: basepath,
maxbuf: maxbuf,
client: client,
}, nil
}
client := &http.Client{}
if network == "unix" {
client.Transport = &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
return net.Dial(network, addr)
},
// ParseHost verifies that the given host strings is valid.
// copied from github.com/docker/docker/client.go
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)
}
var basePath string
proto, addr := protoAddrParts[0], protoAddrParts[1]
if proto == "tcp" {
parsed, err := url.Parse("tcp://" + addr)
if err != nil {
return "", "", "", err
}
return &DockerClient{network, addr, basepath, maxbuf, client}, nil
addr = parsed.Host
basePath = parsed.Path
}
return proto, addr, basePath, nil
}
func (c *DockerClient) call(method, uri string, v interface{}) (*circbuf.Buffer, int, error) {
urlstr := c.baseurl + uri
req, err := http.NewRequest(method, urlstr, nil)
req, err := http.NewRequest(method, uri, nil)
if err != nil {
return nil, 0, err
}
if c.proto == "unix" || c.proto == "npipe" {
// For local communications, it doesn't matter what the host is. We just
// need a valid and meaningful host name. (See #189)
req.Host = "docker"
}
req.URL.Host = c.addr
req.URL.Scheme = c.scheme
if v != nil {
var b bytes.Buffer
if err := json.NewEncoder(&b).Encode(v); err != nil {

View File

@ -1,4 +1,4 @@
// +build linux freebsd solaris openbsd darwin
// +build !windows
package agent