Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -1859,6 +1859,13 @@ definitions: |
| 1859 | 1859 |
type: "string" |
| 1860 | 1860 |
x-nullable: false |
| 1861 | 1861 |
example: "plugins.sock" |
| 1862 |
+ ProtocolScheme: |
|
| 1863 |
+ type: "string" |
|
| 1864 |
+ example: "some.protocol/v1.0" |
|
| 1865 |
+ description: "Protocol to use for clients connecting to the plugin." |
|
| 1866 |
+ enum: |
|
| 1867 |
+ - "" |
|
| 1868 |
+ - "moby.plugins.http/v1" |
|
| 1862 | 1869 |
Entrypoint: |
| 1863 | 1870 |
type: "array" |
| 1864 | 1871 |
items: |
| ... | ... |
@@ -121,6 +121,9 @@ type PluginConfigArgs struct {
|
| 121 | 121 |
// swagger:model PluginConfigInterface |
| 122 | 122 |
type PluginConfigInterface struct {
|
| 123 | 123 |
|
| 124 |
+ // Protocol to use for clients connecting to the plugin. |
|
| 125 |
+ ProtocolScheme string `json:"ProtocolScheme,omitempty"` |
|
| 126 |
+ |
|
| 124 | 127 |
// socket |
| 125 | 128 |
// Required: true |
| 126 | 129 |
Socket string `json:"Socket"` |
| ... | ... |
@@ -5,7 +5,9 @@ import ( |
| 5 | 5 |
"path/filepath" |
| 6 | 6 |
|
| 7 | 7 |
"github.com/docker/docker/pkg/plugingetter" |
| 8 |
+ "github.com/docker/docker/pkg/plugins" |
|
| 8 | 9 |
"github.com/docker/docker/plugin/v2" |
| 10 |
+ "github.com/pkg/errors" |
|
| 9 | 11 |
) |
| 10 | 12 |
|
| 11 | 13 |
func lookupPlugin(name string, pg plugingetter.PluginGetter, config Options) (Driver, error) {
|
| ... | ... |
@@ -28,6 +30,22 @@ func newPluginDriver(name string, pl plugingetter.CompatPlugin, config Options) |
| 28 | 28 |
} |
| 29 | 29 |
} |
| 30 | 30 |
} |
| 31 |
- proxy := &graphDriverProxy{name, pl, Capabilities{}}
|
|
| 31 |
+ |
|
| 32 |
+ var proxy *graphDriverProxy |
|
| 33 |
+ |
|
| 34 |
+ pa, ok := pl.(plugingetter.PluginAddr) |
|
| 35 |
+ if !ok {
|
|
| 36 |
+ proxy = &graphDriverProxy{name, pl, Capabilities{}, pl.Client()}
|
|
| 37 |
+ } else {
|
|
| 38 |
+ if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
|
|
| 39 |
+ return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol())
|
|
| 40 |
+ } |
|
| 41 |
+ addr := pa.Addr() |
|
| 42 |
+ client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout()) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ return nil, errors.Wrap(err, "error creating plugin client") |
|
| 45 |
+ } |
|
| 46 |
+ proxy = &graphDriverProxy{name, pl, Capabilities{}, client}
|
|
| 47 |
+ } |
|
| 32 | 48 |
return proxy, proxy.Init(filepath.Join(home, name), config.DriverOptions, config.UIDMaps, config.GIDMaps) |
| 33 | 49 |
} |
| ... | ... |
@@ -13,9 +13,10 @@ import ( |
| 13 | 13 |
) |
| 14 | 14 |
|
| 15 | 15 |
type graphDriverProxy struct {
|
| 16 |
- name string |
|
| 17 |
- p plugingetter.CompatPlugin |
|
| 18 |
- caps Capabilities |
|
| 16 |
+ name string |
|
| 17 |
+ p plugingetter.CompatPlugin |
|
| 18 |
+ caps Capabilities |
|
| 19 |
+ client *plugins.Client |
|
| 19 | 20 |
} |
| 20 | 21 |
|
| 21 | 22 |
type graphDriverRequest struct {
|
| ... | ... |
@@ -57,7 +58,7 @@ func (d *graphDriverProxy) Init(home string, opts []string, uidMaps, gidMaps []i |
| 57 | 57 |
GIDMaps: gidMaps, |
| 58 | 58 |
} |
| 59 | 59 |
var ret graphDriverResponse |
| 60 |
- if err := d.p.Client().Call("GraphDriver.Init", args, &ret); err != nil {
|
|
| 60 |
+ if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil {
|
|
| 61 | 61 |
return err |
| 62 | 62 |
} |
| 63 | 63 |
if ret.Err != "" {
|
| ... | ... |
@@ -74,7 +75,7 @@ func (d *graphDriverProxy) Init(home string, opts []string, uidMaps, gidMaps []i |
| 74 | 74 |
func (d *graphDriverProxy) fetchCaps() (Capabilities, error) {
|
| 75 | 75 |
args := &graphDriverRequest{}
|
| 76 | 76 |
var ret graphDriverResponse |
| 77 |
- if err := d.p.Client().Call("GraphDriver.Capabilities", args, &ret); err != nil {
|
|
| 77 |
+ if err := d.client.Call("GraphDriver.Capabilities", args, &ret); err != nil {
|
|
| 78 | 78 |
if !plugins.IsNotFound(err) {
|
| 79 | 79 |
return Capabilities{}, err
|
| 80 | 80 |
} |
| ... | ... |
@@ -108,7 +109,7 @@ func (d *graphDriverProxy) create(method, id, parent string, opts *CreateOpts) e |
| 108 | 108 |
args.StorageOpt = opts.StorageOpt |
| 109 | 109 |
} |
| 110 | 110 |
var ret graphDriverResponse |
| 111 |
- if err := d.p.Client().Call(method, args, &ret); err != nil {
|
|
| 111 |
+ if err := d.client.Call(method, args, &ret); err != nil {
|
|
| 112 | 112 |
return err |
| 113 | 113 |
} |
| 114 | 114 |
if ret.Err != "" {
|
| ... | ... |
@@ -120,7 +121,7 @@ func (d *graphDriverProxy) create(method, id, parent string, opts *CreateOpts) e |
| 120 | 120 |
func (d *graphDriverProxy) Remove(id string) error {
|
| 121 | 121 |
args := &graphDriverRequest{ID: id}
|
| 122 | 122 |
var ret graphDriverResponse |
| 123 |
- if err := d.p.Client().Call("GraphDriver.Remove", args, &ret); err != nil {
|
|
| 123 |
+ if err := d.client.Call("GraphDriver.Remove", args, &ret); err != nil {
|
|
| 124 | 124 |
return err |
| 125 | 125 |
} |
| 126 | 126 |
if ret.Err != "" {
|
| ... | ... |
@@ -135,7 +136,7 @@ func (d *graphDriverProxy) Get(id, mountLabel string) (containerfs.ContainerFS, |
| 135 | 135 |
MountLabel: mountLabel, |
| 136 | 136 |
} |
| 137 | 137 |
var ret graphDriverResponse |
| 138 |
- if err := d.p.Client().Call("GraphDriver.Get", args, &ret); err != nil {
|
|
| 138 |
+ if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil {
|
|
| 139 | 139 |
return nil, err |
| 140 | 140 |
} |
| 141 | 141 |
var err error |
| ... | ... |
@@ -148,7 +149,7 @@ func (d *graphDriverProxy) Get(id, mountLabel string) (containerfs.ContainerFS, |
| 148 | 148 |
func (d *graphDriverProxy) Put(id string) error {
|
| 149 | 149 |
args := &graphDriverRequest{ID: id}
|
| 150 | 150 |
var ret graphDriverResponse |
| 151 |
- if err := d.p.Client().Call("GraphDriver.Put", args, &ret); err != nil {
|
|
| 151 |
+ if err := d.client.Call("GraphDriver.Put", args, &ret); err != nil {
|
|
| 152 | 152 |
return err |
| 153 | 153 |
} |
| 154 | 154 |
if ret.Err != "" {
|
| ... | ... |
@@ -160,7 +161,7 @@ func (d *graphDriverProxy) Put(id string) error {
|
| 160 | 160 |
func (d *graphDriverProxy) Exists(id string) bool {
|
| 161 | 161 |
args := &graphDriverRequest{ID: id}
|
| 162 | 162 |
var ret graphDriverResponse |
| 163 |
- if err := d.p.Client().Call("GraphDriver.Exists", args, &ret); err != nil {
|
|
| 163 |
+ if err := d.client.Call("GraphDriver.Exists", args, &ret); err != nil {
|
|
| 164 | 164 |
return false |
| 165 | 165 |
} |
| 166 | 166 |
return ret.Exists |
| ... | ... |
@@ -169,7 +170,7 @@ func (d *graphDriverProxy) Exists(id string) bool {
|
| 169 | 169 |
func (d *graphDriverProxy) Status() [][2]string {
|
| 170 | 170 |
args := &graphDriverRequest{}
|
| 171 | 171 |
var ret graphDriverResponse |
| 172 |
- if err := d.p.Client().Call("GraphDriver.Status", args, &ret); err != nil {
|
|
| 172 |
+ if err := d.client.Call("GraphDriver.Status", args, &ret); err != nil {
|
|
| 173 | 173 |
return nil |
| 174 | 174 |
} |
| 175 | 175 |
return ret.Status |
| ... | ... |
@@ -180,7 +181,7 @@ func (d *graphDriverProxy) GetMetadata(id string) (map[string]string, error) {
|
| 180 | 180 |
ID: id, |
| 181 | 181 |
} |
| 182 | 182 |
var ret graphDriverResponse |
| 183 |
- if err := d.p.Client().Call("GraphDriver.GetMetadata", args, &ret); err != nil {
|
|
| 183 |
+ if err := d.client.Call("GraphDriver.GetMetadata", args, &ret); err != nil {
|
|
| 184 | 184 |
return nil, err |
| 185 | 185 |
} |
| 186 | 186 |
if ret.Err != "" {
|
| ... | ... |
@@ -199,7 +200,7 @@ func (d *graphDriverProxy) Cleanup() error {
|
| 199 | 199 |
|
| 200 | 200 |
args := &graphDriverRequest{}
|
| 201 | 201 |
var ret graphDriverResponse |
| 202 |
- if err := d.p.Client().Call("GraphDriver.Cleanup", args, &ret); err != nil {
|
|
| 202 |
+ if err := d.client.Call("GraphDriver.Cleanup", args, &ret); err != nil {
|
|
| 203 | 203 |
return nil |
| 204 | 204 |
} |
| 205 | 205 |
if ret.Err != "" {
|
| ... | ... |
@@ -213,7 +214,7 @@ func (d *graphDriverProxy) Diff(id, parent string) (io.ReadCloser, error) {
|
| 213 | 213 |
ID: id, |
| 214 | 214 |
Parent: parent, |
| 215 | 215 |
} |
| 216 |
- body, err := d.p.Client().Stream("GraphDriver.Diff", args)
|
|
| 216 |
+ body, err := d.client.Stream("GraphDriver.Diff", args)
|
|
| 217 | 217 |
if err != nil {
|
| 218 | 218 |
return nil, err |
| 219 | 219 |
} |
| ... | ... |
@@ -226,7 +227,7 @@ func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error) |
| 226 | 226 |
Parent: parent, |
| 227 | 227 |
} |
| 228 | 228 |
var ret graphDriverResponse |
| 229 |
- if err := d.p.Client().Call("GraphDriver.Changes", args, &ret); err != nil {
|
|
| 229 |
+ if err := d.client.Call("GraphDriver.Changes", args, &ret); err != nil {
|
|
| 230 | 230 |
return nil, err |
| 231 | 231 |
} |
| 232 | 232 |
if ret.Err != "" {
|
| ... | ... |
@@ -238,7 +239,7 @@ func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error) |
| 238 | 238 |
|
| 239 | 239 |
func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) {
|
| 240 | 240 |
var ret graphDriverResponse |
| 241 |
- if err := d.p.Client().SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
|
|
| 241 |
+ if err := d.client.SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
|
|
| 242 | 242 |
return -1, err |
| 243 | 243 |
} |
| 244 | 244 |
if ret.Err != "" {
|
| ... | ... |
@@ -253,7 +254,7 @@ func (d *graphDriverProxy) DiffSize(id, parent string) (int64, error) {
|
| 253 | 253 |
Parent: parent, |
| 254 | 254 |
} |
| 255 | 255 |
var ret graphDriverResponse |
| 256 |
- if err := d.p.Client().Call("GraphDriver.DiffSize", args, &ret); err != nil {
|
|
| 256 |
+ if err := d.client.Call("GraphDriver.DiffSize", args, &ret); err != nil {
|
|
| 257 | 257 |
return -1, err |
| 258 | 258 |
} |
| 259 | 259 |
if ret.Err != "" {
|
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/docker/api/types/plugins/logdriver" |
| 10 | 10 |
getter "github.com/docker/docker/pkg/plugingetter" |
| 11 |
+ "github.com/docker/docker/pkg/plugins" |
|
| 11 | 12 |
"github.com/docker/docker/pkg/stringid" |
| 12 | 13 |
"github.com/pkg/errors" |
| 13 | 14 |
) |
| ... | ... |
@@ -37,11 +38,32 @@ func getPlugin(name string, mode int) (Creator, error) {
|
| 37 | 37 |
return nil, fmt.Errorf("error looking up logging plugin %s: %v", name, err)
|
| 38 | 38 |
} |
| 39 | 39 |
|
| 40 |
- d := &logPluginProxy{p.Client()}
|
|
| 41 |
- return makePluginCreator(name, d, p.ScopedPath), nil |
|
| 40 |
+ client, err := makePluginClient(p) |
|
| 41 |
+ if err != nil {
|
|
| 42 |
+ return nil, err |
|
| 43 |
+ } |
|
| 44 |
+ return makePluginCreator(name, client, p.ScopedPath), nil |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func makePluginClient(p getter.CompatPlugin) (logPlugin, error) {
|
|
| 48 |
+ pa, ok := p.(getter.PluginAddr) |
|
| 49 |
+ if !ok {
|
|
| 50 |
+ return &logPluginProxy{p.Client()}, nil
|
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
|
|
| 54 |
+ return nil, errors.Errorf("plugin protocol not supported: %s", p)
|
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ addr := pa.Addr() |
|
| 58 |
+ c, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout()) |
|
| 59 |
+ if err != nil {
|
|
| 60 |
+ return nil, errors.Wrap(err, "error making plugin client") |
|
| 61 |
+ } |
|
| 62 |
+ return &logPluginProxy{c}, nil
|
|
| 42 | 63 |
} |
| 43 | 64 |
|
| 44 |
-func makePluginCreator(name string, l *logPluginProxy, scopePath func(s string) string) Creator {
|
|
| 65 |
+func makePluginCreator(name string, l logPlugin, scopePath func(s string) string) Creator {
|
|
| 45 | 66 |
return func(logCtx Info) (logger Logger, err error) {
|
| 46 | 67 |
defer func() {
|
| 47 | 68 |
if err != nil {
|
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"sync" |
| 5 | 5 |
|
| 6 | 6 |
"github.com/docker/docker/pkg/plugingetter" |
| 7 |
+ "github.com/docker/docker/pkg/plugins" |
|
| 7 | 8 |
"github.com/docker/go-metrics" |
| 8 | 9 |
"github.com/pkg/errors" |
| 9 | 10 |
"github.com/prometheus/client_golang/prometheus" |
| ... | ... |
@@ -118,7 +119,15 @@ func (d *Daemon) cleanupMetricsPlugins() {
|
| 118 | 118 |
p := plugin |
| 119 | 119 |
go func() {
|
| 120 | 120 |
defer wg.Done() |
| 121 |
- pluginStopMetricsCollection(p) |
|
| 121 |
+ |
|
| 122 |
+ adapter, err := makePluginAdapter(p) |
|
| 123 |
+ if err != nil {
|
|
| 124 |
+ logrus.WithError(err).WithField("plugin", p.Name()).Error("Error creating metrics plugin adapater")
|
|
| 125 |
+ return |
|
| 126 |
+ } |
|
| 127 |
+ if err := adapter.StopMetrics(); err != nil {
|
|
| 128 |
+ logrus.WithError(err).WithField("plugin", p.Name()).Error("Error stopping plugin metrics collection")
|
|
| 129 |
+ } |
|
| 122 | 130 |
}() |
| 123 | 131 |
} |
| 124 | 132 |
wg.Wait() |
| ... | ... |
@@ -128,12 +137,39 @@ func (d *Daemon) cleanupMetricsPlugins() {
|
| 128 | 128 |
} |
| 129 | 129 |
} |
| 130 | 130 |
|
| 131 |
-func pluginStartMetricsCollection(p plugingetter.CompatPlugin) error {
|
|
| 131 |
+type metricsPlugin interface {
|
|
| 132 |
+ StartMetrics() error |
|
| 133 |
+ StopMetrics() error |
|
| 134 |
+} |
|
| 135 |
+ |
|
| 136 |
+func makePluginAdapter(p plugingetter.CompatPlugin) (metricsPlugin, error) {
|
|
| 137 |
+ pa, ok := p.(plugingetter.PluginAddr) |
|
| 138 |
+ if !ok {
|
|
| 139 |
+ return &metricsPluginAdapter{p.Client(), p.Name()}, nil
|
|
| 140 |
+ } |
|
| 141 |
+ if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
|
|
| 142 |
+ return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol())
|
|
| 143 |
+ } |
|
| 144 |
+ |
|
| 145 |
+ addr := pa.Addr() |
|
| 146 |
+ client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout()) |
|
| 147 |
+ if err != nil {
|
|
| 148 |
+ return nil, errors.Wrap(err, "error creating metrics plugin client") |
|
| 149 |
+ } |
|
| 150 |
+ return &metricsPluginAdapter{client, p.Name()}, nil
|
|
| 151 |
+} |
|
| 152 |
+ |
|
| 153 |
+type metricsPluginAdapter struct {
|
|
| 154 |
+ c *plugins.Client |
|
| 155 |
+ name string |
|
| 156 |
+} |
|
| 157 |
+ |
|
| 158 |
+func (a *metricsPluginAdapter) StartMetrics() error {
|
|
| 132 | 159 |
type metricsPluginResponse struct {
|
| 133 | 160 |
Err string |
| 134 | 161 |
} |
| 135 | 162 |
var res metricsPluginResponse |
| 136 |
- if err := p.Client().Call(metricsPluginType+".StartMetrics", nil, &res); err != nil {
|
|
| 163 |
+ if err := a.c.Call(metricsPluginType+".StartMetrics", nil, &res); err != nil {
|
|
| 137 | 164 |
return errors.Wrap(err, "could not start metrics plugin") |
| 138 | 165 |
} |
| 139 | 166 |
if res.Err != "" {
|
| ... | ... |
@@ -142,8 +178,9 @@ func pluginStartMetricsCollection(p plugingetter.CompatPlugin) error {
|
| 142 | 142 |
return nil |
| 143 | 143 |
} |
| 144 | 144 |
|
| 145 |
-func pluginStopMetricsCollection(p plugingetter.CompatPlugin) {
|
|
| 146 |
- if err := p.Client().Call(metricsPluginType+".StopMetrics", nil, nil); err != nil {
|
|
| 147 |
- logrus.WithError(err).WithField("name", p.Name()).Error("error stopping metrics collector")
|
|
| 145 |
+func (a *metricsPluginAdapter) StopMetrics() error {
|
|
| 146 |
+ if err := a.c.Call(metricsPluginType+".StopMetrics", nil, nil); err != nil {
|
|
| 147 |
+ return errors.Wrap(err, "error stopping metrics collector") |
|
| 148 | 148 |
} |
| 149 |
+ return nil |
|
| 149 | 150 |
} |
| ... | ... |
@@ -49,8 +49,12 @@ func registerMetricsPluginCallback(store *plugin.Store, sockPath string) {
|
| 49 | 49 |
return |
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 |
- if err := pluginStartMetricsCollection(p); err != nil {
|
|
| 53 |
- logrus.WithError(err).WithField("name", name).Error("error while initializing metrics plugin")
|
|
| 52 |
+ adapter, err := makePluginAdapter(p) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ logrus.WithError(err).WithField("plugin", p.Name()).Error("Error creating plugin adapater")
|
|
| 55 |
+ } |
|
| 56 |
+ if err := adapter.StartMetrics(); err != nil {
|
|
| 57 |
+ logrus.WithError(err).WithField("plugin", p.Name()).Error("Error starting metrics collector plugin")
|
|
| 54 | 58 |
} |
| 55 | 59 |
}) |
| 56 | 60 |
} |
| ... | ... |
@@ -1,6 +1,9 @@ |
| 1 | 1 |
package plugingetter // import "github.com/docker/docker/pkg/plugingetter" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "net" |
|
| 5 |
+ "time" |
|
| 6 |
+ |
|
| 4 | 7 |
"github.com/docker/docker/pkg/plugins" |
| 5 | 8 |
) |
| 6 | 9 |
|
| ... | ... |
@@ -21,6 +24,14 @@ type CompatPlugin interface {
|
| 21 | 21 |
IsV1() bool |
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 |
+// PluginAddr is a plugin that exposes the socket address for creating custom clients rather than the built-in `*plugins.Client` |
|
| 25 |
+type PluginAddr interface {
|
|
| 26 |
+ CompatPlugin |
|
| 27 |
+ Addr() net.Addr |
|
| 28 |
+ Timeout() time.Duration |
|
| 29 |
+ Protocol() string |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 24 | 32 |
// CountedPlugin is a plugin which is reference counted. |
| 25 | 33 |
type CountedPlugin interface {
|
| 26 | 34 |
Acquire() |
| ... | ... |
@@ -31,6 +31,9 @@ import ( |
| 31 | 31 |
"github.com/sirupsen/logrus" |
| 32 | 32 |
) |
| 33 | 33 |
|
| 34 |
+// ProtocolSchemeHTTPV1 is the name of the protocol used for interacting with plugins using this package. |
|
| 35 |
+const ProtocolSchemeHTTPV1 = "moby.plugins.http/v1" |
|
| 36 |
+ |
|
| 34 | 37 |
var ( |
| 35 | 38 |
// ErrNotImplements is returned if the plugin does not implement the requested driver. |
| 36 | 39 |
ErrNotImplements = errors.New("Plugin does not implement the requested driver")
|
| ... | ... |
@@ -88,6 +91,11 @@ func (p *Plugin) Client() *Client {
|
| 88 | 88 |
return p.client |
| 89 | 89 |
} |
| 90 | 90 |
|
| 91 |
+// Protocol returns the protocol name/version used for plugins in this package. |
|
| 92 |
+func (p *Plugin) Protocol() string {
|
|
| 93 |
+ return ProtocolSchemeHTTPV1 |
|
| 94 |
+} |
|
| 95 |
+ |
|
| 91 | 96 |
// IsV1 returns true for V1 plugins and false otherwise. |
| 92 | 97 |
func (p *Plugin) IsV1() bool {
|
| 93 | 98 |
return true |
| ... | ... |
@@ -71,14 +71,20 @@ func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error {
|
| 71 | 71 |
|
| 72 | 72 |
func (pm *Manager) pluginPostStart(p *v2.Plugin, c *controller) error {
|
| 73 | 73 |
sockAddr := filepath.Join(pm.config.ExecRoot, p.GetID(), p.GetSocket()) |
| 74 |
- client, err := plugins.NewClientWithTimeout("unix://"+sockAddr, nil, time.Duration(c.timeoutInSecs)*time.Second)
|
|
| 75 |
- if err != nil {
|
|
| 76 |
- c.restart = false |
|
| 77 |
- shutdownPlugin(p, c, pm.executor) |
|
| 78 |
- return errors.WithStack(err) |
|
| 79 |
- } |
|
| 74 |
+ p.SetTimeout(time.Duration(c.timeoutInSecs) * time.Second) |
|
| 75 |
+ addr := &net.UnixAddr{Net: "unix", Name: sockAddr}
|
|
| 76 |
+ p.SetAddr(addr) |
|
| 80 | 77 |
|
| 81 |
- p.SetPClient(client) |
|
| 78 |
+ if p.Protocol() == plugins.ProtocolSchemeHTTPV1 {
|
|
| 79 |
+ client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, p.Timeout()) |
|
| 80 |
+ if err != nil {
|
|
| 81 |
+ c.restart = false |
|
| 82 |
+ shutdownPlugin(p, c, pm.executor) |
|
| 83 |
+ return errors.WithStack(err) |
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ p.SetPClient(client) |
|
| 87 |
+ } |
|
| 82 | 88 |
|
| 83 | 89 |
// Initial sleep before net Dial to allow plugin to listen on socket. |
| 84 | 90 |
time.Sleep(500 * time.Millisecond) |
| ... | ... |
@@ -2,9 +2,11 @@ package v2 // import "github.com/docker/docker/plugin/v2" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
+ "net" |
|
| 5 | 6 |
"path/filepath" |
| 6 | 7 |
"strings" |
| 7 | 8 |
"sync" |
| 9 |
+ "time" |
|
| 8 | 10 |
|
| 9 | 11 |
"github.com/docker/docker/api/types" |
| 10 | 12 |
"github.com/docker/docker/pkg/plugingetter" |
| ... | ... |
@@ -27,6 +29,8 @@ type Plugin struct {
|
| 27 | 27 |
modifyRuntimeSpec func(*specs.Spec) |
| 28 | 28 |
|
| 29 | 29 |
SwarmServiceID string |
| 30 |
+ timeout time.Duration |
|
| 31 |
+ addr net.Addr |
|
| 30 | 32 |
} |
| 31 | 33 |
|
| 32 | 34 |
const defaultPluginRuntimeDestination = "/run/docker/plugins" |
| ... | ... |
@@ -50,6 +54,7 @@ func (p *Plugin) ScopedPath(s string) string {
|
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 | 52 |
// Client returns the plugin client. |
| 53 |
+// Deprecated: use p.Addr() and manually create the client |
|
| 53 | 54 |
func (p *Plugin) Client() *plugins.Client {
|
| 54 | 55 |
p.mu.RLock() |
| 55 | 56 |
defer p.mu.RUnlock() |
| ... | ... |
@@ -58,6 +63,7 @@ func (p *Plugin) Client() *plugins.Client {
|
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 | 60 |
// SetPClient set the plugin client. |
| 61 |
+// Deprecated: Hardcoded plugin client is deprecated |
|
| 61 | 62 |
func (p *Plugin) SetPClient(client *plugins.Client) {
|
| 62 | 63 |
p.mu.Lock() |
| 63 | 64 |
defer p.mu.Unlock() |
| ... | ... |
@@ -264,3 +270,42 @@ func (p *Plugin) SetSpecOptModifier(f func(*specs.Spec)) {
|
| 264 | 264 |
p.modifyRuntimeSpec = f |
| 265 | 265 |
p.mu.Unlock() |
| 266 | 266 |
} |
| 267 |
+ |
|
| 268 |
+// Timeout gets the currently configured connection timeout. |
|
| 269 |
+// This should be used when dialing the plugin. |
|
| 270 |
+func (p *Plugin) Timeout() time.Duration {
|
|
| 271 |
+ p.mu.RLock() |
|
| 272 |
+ t := p.timeout |
|
| 273 |
+ p.mu.RUnlock() |
|
| 274 |
+ return t |
|
| 275 |
+} |
|
| 276 |
+ |
|
| 277 |
+// SetTimeout sets the timeout to use for dialing. |
|
| 278 |
+func (p *Plugin) SetTimeout(t time.Duration) {
|
|
| 279 |
+ p.mu.Lock() |
|
| 280 |
+ p.timeout = t |
|
| 281 |
+ p.mu.Unlock() |
|
| 282 |
+} |
|
| 283 |
+ |
|
| 284 |
+// Addr returns the net.Addr to use to connect to the plugin socket |
|
| 285 |
+func (p *Plugin) Addr() net.Addr {
|
|
| 286 |
+ p.mu.RLock() |
|
| 287 |
+ addr := p.addr |
|
| 288 |
+ p.mu.RUnlock() |
|
| 289 |
+ return addr |
|
| 290 |
+} |
|
| 291 |
+ |
|
| 292 |
+// SetAddr sets the plugin address which can be used for dialing the plugin. |
|
| 293 |
+func (p *Plugin) SetAddr(addr net.Addr) {
|
|
| 294 |
+ p.mu.Lock() |
|
| 295 |
+ p.addr = addr |
|
| 296 |
+ p.mu.Unlock() |
|
| 297 |
+} |
|
| 298 |
+ |
|
| 299 |
+// Protocol is the protocol that should be used for interacting with the plugin. |
|
| 300 |
+func (p *Plugin) Protocol() string {
|
|
| 301 |
+ if p.PluginObj.Config.Interface.ProtocolScheme != "" {
|
|
| 302 |
+ return p.PluginObj.Config.Interface.ProtocolScheme |
|
| 303 |
+ } |
|
| 304 |
+ return plugins.ProtocolSchemeHTTPV1 |
|
| 305 |
+} |
| ... | ... |
@@ -5,7 +5,7 @@ package v2 // import "github.com/docker/docker/plugin/v2" |
| 5 | 5 |
import ( |
| 6 | 6 |
"errors" |
| 7 | 7 |
|
| 8 |
- specs "github.com/opencontainers/runtime-spec/specs-go" |
|
| 8 |
+ "github.com/opencontainers/runtime-spec/specs-go" |
|
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// InitSpec creates an OCI spec from the plugin's config. |
| ... | ... |
@@ -17,7 +17,7 @@ type volumeDriverAdapter struct {
|
| 17 | 17 |
name string |
| 18 | 18 |
scopePath func(s string) string |
| 19 | 19 |
capabilities *volume.Capability |
| 20 |
- proxy *volumeDriverProxy |
|
| 20 |
+ proxy volumeDriver |
|
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 | 23 |
func (a *volumeDriverAdapter) Name() string {
|
| ... | ... |
@@ -114,7 +114,7 @@ func (a *volumeDriverAdapter) getCapabilities() volume.Capability {
|
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 | 116 |
type volumeAdapter struct {
|
| 117 |
- proxy *volumeDriverProxy |
|
| 117 |
+ proxy volumeDriver |
|
| 118 | 118 |
name string |
| 119 | 119 |
scopePath func(string) string |
| 120 | 120 |
driverName string |
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/errdefs" |
| 11 | 11 |
"github.com/docker/docker/pkg/locker" |
| 12 | 12 |
getter "github.com/docker/docker/pkg/plugingetter" |
| 13 |
+ "github.com/docker/docker/pkg/plugins" |
|
| 13 | 14 |
"github.com/docker/docker/volume" |
| 14 | 15 |
"github.com/pkg/errors" |
| 15 | 16 |
"github.com/sirupsen/logrus" |
| ... | ... |
@@ -17,12 +18,6 @@ import ( |
| 17 | 17 |
|
| 18 | 18 |
const extName = "VolumeDriver" |
| 19 | 19 |
|
| 20 |
-// NewVolumeDriver returns a driver has the given name mapped on the given client. |
|
| 21 |
-func NewVolumeDriver(name string, scopePath func(string) string, c client) volume.Driver {
|
|
| 22 |
- proxy := &volumeDriverProxy{c}
|
|
| 23 |
- return &volumeDriverAdapter{name: name, scopePath: scopePath, proxy: proxy}
|
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 | 20 |
// volumeDriver defines the available functions that volume plugins must implement. |
| 27 | 21 |
// This interface is only defined to generate the proxy objects. |
| 28 | 22 |
// It's not intended to be public or reused. |
| ... | ... |
@@ -93,7 +88,10 @@ func (s *Store) lookup(name string, mode int) (volume.Driver, error) {
|
| 93 | 93 |
return nil, errors.Wrap(err, "error looking up volume plugin "+name) |
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 |
- d := NewVolumeDriver(p.Name(), p.ScopedPath, p.Client()) |
|
| 96 |
+ d, err := makePluginAdapter(p) |
|
| 97 |
+ if err != nil {
|
|
| 98 |
+ return nil, errors.Wrap(err, "error making plugin client") |
|
| 99 |
+ } |
|
| 97 | 100 |
if err := validateDriver(d); err != nil {
|
| 98 | 101 |
if mode > 0 {
|
| 99 | 102 |
// Undo any reference count changes from the initial `Get` |
| ... | ... |
@@ -201,7 +199,10 @@ func (s *Store) GetAllDrivers() ([]volume.Driver, error) {
|
| 201 | 201 |
continue |
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 |
- ext := NewVolumeDriver(name, p.ScopedPath, p.Client()) |
|
| 204 |
+ ext, err := makePluginAdapter(p) |
|
| 205 |
+ if err != nil {
|
|
| 206 |
+ return nil, errors.Wrap(err, "error making plugin client") |
|
| 207 |
+ } |
|
| 205 | 208 |
if p.IsV1() {
|
| 206 | 209 |
s.extensions[name] = ext |
| 207 | 210 |
} |
| ... | ... |
@@ -209,3 +210,22 @@ func (s *Store) GetAllDrivers() ([]volume.Driver, error) {
|
| 209 | 209 |
} |
| 210 | 210 |
return ds, nil |
| 211 | 211 |
} |
| 212 |
+ |
|
| 213 |
+func makePluginAdapter(p getter.CompatPlugin) (*volumeDriverAdapter, error) {
|
|
| 214 |
+ pa, ok := p.(getter.PluginAddr) |
|
| 215 |
+ if !ok {
|
|
| 216 |
+ return &volumeDriverAdapter{name: p.Name(), scopePath: p.ScopedPath, proxy: &volumeDriverProxy{p.Client()}}, nil
|
|
| 217 |
+ } |
|
| 218 |
+ |
|
| 219 |
+ if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
|
|
| 220 |
+ return nil, errors.Errorf("plugin protocol not supported: %s", p)
|
|
| 221 |
+ } |
|
| 222 |
+ |
|
| 223 |
+ addr := pa.Addr() |
|
| 224 |
+ client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout()) |
|
| 225 |
+ if err != nil {
|
|
| 226 |
+ return nil, errors.Wrap(err, "error creating plugin client") |
|
| 227 |
+ } |
|
| 228 |
+ |
|
| 229 |
+ return &volumeDriverAdapter{name: p.Name(), scopePath: p.ScopedPath, proxy: &volumeDriverProxy{client}}, nil
|
|
| 230 |
+} |