From 7c77df8acc597cd4f540d873de5fe53a3d414ba9 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Wed, 30 May 2018 15:00:42 -0400 Subject: [PATCH] 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 --- daemon/graphdriver/plugin.go | 20 ++++++++++++-------- daemon/logger/plugin.go | 6 +++++- daemon/metrics.go | 10 ++++++++-- pkg/plugingetter/getter.go | 8 ++++++-- volume/drivers/extpoint.go | 6 +++++- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/daemon/graphdriver/plugin.go b/daemon/graphdriver/plugin.go index f5940dfe82..b0983c5667 100644 --- a/daemon/graphdriver/plugin.go +++ b/daemon/graphdriver/plugin.go @@ -4,6 +4,7 @@ import ( "fmt" "path/filepath" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/plugin/v2" @@ -33,19 +34,22 @@ func newPluginDriver(name string, pl plugingetter.CompatPlugin, config Options) var proxy *graphDriverProxy - pa, ok := pl.(plugingetter.PluginAddr) - if !ok { - proxy = &graphDriverProxy{name, pl, Capabilities{}, pl.Client()} - } else { - if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 { - return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol()) + switch pt := pl.(type) { + case plugingetter.PluginWithV1Client: + proxy = &graphDriverProxy{name, pl, Capabilities{}, pt.Client()} + case plugingetter.PluginAddr: + if pt.Protocol() != plugins.ProtocolSchemeHTTPV1 { + return nil, errors.Errorf("plugin protocol not supported: %s", pt.Protocol()) } - addr := pa.Addr() - client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout()) + addr := pt.Addr() + client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pt.Timeout()) if err != nil { return nil, errors.Wrap(err, "error creating plugin client") } proxy = &graphDriverProxy{name, pl, Capabilities{}, client} + default: + return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", pt)) } + return proxy, proxy.Init(filepath.Join(home, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) } diff --git a/daemon/logger/plugin.go b/daemon/logger/plugin.go index 4cbb469515..c66540ce52 100644 --- a/daemon/logger/plugin.go +++ b/daemon/logger/plugin.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/docker/docker/api/types/plugins/logdriver" + "github.com/docker/docker/errdefs" getter "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/pkg/stringid" @@ -46,9 +47,12 @@ func getPlugin(name string, mode int) (Creator, error) { } func makePluginClient(p getter.CompatPlugin) (logPlugin, error) { + if pc, ok := p.(getter.PluginWithV1Client); ok { + return &logPluginProxy{pc.Client()}, nil + } pa, ok := p.(getter.PluginAddr) if !ok { - return &logPluginProxy{p.Client()}, nil + return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", p)) } if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 { diff --git a/daemon/metrics.go b/daemon/metrics.go index 4bf4310cda..f6961a3553 100644 --- a/daemon/metrics.go +++ b/daemon/metrics.go @@ -3,6 +3,7 @@ package daemon // import "github.com/docker/docker/daemon" import ( "sync" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/pkg/plugins" "github.com/docker/go-metrics" @@ -142,11 +143,16 @@ type metricsPlugin interface { StopMetrics() error } -func makePluginAdapter(p plugingetter.CompatPlugin) (metricsPlugin, error) { +func makePluginAdapter(p plugingetter.CompatPlugin) (metricsPlugin, error) { // nolint: interfacer + if pc, ok := p.(plugingetter.PluginWithV1Client); ok { + return &metricsPluginAdapter{pc.Client(), p.Name()}, nil + } + pa, ok := p.(plugingetter.PluginAddr) if !ok { - return &metricsPluginAdapter{p.Client(), p.Name()}, nil + return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", p)) } + if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 { return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol()) } diff --git a/pkg/plugingetter/getter.go b/pkg/plugingetter/getter.go index 031b5049c2..370e0d5b97 100644 --- a/pkg/plugingetter/getter.go +++ b/pkg/plugingetter/getter.go @@ -18,15 +18,19 @@ const ( // CompatPlugin is an abstraction to handle both v2(new) and v1(legacy) plugins. type CompatPlugin interface { - Client() *plugins.Client Name() string ScopedPath(string) string IsV1() bool + PluginWithV1Client +} + +// PluginWithV1Client is a plugin that directly utilizes the v1/http plugin client +type PluginWithV1Client interface { + Client() *plugins.Client } // PluginAddr is a plugin that exposes the socket address for creating custom clients rather than the built-in `*plugins.Client` type PluginAddr interface { - CompatPlugin Addr() net.Addr Timeout() time.Duration Protocol() string diff --git a/volume/drivers/extpoint.go b/volume/drivers/extpoint.go index f7d3617caa..5a3c4ce95a 100644 --- a/volume/drivers/extpoint.go +++ b/volume/drivers/extpoint.go @@ -212,9 +212,13 @@ func (s *Store) GetAllDrivers() ([]volume.Driver, error) { } func makePluginAdapter(p getter.CompatPlugin) (*volumeDriverAdapter, error) { + if pc, ok := p.(getter.PluginWithV1Client); ok { + return &volumeDriverAdapter{name: p.Name(), scopePath: p.ScopedPath, proxy: &volumeDriverProxy{pc.Client()}}, nil + } + pa, ok := p.(getter.PluginAddr) if !ok { - return &volumeDriverAdapter{name: p.Name(), scopePath: p.ScopedPath, proxy: &volumeDriverProxy{p.Client()}}, nil + return nil, errdefs.System(errors.Errorf("got unknown plugin instance %T", p)) } if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {