Skip to content

Commit 76c81ed

Browse files
committed
reuse http client
1 parent 5d52fde commit 76c81ed

File tree

4 files changed

+150
-60
lines changed

4 files changed

+150
-60
lines changed

engine/docker/docker.go

+9-36
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ package docker
22

33
import (
44
"context"
5-
"fmt"
6-
"io/ioutil"
75
"net/http"
8-
"os"
6+
"strings"
97

108
"github.com/projecteru2/core/engine"
119
enginetypes "github.com/projecteru2/core/engine/types"
1210
"github.com/projecteru2/core/log"
1311
coretypes "github.com/projecteru2/core/types"
12+
"github.com/projecteru2/core/utils"
1413

1514
dockerapi "github.com/docker/docker/client"
16-
"github.com/docker/go-connections/tlsconfig"
1715
)
1816

1917
const (
@@ -34,44 +32,19 @@ type Engine struct {
3432
// MakeClient make docker cli
3533
func MakeClient(ctx context.Context, config coretypes.Config, nodename, endpoint, ca, cert, key string) (engine.API, error) {
3634
var client *http.Client
37-
if config.CertPath != "" && ca != "" && cert != "" && key != "" { // nolint
38-
caFile, err := ioutil.TempFile(config.CertPath, fmt.Sprintf("ca-%s", nodename))
35+
var err error
36+
if strings.HasPrefix(endpoint, "unix://") {
37+
client = utils.GetUnixSockClient()
38+
} else {
39+
client, err = utils.GetHTTPSClient(ctx, config.CertPath, nodename, ca, cert, key)
3940
if err != nil {
41+
log.Errorf(ctx, "[MakeClient] GetHTTPSClient for %s %s error: %v", nodename, endpoint, err)
4042
return nil, err
4143
}
42-
certFile, err := ioutil.TempFile(config.CertPath, fmt.Sprintf("cert-%s", nodename))
43-
if err != nil {
44-
return nil, err
45-
}
46-
keyFile, err := ioutil.TempFile(config.CertPath, fmt.Sprintf("key-%s", nodename))
47-
if err != nil {
48-
return nil, err
49-
}
50-
if err = dumpFromString(ctx, caFile, certFile, keyFile, ca, cert, key); err != nil {
51-
return nil, err
52-
}
53-
options := tlsconfig.Options{
54-
CAFile: caFile.Name(),
55-
CertFile: certFile.Name(),
56-
KeyFile: keyFile.Name(),
57-
InsecureSkipVerify: true,
58-
}
59-
defer os.Remove(caFile.Name())
60-
defer os.Remove(certFile.Name())
61-
defer os.Remove(keyFile.Name())
62-
tlsc, err := tlsconfig.Client(options)
63-
if err != nil {
64-
return nil, err
65-
}
66-
client = &http.Client{
67-
Transport: &http.Transport{
68-
TLSClientConfig: tlsc,
69-
},
70-
}
7144
}
7245

7346
log.Debugf(ctx, "[MakeDockerEngine] Create new http.Client for %s, %s", endpoint, config.Docker.APIVersion)
74-
return makeRawClient(ctx, config, client, endpoint)
47+
return makeDockerClient(ctx, config, client, endpoint)
7548
}
7649

7750
// Info show node info

engine/docker/helper.go

+1-19
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ func GetIP(ctx context.Context, daemonHost string) string {
257257
return u.Hostname()
258258
}
259259

260-
func makeRawClient(_ context.Context, config coretypes.Config, client *http.Client, endpoint string) (engine.API, error) {
260+
func makeDockerClient(_ context.Context, config coretypes.Config, client *http.Client, endpoint string) (engine.API, error) {
261261
cli, err := dockerapi.NewClientWithOpts(
262262
dockerapi.WithHost(endpoint),
263263
dockerapi.WithVersion(config.Docker.APIVersion),
@@ -268,24 +268,6 @@ func makeRawClient(_ context.Context, config coretypes.Config, client *http.Clie
268268
return &Engine{cli, config}, nil
269269
}
270270

271-
func dumpFromString(ctx context.Context, ca, cert, key *os.File, caStr, certStr, keyStr string) error {
272-
files := []*os.File{ca, cert, key}
273-
data := []string{caStr, certStr, keyStr}
274-
for i := 0; i < 3; i++ {
275-
if _, err := files[i].WriteString(data[i]); err != nil {
276-
return err
277-
}
278-
if err := files[i].Chmod(0444); err != nil {
279-
return err
280-
}
281-
if err := files[i].Close(); err != nil {
282-
return err
283-
}
284-
}
285-
log.Debug(ctx, "[dumpFromString] Dump ca.pem, cert.pem, key.pem from string")
286-
return nil
287-
}
288-
289271
func useCNI(labels map[string]string) bool {
290272
for k, v := range labels {
291273
if k == "cni" && v == "1" {

engine/factory/factory.go

-5
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,6 @@ func validateEngine(ctx context.Context, engine engine.API, timeout time.Duratio
141141
utils.WithTimeout(ctx, timeout, func(ctx context.Context) {
142142
err = engine.Ping(ctx)
143143
})
144-
if err != nil {
145-
if closeErr := engine.CloseConn(); closeErr != nil {
146-
log.Errorf(ctx, "[validateEngine] close conn error: %v", closeErr)
147-
}
148-
}
149144
return err
150145
}
151146

utils/http.go

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package utils
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io/ioutil"
7+
"net"
8+
"net/http"
9+
"os"
10+
"runtime"
11+
"strings"
12+
"time"
13+
14+
"github.com/cornelk/hashmap"
15+
"github.com/docker/go-connections/tlsconfig"
16+
17+
"github.com/projecteru2/core/log"
18+
)
19+
20+
var defaultHTTPClient = &http.Client{
21+
CheckRedirect: checkRedirect,
22+
Transport: getDefaultTransport(),
23+
}
24+
25+
var defaultUnixSockClient = &http.Client{
26+
Transport: getDefaultUnixSockTransport(),
27+
}
28+
29+
var httpsClientCache = hashmap.New(32)
30+
31+
// GetHTTPClient returns a HTTP client
32+
func GetHTTPClient() *http.Client {
33+
return defaultHTTPClient
34+
}
35+
36+
// GetUnixSockClient .
37+
func GetUnixSockClient() *http.Client {
38+
return defaultUnixSockClient
39+
}
40+
41+
// GetHTTPSClient returns an HTTPS client
42+
// if cert_path/ca/cert/key is empty, it returns an HTTP client instead
43+
func GetHTTPSClient(ctx context.Context, certPath, name, ca, cert, key string) (client *http.Client, err error) {
44+
if certPath == "" || ca == "" || cert == "" || key == "" {
45+
return GetHTTPClient(), nil
46+
}
47+
48+
cacheKey := name + SHA256(fmt.Sprintf("%s-%s-%s-%s-%s", certPath, name, ca, cert, key))[:8]
49+
if httpsClient, ok := httpsClientCache.Get(cacheKey); ok {
50+
return httpsClient.(*http.Client), nil
51+
}
52+
53+
caFile, err := ioutil.TempFile(certPath, fmt.Sprintf("ca-%s", name))
54+
if err != nil {
55+
return nil, err
56+
}
57+
certFile, err := ioutil.TempFile(certPath, fmt.Sprintf("cert-%s", name))
58+
if err != nil {
59+
return nil, err
60+
}
61+
keyFile, err := ioutil.TempFile(certPath, fmt.Sprintf("key-%s", name))
62+
if err != nil {
63+
return nil, err
64+
}
65+
if err = dumpFromString(ctx, caFile, certFile, keyFile, ca, cert, key); err != nil {
66+
return nil, err
67+
}
68+
options := tlsconfig.Options{
69+
CAFile: caFile.Name(),
70+
CertFile: certFile.Name(),
71+
KeyFile: keyFile.Name(),
72+
InsecureSkipVerify: true,
73+
}
74+
defer os.Remove(caFile.Name())
75+
defer os.Remove(certFile.Name())
76+
defer os.Remove(keyFile.Name())
77+
tlsc, err := tlsconfig.Client(options)
78+
if err != nil {
79+
return nil, err
80+
}
81+
transport := getDefaultTransport()
82+
transport.TLSClientConfig = tlsc
83+
84+
client = &http.Client{
85+
CheckRedirect: checkRedirect,
86+
Transport: transport,
87+
}
88+
httpsClientCache.Set(cacheKey, client)
89+
return client, nil
90+
}
91+
92+
func getDefaultTransport() *http.Transport {
93+
return &http.Transport{
94+
DialContext: (&net.Dialer{
95+
KeepAlive: time.Second * 30,
96+
Timeout: time.Second * 30,
97+
}).DialContext,
98+
99+
IdleConnTimeout: time.Second * 90,
100+
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
101+
Proxy: http.ProxyFromEnvironment,
102+
}
103+
}
104+
105+
func getDefaultUnixSockTransport() *http.Transport {
106+
return &http.Transport{
107+
DialContext: func(_ context.Context, _, addr string) (net.Conn, error) {
108+
return net.DialTimeout("unix", strings.Split(addr, ":")[0], time.Second*30)
109+
},
110+
111+
IdleConnTimeout: time.Second * 90,
112+
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
113+
DisableCompression: true,
114+
}
115+
}
116+
117+
func dumpFromString(ctx context.Context, ca, cert, key *os.File, caStr, certStr, keyStr string) error {
118+
files := []*os.File{ca, cert, key}
119+
data := []string{caStr, certStr, keyStr}
120+
for i := 0; i < 3; i++ {
121+
if _, err := files[i].WriteString(data[i]); err != nil {
122+
return err
123+
}
124+
if err := files[i].Chmod(0444); err != nil {
125+
return err
126+
}
127+
if err := files[i].Close(); err != nil {
128+
return err
129+
}
130+
}
131+
log.Debug(ctx, "[dumpFromString] Dump ca.pem, cert.pem, key.pem from string")
132+
return nil
133+
}
134+
135+
func checkRedirect(req *http.Request, via []*http.Request) error {
136+
if via[0].Method == http.MethodGet {
137+
return http.ErrUseLastResponse
138+
}
139+
return fmt.Errorf("unexpected redirect")
140+
}

0 commit comments

Comments
 (0)