Skip to content

Commit b45eec4

Browse files
committed
feature: add pouch plugin
To use existing docker volume and network plugin. We implement pouch plugin mechanism. We change the plugin discovery directory to /run/pouch/plugins, /etc/pouch/plugins, /usr/lib/pouch/plugins. In future, maybe we will use the grpc protocol to implement the plugin Signed-off-by: Eric Li <[email protected]>
1 parent 4d3ac8b commit b45eec4

File tree

12 files changed

+1183
-139
lines changed

12 files changed

+1183
-139
lines changed

apis/server/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import (
1111
"syscall"
1212

1313
"github.com/alibaba/pouch/apis/plugins"
14-
"github.com/alibaba/pouch/client"
1514
"github.com/alibaba/pouch/daemon/config"
1615
"github.com/alibaba/pouch/daemon/mgr"
16+
"github.com/alibaba/pouch/pkg/httputils"
1717

1818
"github.com/sirupsen/logrus"
1919
)
@@ -47,7 +47,7 @@ func (s *Server) Start() (err error) {
4747

4848
var tlsConfig *tls.Config
4949
if s.Config.TLS.Key != "" && s.Config.TLS.Cert != "" {
50-
tlsConfig, err = client.GenTLSConfig(s.Config.TLS.Key, s.Config.TLS.Cert, s.Config.TLS.CA)
50+
tlsConfig, err = httputils.GenTLSConfig(s.Config.TLS.Key, s.Config.TLS.Cert, s.Config.TLS.CA)
5151
if err != nil {
5252
return err
5353
}

client/client.go

Lines changed: 5 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
package client
22

33
import (
4-
"context"
54
"crypto/tls"
6-
"crypto/x509"
75
"fmt"
8-
"io/ioutil"
9-
"net"
106
"net/http"
117
"net/url"
128
"os"
139
"strings"
1410
"time"
11+
12+
"github.com/alibaba/pouch/pkg/httputils"
1513
)
1614

1715
var (
@@ -47,14 +45,14 @@ func NewAPIClient(host string, tls TLSConfig) (CommonAPIClient, error) {
4745
host = defaultHost
4846
}
4947

50-
newURL, basePath, addr, err := parseHost(host)
48+
newURL, basePath, addr, err := httputils.ParseHost(host)
5149
if err != nil {
5250
return nil, fmt.Errorf("failed to parse host %s: %v", host, err)
5351
}
5452

5553
tlsConfig := generateTLSConfig(host, tls)
5654

57-
httpCli := newHTTPClient(newURL, tlsConfig)
55+
httpCli := httputils.NewHTTPClient(newURL, tlsConfig, defaultTimeout)
5856

5957
basePath = generateBaseURL(newURL, tls)
6058

@@ -72,57 +70,11 @@ func NewAPIClient(host string, tls TLSConfig) (CommonAPIClient, error) {
7270
}, nil
7371
}
7472

75-
// parseHost inputs a host address string, and output three type:
76-
// url.URL, basePath and an error
77-
func parseHost(host string) (*url.URL, string, string, error) {
78-
u, err := url.Parse(host)
79-
if err != nil {
80-
return nil, "", "", err
81-
}
82-
83-
var basePath string
84-
switch u.Scheme {
85-
case "unix":
86-
basePath = "http://d"
87-
case "tcp":
88-
basePath = "http://" + u.Host
89-
case "http":
90-
basePath = host
91-
default:
92-
return nil, "", "", fmt.Errorf("not support url scheme %v", u.Scheme)
93-
}
94-
95-
return u, basePath, strings.TrimPrefix(host, u.Scheme+"://"), nil
96-
}
97-
98-
func newHTTPClient(u *url.URL, tlsConfig *tls.Config) *http.Client {
99-
tr := &http.Transport{
100-
TLSClientConfig: tlsConfig,
101-
}
102-
103-
switch u.Scheme {
104-
case "unix":
105-
unixDial := func(ctx context.Context, network, addr string) (net.Conn, error) {
106-
return net.DialTimeout("unix", u.Path, time.Duration(defaultTimeout))
107-
}
108-
tr.DialContext = unixDial
109-
default:
110-
dial := func(ctx context.Context, network, addr string) (net.Conn, error) {
111-
return net.DialTimeout(network, addr, time.Duration(defaultTimeout))
112-
}
113-
tr.DialContext = dial
114-
}
115-
116-
return &http.Client{
117-
Transport: tr,
118-
}
119-
}
120-
12173
// generateTLSConfig configures TLS for API Client.
12274
func generateTLSConfig(host string, tls TLSConfig) *tls.Config {
12375
// init tls config
12476
if tls.Key != "" && tls.Cert != "" && !strings.HasPrefix(host, "unix://") {
125-
tlsCfg, err := GenTLSConfig(tls.Key, tls.Cert, tls.CA)
77+
tlsCfg, err := httputils.GenTLSConfig(tls.Key, tls.Cert, tls.CA)
12678
if err != nil {
12779
fmt.Fprintf(os.Stderr, "fail to parse tls config %v", err)
12880
os.Exit(1)
@@ -174,27 +126,3 @@ func (client *APIClient) GetAPIPath(path string, query url.Values) string {
174126
func (client *APIClient) UpdateClientVersion(v string) {
175127
client.version = v
176128
}
177-
178-
// GenTLSConfig returns a tls config object according to inputting parameters.
179-
func GenTLSConfig(key, cert, ca string) (*tls.Config, error) {
180-
tlsConfig := &tls.Config{}
181-
tlsCert, err := tls.LoadX509KeyPair(cert, key)
182-
if err != nil {
183-
return nil, fmt.Errorf("failed to read X509 key pair (cert: %q, key: %q): %v", cert, key, err)
184-
}
185-
tlsConfig.Certificates = []tls.Certificate{tlsCert}
186-
if ca == "" {
187-
return tlsConfig, nil
188-
}
189-
190-
cp := x509.NewCertPool()
191-
pem, err := ioutil.ReadFile(ca)
192-
if err != nil {
193-
return nil, fmt.Errorf("failed to read CA certificate %q: %v", ca, err)
194-
}
195-
if !cp.AppendCertsFromPEM(pem) {
196-
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", ca)
197-
}
198-
tlsConfig.ClientCAs = cp
199-
return tlsConfig, nil
200-
}

client/client_test.go

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package client
22

33
import (
4-
"crypto/tls"
54
"fmt"
65
"net/url"
7-
"reflect"
86
"testing"
97

108
"github.com/stretchr/testify/assert"
@@ -35,36 +33,6 @@ func TestNewAPIClient(t *testing.T) {
3533
}
3634
}
3735

38-
func TestParseHost(t *testing.T) {
39-
assert := assert.New(t)
40-
type parsed struct {
41-
host string
42-
expectError bool
43-
expectBasePath string
44-
expectAddr string
45-
}
46-
47-
parseds := []parsed{
48-
{host: testHost, expectError: false, expectBasePath: "http://d", expectAddr: "/var/run/pouchd.sock"},
49-
{host: "tcp://localhost:1234", expectError: false, expectBasePath: "http://localhost:1234", expectAddr: "localhost:1234"},
50-
{host: "http://localhost:5678", expectError: false, expectBasePath: "http://localhost:5678", expectAddr: "localhost:5678"},
51-
{host: "foo:bar", expectError: true, expectBasePath: "", expectAddr: ""},
52-
{host: "", expectError: true, expectBasePath: "", expectAddr: ""},
53-
}
54-
55-
for _, p := range parseds {
56-
_, basePath, addr, err := parseHost(p.host)
57-
if p.expectError {
58-
assert.Error(err, fmt.Sprintf("test data %v", p.host))
59-
} else {
60-
assert.NoError(err, fmt.Sprintf("test data %v", p.host))
61-
}
62-
63-
assert.Equal(basePath, p.expectBasePath)
64-
assert.Equal(addr, p.expectAddr)
65-
}
66-
}
67-
6836
func Test_generateBaseURL(t *testing.T) {
6937
type args struct {
7038
u *url.URL
@@ -85,31 +53,3 @@ func Test_generateBaseURL(t *testing.T) {
8553
})
8654
}
8755
}
88-
89-
func TestGenTLSConfig(t *testing.T) {
90-
type args struct {
91-
key string
92-
cert string
93-
ca string
94-
}
95-
tests := []struct {
96-
name string
97-
args args
98-
want *tls.Config
99-
wantErr bool
100-
}{
101-
// TODO: Add test cases.
102-
}
103-
for _, tt := range tests {
104-
t.Run(tt.name, func(t *testing.T) {
105-
got, err := GenTLSConfig(tt.args.key, tt.args.cert, tt.args.ca)
106-
if (err != nil) != tt.wantErr {
107-
t.Errorf("GenTLSConfig() error = %v, wantErr %v", err, tt.wantErr)
108-
return
109-
}
110-
if !reflect.DeepEqual(got, tt.want) {
111-
t.Errorf("GenTLSConfig() = %v, want %v", got, tt.want)
112-
}
113-
})
114-
}
115-
}

pkg/httputils/client.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package httputils
2+
3+
import (
4+
"context"
5+
"crypto/tls"
6+
"crypto/x509"
7+
"fmt"
8+
"io/ioutil"
9+
"net"
10+
"net/http"
11+
"net/url"
12+
"strings"
13+
"time"
14+
)
15+
16+
// ParseHost inputs a host address string, and output three type:
17+
// url.URL, basePath and an error.
18+
func ParseHost(host string) (*url.URL, string, string, error) {
19+
u, err := url.Parse(host)
20+
if err != nil {
21+
return nil, "", "", err
22+
}
23+
24+
var basePath string
25+
switch u.Scheme {
26+
case "unix":
27+
basePath = "http://d"
28+
case "tcp":
29+
basePath = "http://" + u.Host
30+
case "http":
31+
basePath = host
32+
case "https":
33+
basePath = host
34+
default:
35+
return nil, "", "", fmt.Errorf("not support url scheme %v", u.Scheme)
36+
}
37+
38+
return u, basePath, strings.TrimPrefix(host, u.Scheme+"://"), nil
39+
}
40+
41+
// GenTLSConfig returns a tls config object according to inputting parameters.
42+
func GenTLSConfig(key, cert, ca string) (*tls.Config, error) {
43+
tlsConfig := &tls.Config{}
44+
tlsCert, err := tls.LoadX509KeyPair(cert, key)
45+
if err != nil {
46+
return nil, fmt.Errorf("failed to read X509 key pair (cert: %q, key: %q): %v", cert, key, err)
47+
}
48+
tlsConfig.Certificates = []tls.Certificate{tlsCert}
49+
if ca == "" {
50+
return tlsConfig, nil
51+
}
52+
53+
cp := x509.NewCertPool()
54+
pem, err := ioutil.ReadFile(ca)
55+
if err != nil {
56+
return nil, fmt.Errorf("failed to read CA certificate %q: %v", ca, err)
57+
}
58+
if !cp.AppendCertsFromPEM(pem) {
59+
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", ca)
60+
}
61+
tlsConfig.ClientCAs = cp
62+
return tlsConfig, nil
63+
}
64+
65+
// NewHTTPClient creates a http client using url and tlsconfig
66+
func NewHTTPClient(u *url.URL, tlsConfig *tls.Config, dialTimeout time.Duration) *http.Client {
67+
tr := &http.Transport{
68+
TLSClientConfig: tlsConfig,
69+
}
70+
71+
switch u.Scheme {
72+
case "unix":
73+
unixDial := func(ctx context.Context, network, addr string) (net.Conn, error) {
74+
return net.DialTimeout("unix", u.Path, dialTimeout)
75+
}
76+
tr.DialContext = unixDial
77+
default:
78+
dial := func(ctx context.Context, network, addr string) (net.Conn, error) {
79+
return net.DialTimeout(network, addr, dialTimeout)
80+
}
81+
tr.DialContext = dial
82+
}
83+
84+
return &http.Client{
85+
Transport: tr,
86+
}
87+
}

pkg/httputils/client_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package httputils
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"reflect"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
var (
13+
testHost = "unix:///var/run/pouchd.sock"
14+
)
15+
16+
func TestParseHost(t *testing.T) {
17+
assert := assert.New(t)
18+
type parsed struct {
19+
host string
20+
expectError bool
21+
expectBasePath string
22+
expectAddr string
23+
}
24+
25+
parseds := []parsed{
26+
{host: testHost, expectError: false, expectBasePath: "http://d", expectAddr: "/var/run/pouchd.sock"},
27+
{host: "tcp://localhost:1234", expectError: false, expectBasePath: "http://localhost:1234", expectAddr: "localhost:1234"},
28+
{host: "http://localhost:5678", expectError: false, expectBasePath: "http://localhost:5678", expectAddr: "localhost:5678"},
29+
{host: "foo:bar", expectError: true, expectBasePath: "", expectAddr: ""},
30+
{host: "", expectError: true, expectBasePath: "", expectAddr: ""},
31+
}
32+
33+
for _, p := range parseds {
34+
_, basePath, addr, err := ParseHost(p.host)
35+
if p.expectError {
36+
assert.Error(err, fmt.Sprintf("test data %v", p.host))
37+
} else {
38+
assert.NoError(err, fmt.Sprintf("test data %v", p.host))
39+
}
40+
41+
assert.Equal(basePath, p.expectBasePath)
42+
assert.Equal(addr, p.expectAddr)
43+
}
44+
}
45+
46+
func TestGenTLSConfig(t *testing.T) {
47+
type args struct {
48+
key string
49+
cert string
50+
ca string
51+
}
52+
tests := []struct {
53+
name string
54+
args args
55+
want *tls.Config
56+
wantErr bool
57+
}{
58+
// TODO: Add test cases.
59+
}
60+
for _, tt := range tests {
61+
t.Run(tt.name, func(t *testing.T) {
62+
got, err := GenTLSConfig(tt.args.key, tt.args.cert, tt.args.ca)
63+
if (err != nil) != tt.wantErr {
64+
t.Errorf("GenTLSConfig() error = %v, wantErr %v", err, tt.wantErr)
65+
return
66+
}
67+
if !reflect.DeepEqual(got, tt.want) {
68+
t.Errorf("GenTLSConfig() = %v, want %v", got, tt.want)
69+
}
70+
})
71+
}
72+
}

0 commit comments

Comments
 (0)