Creating http client in swarm

Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
This commit is contained in:
Nishant Totla 2016-05-02 18:45:30 -07:00
parent 2fdb517952
commit 0f188a3787
No known key found for this signature in database
GPG Key ID: 7EA5781C9B3D0C19
3 changed files with 77 additions and 3 deletions

View File

@ -11,6 +11,7 @@ import (
"math/rand"
"net"
"net/http"
"net/url"
"strings"
"sync"
"time"
@ -123,6 +124,8 @@ type Engine struct {
images []*Image
networks map[string]*Network
volumes map[string]*Volume
httpClient *http.Client
url *url.URL
client dockerclient.Client
apiClient swarmclient.SwarmAPIClient
eventHandler EventHandler
@ -158,8 +161,9 @@ func NewEngine(addr string, overcommitRatio float64, opts *EngineOpts) *Engine {
// HTTPClientAndScheme returns the underlying HTTPClient and the scheme used by the engine
func (e *Engine) HTTPClientAndScheme() (*http.Client, string, error) {
if dc, ok := e.client.(*dockerclient.DockerClient); ok {
return dc.HTTPClient, dc.URL.Scheme, nil
// TODO(nishanttotla): return the proper client after checking connection
if _, ok := e.apiClient.(*engineapi.Client); ok {
return e.httpClient, e.url.Scheme, nil
}
return nil, "", fmt.Errorf("Possibly lost connection to Engine (name: %s, ID: %s) ", e.Name, e.ID)
}
@ -178,10 +182,17 @@ func (e *Engine) Connect(config *tls.Config) error {
}
e.IP = addr.IP.String()
c, err := dockerclient.NewDockerClientTimeout("tcp://"+e.Addr, config, time.Duration(requestTimeout), setTCPUserTimeout)
// create the HTTP Client and URL
httpClient, url, err := NewHTTPClientTimeout("tcp://"+e.Addr, config, time.Duration(requestTimeout), setTCPUserTimeout)
if err != nil {
return err
}
e.httpClient = httpClient
e.url = url
// Use HTTP Client created above to create a dockerclient client
c := dockerclient.NewDockerClientFromHTTP(url, httpClient, config)
// Use HTTP Client used by dockerclient to create engine-api client
apiClient, err := engineapi.NewClient("tcp://"+e.Addr, "", c.HTTPClient, nil)
if err != nil {

57
cluster/httpclient.go Normal file
View File

@ -0,0 +1,57 @@
package cluster
import (
"crypto/tls"
"net"
"net/http"
"net/url"
"time"
)
type tcpFunc func(*net.TCPConn, time.Duration) error
func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration, setUserTimeout tcpFunc) *http.Client {
httpTransport := &http.Transport{
TLSClientConfig: tlsConfig,
}
switch u.Scheme {
default:
httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(proto, addr, timeout)
if tcpConn, ok := conn.(*net.TCPConn); ok && setUserTimeout != nil {
// Sender can break TCP connection if the remote side doesn't
// acknowledge packets within timeout
setUserTimeout(tcpConn, timeout)
}
return conn, err
}
case "unix":
socketPath := u.Path
unixDial := func(proto, addr string) (net.Conn, error) {
return net.DialTimeout("unix", socketPath, timeout)
}
httpTransport.Dial = unixDial
// Override the main URL object so the HTTP lib won't complain
u.Scheme = "http"
u.Host = "unix.sock"
u.Path = ""
}
return &http.Client{Transport: httpTransport}
}
func NewHTTPClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration, setUserTimeout tcpFunc) (*http.Client, *url.URL, error) {
u, err := url.Parse(daemonUrl)
if err != nil {
return nil, nil, err
}
if u.Scheme == "" || u.Scheme == "tcp" {
if tlsConfig == nil {
u.Scheme = "http"
} else {
u.Scheme = "https"
}
}
httpClient := newHTTPClient(u, tlsConfig, timeout, setUserTimeout)
return httpClient, u, nil
}

View File

@ -59,6 +59,12 @@ func NewDockerClient(daemonUrl string, tlsConfig *tls.Config) (*DockerClient, er
return NewDockerClientTimeout(daemonUrl, tlsConfig, time.Duration(defaultTimeout), nil)
}
// NewDockerClientFromHTTP assumes that the URL, HTTP Client, and TLS Config have been
// appropriately set when passed. It chooses default values for other fields
func NewDockerClientFromHTTP(u *url.URL, httpClient *http.Client, tlsConfig *tls.Config) *DockerClient {
return &DockerClient{u, httpClient, tlsConfig, 0, nil}
}
func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration, setUserTimeout tcpFunc) (*DockerClient, error) {
u, err := url.Parse(daemonUrl)
if err != nil {