Skip to content

Commit 61113e3

Browse files
committed
Adds shim layer for writing volume drivers
This allows a plugin writer to not care about the plugin API and rather focus on the volume driver API from engine. As ane example, engine's built-in `local` driver can operate as a plugin with no extra effort with this shim layer. Signed-off-by: Brian Goff <[email protected]>
1 parent 43a6e81 commit 61113e3

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

volume/shim.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package volume
2+
3+
import "github.com/docker/docker/volume"
4+
5+
type shimDriver struct {
6+
d volume.Driver
7+
}
8+
9+
// NewHandlerFromVolumeDriver creates a plugin handler from an existing volume
10+
// driver. This could be used, for instance, by the `local` volume driver built-in
11+
// to Docker Engine and it would create a plugin from it that maps plugin API calls
12+
// directly to any volume driver that satifies the volume.Driver interface from
13+
// Docker Engine.
14+
func NewHandlerFromVolumeDriver(d volume.Driver) *Handler {
15+
return NewHandler(&shimDriver{d})
16+
}
17+
18+
func (d *shimDriver) Create(req Request) Response {
19+
var res Response
20+
_, err := d.d.Create(req.Name, req.Options)
21+
if err != nil {
22+
res.Err = err.Error()
23+
}
24+
return res
25+
}
26+
27+
func (d *shimDriver) List(req Request) Response {
28+
var res Response
29+
ls, err := d.d.List()
30+
if err != nil {
31+
res.Err = err.Error()
32+
return res
33+
}
34+
vols := make([]*Volume, len(ls))
35+
36+
for _, v := range ls {
37+
vol := &Volume{
38+
Name: v.Name(),
39+
Mountpoint: v.Path(),
40+
}
41+
vols = append(vols, vol)
42+
}
43+
res.Volumes = vols
44+
return res
45+
}
46+
47+
func (d *shimDriver) Get(req Request) Response {
48+
var res Response
49+
v, err := d.d.Get(req.Name)
50+
if err != nil {
51+
res.Err = err.Error()
52+
return res
53+
}
54+
res.Volume = &Volume{
55+
Name: v.Name(),
56+
Mountpoint: v.Path(),
57+
}
58+
return res
59+
}
60+
61+
func (d *shimDriver) Remove(req Request) Response {
62+
var res Response
63+
v, err := d.d.Get(req.Name)
64+
if err != nil {
65+
res.Err = err.Error()
66+
return res
67+
}
68+
if err := d.d.Remove(v); err != nil {
69+
res.Err = err.Error()
70+
}
71+
return res
72+
}
73+
74+
func (d *shimDriver) Path(req Request) Response {
75+
var res Response
76+
v, err := d.d.Get(req.Name)
77+
if err != nil {
78+
res.Err = err.Error()
79+
return res
80+
}
81+
res.Mountpoint = v.Path()
82+
return res
83+
}
84+
85+
func (d *shimDriver) Mount(req Request) Response {
86+
var res Response
87+
v, err := d.d.Get(req.Name)
88+
if err != nil {
89+
res.Err = err.Error()
90+
return res
91+
}
92+
pth, err := v.Mount()
93+
if err != nil {
94+
res.Err = err.Error()
95+
}
96+
res.Mountpoint = pth
97+
return res
98+
}
99+
100+
func (d *shimDriver) Unmount(req Request) Response {
101+
var res Response
102+
v, err := d.d.Get(req.Name)
103+
if err != nil {
104+
res.Err = err.Error()
105+
return res
106+
}
107+
if err := v.Unmount(); err != nil {
108+
res.Err = err.Error()
109+
}
110+
return res
111+
}

volume/shim_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package volume
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/docker/docker/volume"
8+
"github.com/docker/go-connections/sockets"
9+
)
10+
11+
type testVolumeDriver struct{}
12+
type testVolume struct{}
13+
14+
func (testVolume) Name() string { return "" }
15+
func (testVolume) Path() string { return "" }
16+
func (testVolume) Mount() (string, error) { return "", nil }
17+
func (testVolume) Unmount() error { return nil }
18+
func (testVolume) DriverName() string { return "" }
19+
20+
func (testVolumeDriver) Name() string { return "" }
21+
func (testVolumeDriver) Create(string, map[string]string) (volume.Volume, error) { return nil, nil }
22+
func (testVolumeDriver) Remove(volume.Volume) error { return nil }
23+
func (testVolumeDriver) List() ([]volume.Volume, error) { return nil, nil }
24+
func (testVolumeDriver) Get(name string) (volume.Volume, error) { return nil, nil }
25+
26+
func TestVolumeDriver(t *testing.T) {
27+
h := NewHandlerFromVolumeDriver(testVolumeDriver{})
28+
l := sockets.NewInmemSocket("test", 0)
29+
go h.Serve(l)
30+
defer l.Close()
31+
32+
client := &http.Client{Transport: &http.Transport{
33+
Dial: l.Dial,
34+
}}
35+
36+
resp, err := pluginRequest(client, createPath, Request{Name: "foo"})
37+
if err != nil {
38+
t.Fatal(err)
39+
}
40+
if resp.Err != "" {
41+
t.Fatalf("error while creating volume: %v", err)
42+
}
43+
}

0 commit comments

Comments
 (0)