123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- package testutils // import "github.com/docker/docker/volume/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"
- )
- // NoopVolume is a volume that doesn't perform any operation
- type NoopVolume struct{}
- // Name is the name of the volume
- func (NoopVolume) Name() string { return "noop" }
- // DriverName is the name of the driver
- func (NoopVolume) DriverName() string { return "noop" }
- // Path is the filesystem path to the volume
- func (NoopVolume) Path() string { return "noop" }
- // Mount mounts the volume in the container
- func (NoopVolume) Mount(_ string) (string, error) { return "noop", nil }
- // Unmount unmounts the volume from the container
- func (NoopVolume) Unmount(_ string) error { return nil }
- // Status provides low-level details about the volume
- func (NoopVolume) Status() map[string]interface{} { return nil }
- // CreatedAt provides the time the volume (directory) was created at
- func (NoopVolume) CreatedAt() (time.Time, error) { return time.Now(), nil }
- // FakeVolume is a fake volume with a random name
- type FakeVolume struct {
- name string
- driverName string
- createdAt time.Time
- }
- // NewFakeVolume creates a new fake volume for testing
- func NewFakeVolume(name string, driverName string) volume.Volume {
- return FakeVolume{name: name, driverName: driverName, createdAt: time.Now()}
- }
- // Name is the name of the volume
- func (f FakeVolume) Name() string { return f.name }
- // DriverName is the name of the driver
- func (f FakeVolume) DriverName() string { return f.driverName }
- // Path is the filesystem path to the volume
- func (FakeVolume) Path() string { return "fake" }
- // Mount mounts the volume in the container
- func (FakeVolume) Mount(_ string) (string, error) { return "fake", nil }
- // Unmount unmounts the volume from the container
- func (FakeVolume) Unmount(_ string) error { return nil }
- // Status provides low-level details about the volume
- func (FakeVolume) Status() map[string]interface{} {
- return map[string]interface{}{"datakey": "datavalue"}
- }
- // CreatedAt provides the time the volume (directory) was created at
- func (f FakeVolume) CreatedAt() (time.Time, error) {
- return f.createdAt, nil
- }
- // FakeDriver is a driver that generates fake volumes
- type FakeDriver struct {
- name string
- vols map[string]volume.Volume
- }
- // NewFakeDriver creates a new FakeDriver with the specified name
- func NewFakeDriver(name string) volume.Driver {
- return &FakeDriver{
- name: name,
- vols: make(map[string]volume.Volume),
- }
- }
- // Name is the name of the driver
- func (d *FakeDriver) Name() string { return d.name }
- // Create initializes a fake volume.
- // It returns an error if the options include an "error" key with a message
- func (d *FakeDriver) Create(name string, opts map[string]string) (volume.Volume, error) {
- if opts != nil && opts["error"] != "" {
- return nil, fmt.Errorf(opts["error"])
- }
- v := NewFakeVolume(name, d.name)
- d.vols[name] = v
- return v, nil
- }
- // Remove deletes a volume.
- func (d *FakeDriver) Remove(v volume.Volume) error {
- if _, exists := d.vols[v.Name()]; !exists {
- return fmt.Errorf("no such volume")
- }
- delete(d.vols, v.Name())
- return nil
- }
- // List lists the volumes
- func (d *FakeDriver) List() ([]volume.Volume, error) {
- var vols []volume.Volume
- for _, v := range d.vols {
- vols = append(vols, v)
- }
- return vols, nil
- }
- // Get gets the volume
- func (d *FakeDriver) Get(name string) (volume.Volume, error) {
- if v, exists := d.vols[name]; exists {
- return v, nil
- }
- return nil, fmt.Errorf("no such volume")
- }
- // Scope returns the local scope
- 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) // #nosec G114 -- Ignoring for test-code: G114: Use of net/http serve function that has no support for setting timeouts (gosec)
- 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) ScopedPath(s string) string {
- return s
- }
- 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
- }
|