|
@@ -1,9 +1,15 @@
|
|
|
package testutils
|
|
|
|
|
|
import (
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
"fmt"
|
|
|
+ "net"
|
|
|
+ "net/http"
|
|
|
"time"
|
|
|
|
|
|
+ "github.com/docker/docker/pkg/plugingetter"
|
|
|
+ "github.com/docker/docker/pkg/plugins"
|
|
|
"github.com/docker/docker/volume"
|
|
|
)
|
|
|
|
|
@@ -121,3 +127,99 @@ func (d *FakeDriver) Get(name string) (volume.Volume, error) {
|
|
|
func (*FakeDriver) Scope() string {
|
|
|
return "local"
|
|
|
}
|
|
|
+
|
|
|
+type fakePlugin struct {
|
|
|
+ client *plugins.Client
|
|
|
+ name string
|
|
|
+ refs int
|
|
|
+}
|
|
|
+
|
|
|
+// MakeFakePlugin creates a fake plugin from the passed in driver
|
|
|
+// Note: currently only "Create" is implemented because that's all that's needed
|
|
|
+// so far. If you need it to test something else, add it here, but probably you
|
|
|
+// shouldn't need to use this except for very specific cases with v2 plugin handling.
|
|
|
+func MakeFakePlugin(d volume.Driver, l net.Listener) (plugingetter.CompatPlugin, error) {
|
|
|
+ c, err := plugins.NewClient(l.Addr().Network()+"://"+l.Addr().String(), nil)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ mux := http.NewServeMux()
|
|
|
+
|
|
|
+ mux.HandleFunc("/VolumeDriver.Create", func(w http.ResponseWriter, r *http.Request) {
|
|
|
+ createReq := struct {
|
|
|
+ Name string
|
|
|
+ Opts map[string]string
|
|
|
+ }{}
|
|
|
+ if err := json.NewDecoder(r.Body).Decode(&createReq); err != nil {
|
|
|
+ fmt.Fprintf(w, `{"Err": "%s"}`, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ _, err := d.Create(createReq.Name, createReq.Opts)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(w, `{"Err": "%s"}`, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ w.Write([]byte("{}"))
|
|
|
+ })
|
|
|
+
|
|
|
+ go http.Serve(l, mux)
|
|
|
+ return &fakePlugin{client: c, name: d.Name()}, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (p *fakePlugin) Client() *plugins.Client {
|
|
|
+ return p.client
|
|
|
+}
|
|
|
+
|
|
|
+func (p *fakePlugin) Name() string {
|
|
|
+ return p.name
|
|
|
+}
|
|
|
+
|
|
|
+func (p *fakePlugin) IsV1() bool {
|
|
|
+ return false
|
|
|
+}
|
|
|
+
|
|
|
+func (p *fakePlugin) BasePath() string {
|
|
|
+ return ""
|
|
|
+}
|
|
|
+
|
|
|
+type fakePluginGetter struct {
|
|
|
+ plugins map[string]plugingetter.CompatPlugin
|
|
|
+}
|
|
|
+
|
|
|
+// NewFakePluginGetter returns a plugin getter for fake plugins
|
|
|
+func NewFakePluginGetter(pls ...plugingetter.CompatPlugin) plugingetter.PluginGetter {
|
|
|
+ idx := make(map[string]plugingetter.CompatPlugin, len(pls))
|
|
|
+ for _, p := range pls {
|
|
|
+ idx[p.Name()] = p
|
|
|
+ }
|
|
|
+ return &fakePluginGetter{plugins: idx}
|
|
|
+}
|
|
|
+
|
|
|
+// This ignores the second argument since we only care about volume drivers here,
|
|
|
+// there shouldn't be any other kind of plugin in here
|
|
|
+func (g *fakePluginGetter) Get(name, _ string, mode int) (plugingetter.CompatPlugin, error) {
|
|
|
+ p, ok := g.plugins[name]
|
|
|
+ if !ok {
|
|
|
+ return nil, errors.New("not found")
|
|
|
+ }
|
|
|
+ p.(*fakePlugin).refs += mode
|
|
|
+ return p, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (g *fakePluginGetter) GetAllByCap(capability string) ([]plugingetter.CompatPlugin, error) {
|
|
|
+ panic("GetAllByCap shouldn't be called")
|
|
|
+}
|
|
|
+
|
|
|
+func (g *fakePluginGetter) GetAllManagedPluginsByCap(capability string) []plugingetter.CompatPlugin {
|
|
|
+ panic("GetAllManagedPluginsByCap should not be called")
|
|
|
+}
|
|
|
+
|
|
|
+func (g *fakePluginGetter) Handle(capability string, callback func(string, *plugins.Client)) {
|
|
|
+ panic("Handle should not be called")
|
|
|
+}
|
|
|
+
|
|
|
+// FakeRefs checks ref count on a fake plugin.
|
|
|
+func FakeRefs(p plugingetter.CompatPlugin) int {
|
|
|
+ // this should panic if something other than a `*fakePlugin` is passed in
|
|
|
+ return p.(*fakePlugin).refs
|
|
|
+}
|