Browse code

Move plugin client to separate interface

This makes it a bit simpler to remove this interface for v2 plugins
and not break external projects (libnetwork and swarmkit).

Note that before we remove the `Client()` interface from `CompatPlugin`
libnetwork and swarmkit must be updated to explicitly check for the v1
client interface as is done int his PR.

This is just a minor tweak that I realized is needed after trying to
implement the needed changes on libnetwork.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2018/05/31 04:00:42
Showing 5 changed files
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"path/filepath"
6 6
 
7
+	"github.com/docker/docker/errdefs"
7 8
 	"github.com/docker/docker/pkg/plugingetter"
8 9
 	"github.com/docker/docker/pkg/plugins"
9 10
 	"github.com/docker/docker/plugin/v2"
... ...
@@ -33,19 +34,22 @@ func newPluginDriver(name string, pl plugingetter.CompatPlugin, config Options)
33 33
 
34 34
 	var proxy *graphDriverProxy
35 35
 
36
-	pa, ok := pl.(plugingetter.PluginAddr)
37
-	if !ok {
38
-		proxy = &graphDriverProxy{name, pl, Capabilities{}, pl.Client()}
39
-	} else {
40
-		if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
41
-			return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol())
36
+	switch pt := pl.(type) {
37
+	case plugingetter.PluginWithV1Client:
38
+		proxy = &graphDriverProxy{name, pl, Capabilities{}, pt.Client()}
39
+	case plugingetter.PluginAddr:
40
+		if pt.Protocol() != plugins.ProtocolSchemeHTTPV1 {
41
+			return nil, errors.Errorf("plugin protocol not supported: %s", pt.Protocol())
42 42
 		}
43
-		addr := pa.Addr()
44
-		client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout())
43
+		addr := pt.Addr()
44
+		client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pt.Timeout())
45 45
 		if err != nil {
46 46
 			return nil, errors.Wrap(err, "error creating plugin client")
47 47
 		}
48 48
 		proxy = &graphDriverProxy{name, pl, Capabilities{}, client}
49
+	default:
50
+		return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", pt))
49 51
 	}
52
+
50 53
 	return proxy, proxy.Init(filepath.Join(home, name), config.DriverOptions, config.UIDMaps, config.GIDMaps)
51 54
 }
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"path/filepath"
8 8
 
9 9
 	"github.com/docker/docker/api/types/plugins/logdriver"
10
+	"github.com/docker/docker/errdefs"
10 11
 	getter "github.com/docker/docker/pkg/plugingetter"
11 12
 	"github.com/docker/docker/pkg/plugins"
12 13
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -46,9 +47,12 @@ func getPlugin(name string, mode int) (Creator, error) {
46 46
 }
47 47
 
48 48
 func makePluginClient(p getter.CompatPlugin) (logPlugin, error) {
49
+	if pc, ok := p.(getter.PluginWithV1Client); ok {
50
+		return &logPluginProxy{pc.Client()}, nil
51
+	}
49 52
 	pa, ok := p.(getter.PluginAddr)
50 53
 	if !ok {
51
-		return &logPluginProxy{p.Client()}, nil
54
+		return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", p))
52 55
 	}
53 56
 
54 57
 	if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
... ...
@@ -3,6 +3,7 @@ package daemon // import "github.com/docker/docker/daemon"
3 3
 import (
4 4
 	"sync"
5 5
 
6
+	"github.com/docker/docker/errdefs"
6 7
 	"github.com/docker/docker/pkg/plugingetter"
7 8
 	"github.com/docker/docker/pkg/plugins"
8 9
 	"github.com/docker/go-metrics"
... ...
@@ -142,11 +143,16 @@ type metricsPlugin interface {
142 142
 	StopMetrics() error
143 143
 }
144 144
 
145
-func makePluginAdapter(p plugingetter.CompatPlugin) (metricsPlugin, error) {
145
+func makePluginAdapter(p plugingetter.CompatPlugin) (metricsPlugin, error) { // nolint: interfacer
146
+	if pc, ok := p.(plugingetter.PluginWithV1Client); ok {
147
+		return &metricsPluginAdapter{pc.Client(), p.Name()}, nil
148
+	}
149
+
146 150
 	pa, ok := p.(plugingetter.PluginAddr)
147 151
 	if !ok {
148
-		return &metricsPluginAdapter{p.Client(), p.Name()}, nil
152
+		return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", p))
149 153
 	}
154
+
150 155
 	if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
151 156
 		return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol())
152 157
 	}
... ...
@@ -18,15 +18,19 @@ const (
18 18
 
19 19
 // CompatPlugin is an abstraction to handle both v2(new) and v1(legacy) plugins.
20 20
 type CompatPlugin interface {
21
-	Client() *plugins.Client
22 21
 	Name() string
23 22
 	ScopedPath(string) string
24 23
 	IsV1() bool
24
+	PluginWithV1Client
25
+}
26
+
27
+// PluginWithV1Client is a plugin that directly utilizes the v1/http plugin client
28
+type PluginWithV1Client interface {
29
+	Client() *plugins.Client
25 30
 }
26 31
 
27 32
 // PluginAddr is a plugin that exposes the socket address for creating custom clients rather than the built-in `*plugins.Client`
28 33
 type PluginAddr interface {
29
-	CompatPlugin
30 34
 	Addr() net.Addr
31 35
 	Timeout() time.Duration
32 36
 	Protocol() string
... ...
@@ -212,9 +212,13 @@ func (s *Store) GetAllDrivers() ([]volume.Driver, error) {
212 212
 }
213 213
 
214 214
 func makePluginAdapter(p getter.CompatPlugin) (*volumeDriverAdapter, error) {
215
+	if pc, ok := p.(getter.PluginWithV1Client); ok {
216
+		return &volumeDriverAdapter{name: p.Name(), scopePath: p.ScopedPath, proxy: &volumeDriverProxy{pc.Client()}}, nil
217
+	}
218
+
215 219
 	pa, ok := p.(getter.PluginAddr)
216 220
 	if !ok {
217
-		return &volumeDriverAdapter{name: p.Name(), scopePath: p.ScopedPath, proxy: &volumeDriverProxy{p.Client()}}, nil
221
+		return nil, errdefs.System(errors.Errorf("got unknown plugin instance %T", p))
218 222
 	}
219 223
 
220 224
 	if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {