Skip to content
This repository was archived by the owner on Oct 19, 2022. It is now read-only.

Commit 02e50b3

Browse files
committed
refactor code
Signed-off-by: Victor Vieux <[email protected]>
1 parent 83cf646 commit 02e50b3

File tree

8 files changed

+361
-313
lines changed

8 files changed

+361
-313
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
2323
- sudo apt-get update
2424
- sudo apt-get -y install docker-ce
25+
install:
26+
- docker pull rastasheep/ubuntu-sshd
27+
- docker pull busybox
28+
- docker build -t sshd .travis/ssh
2529
env: TESTFILE=integration.sh
2630

2731
script:

.travis/integration.sh

Lines changed: 44 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,54 @@ set -x
55

66
TAG=test
77

8-
# before_install
9-
#curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
10-
#sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
11-
#sudo apt-get update
12-
#sudo apt-get -y install docker-ce
13-
14-
# install
15-
sudo docker pull rastasheep/ubuntu-sshd
16-
sudo docker pull busybox
17-
188
docker build -t sshd .travis/ssh
19-
#script
209

2110
# make the plugin
22-
sudo PLUGIN_TAG=$TAG make
11+
PLUGIN_TAG=$TAG make
2312
# enable the plugin
24-
sudo docker plugin enable vieux/sshfs:$TAG
13+
PLUGIN_TAG=$TAG make enable
2514
# list plugins
26-
sudo docker plugin ls
15+
docker plugin ls
2716
# start sshd
28-
sudo docker run -d -p 2222:22 sshd
29-
30-
# test1: simple
31-
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 -o password=root sshvolume
32-
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
33-
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
34-
#sudo cat /var/lib/docker/plugins/sshfs-state.json
35-
sudo docker volume rm sshvolume
36-
37-
# test2: allow_other
38-
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o allow_other -o port=2222 -o password=root sshvolume
39-
sudo docker run --rm -v sshvolume:/write -u nobody busybox sh -c "echo hello > /write/world"
17+
docker run -d -p 2222:22 sshd
18+
19+
echo "# test1: simple"
20+
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 -o password=root sshvolume
21+
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
22+
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
23+
#cat /var/lib/docker/plugins/sshfs-state.json
24+
docker volume rm sshvolume
25+
26+
echo "# test2: allow_other"
27+
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o allow_other -o port=2222 -o password=root sshvolume
28+
docker run --rm -v sshvolume:/write -u nobody busybox sh -c "echo hello > /write/world"
4029
docker run --rm -v sshvolume:/read -u nobody busybox grep -Fxq hello /read/world
41-
#sudo cat /var/lib/docker/plugins/sshfs-state.json
42-
sudo docker volume rm sshvolume
43-
44-
# test3: compression
45-
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o Ciphers=arcfour -o Compression=no -o port=2222 -o password=root sshvolume
46-
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
47-
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
48-
#sudo cat /var/lib/docker/plugins/sshfs-state.json
49-
sudo docker volume rm sshvolume
50-
51-
# test4: source
52-
sudo docker plugin disable vieux/sshfs:$TAG
53-
sudo docker plugin set vieux/sshfs:$TAG state.source=/tmp
54-
sudo docker plugin enable vieux/sshfs:$TAG
55-
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o Ciphers=arcfour -o Compression=no -o port=2222 -o password=root sshvolume
56-
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
57-
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
58-
#sudo cat /tmp/sshfs-state.json
59-
sudo docker volume rm sshvolume
60-
61-
# test5: ssh key
62-
sudo docker plugin disable vieux/sshfs:$TAG
63-
sudo docker plugin set vieux/sshfs:$TAG sshkey.source=`pwd`/.travis/ssh/
64-
sudo docker plugin enable vieux/sshfs:$TAG
65-
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 sshvolume
66-
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
67-
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
68-
#sudo cat /var/lib/docker/plugins/sshfs-state.json
69-
sudo docker volume rm sshvolume
30+
#cat /var/lib/docker/plugins/sshfs-state.json
31+
docker volume rm sshvolume
32+
33+
echo "# test3: compression"
34+
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o Ciphers=arcfour -o Compression=no -o port=2222 -o password=root sshvolume
35+
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
36+
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
37+
#cat /var/lib/docker/plugins/sshfs-state.json
38+
docker volume rm sshvolume
39+
40+
echo "# test4: source"
41+
docker plugin disable vieux/sshfs:$TAG
42+
docker plugin set vieux/sshfs:$TAG state.source=/tmp
43+
docker plugin enable vieux/sshfs:$TAG
44+
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o Ciphers=arcfour -o Compression=no -o port=2222 -o password=root sshvolume
45+
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
46+
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
47+
#cat /tmp/sshfs-state.json
48+
docker volume rm sshvolume
49+
50+
echo "# test5: ssh key"
51+
docker plugin disable vieux/sshfs:$TAG
52+
docker plugin set vieux/sshfs:$TAG sshkey.source=`pwd`/.travis/ssh/
53+
docker plugin enable vieux/sshfs:$TAG
54+
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 sshvolume
55+
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
56+
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
57+
#cat /var/lib/docker/plugins/sshfs-state.json
58+
docker volume rm sshvolume

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ create:
2525
@docker plugin create ${PLUGIN_NAME}:${PLUGIN_TAG} ./plugin
2626

2727
enable:
28-
@echo "### enable plugin ${PLUGIN_NAME}:${PLUGIN_TAG}"
28+
@echo "### enable plugin ${PLUGIN_NAME}:${PLUGIN_TAG}"
29+
@docker plugin set ${PLUGIN_NAME}:${PLUGIN_TAG} DEBUG=1
2930
@docker plugin enable ${PLUGIN_NAME}:${PLUGIN_TAG}
3031

3132
push: clean rootfs create enable

driver.go

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"sync"
7+
8+
"github.com/Sirupsen/logrus"
9+
"github.com/docker/go-plugins-helpers/volume"
10+
)
11+
12+
const socketAddress = "/run/docker/plugins/sshfs.sock"
13+
14+
type sshfsDriver struct {
15+
sync.RWMutex
16+
17+
root string
18+
statePath string
19+
volumes map[string]*sshfsVolume
20+
}
21+
22+
func newSshfsDriver(root string) (*sshfsDriver, error) {
23+
logrus.WithField("method", "new driver").Debug(root)
24+
25+
statePath := filepath.Join(root, "state", "sshfs-state.json")
26+
volumes, err := readState(statePath)
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
return &sshfsDriver{
32+
root: filepath.Join(root, "volumes"),
33+
statePath: statePath,
34+
volumes: volumes,
35+
}, nil
36+
}
37+
38+
func (d *sshfsDriver) Create(r *volume.CreateRequest) error {
39+
logrus.WithField("method", "create").Debugf("%#v", r)
40+
41+
v, err := newSshfsVolume(d.root, r.Options)
42+
if err != nil {
43+
return err
44+
}
45+
46+
d.Lock()
47+
defer d.Unlock()
48+
49+
d.volumes[r.Name] = v
50+
51+
return saveState(d.statePath, d.volumes)
52+
}
53+
54+
func (d *sshfsDriver) Remove(r *volume.RemoveRequest) error {
55+
logrus.WithField("method", "remove").Debugf("%#v", r)
56+
57+
d.Lock()
58+
defer d.Unlock()
59+
60+
v, ok := d.volumes[r.Name]
61+
if !ok {
62+
return logError("volume %s not found", r.Name)
63+
}
64+
65+
if v.connections != 0 {
66+
return logError("volume %s is currently used by a container", r.Name)
67+
}
68+
69+
if err := os.RemoveAll(v.Mountpoint); err != nil {
70+
return logError(err.Error())
71+
}
72+
73+
delete(d.volumes, r.Name)
74+
75+
return saveState(d.statePath, d.volumes)
76+
}
77+
78+
func (d *sshfsDriver) Path(r *volume.PathRequest) (*volume.PathResponse, error) {
79+
logrus.WithField("method", "path").Debugf("%#v", r)
80+
81+
d.RLock()
82+
defer d.RUnlock()
83+
84+
v, ok := d.volumes[r.Name]
85+
if !ok {
86+
return &volume.PathResponse{}, logError("volume %s not found", r.Name)
87+
}
88+
89+
return &volume.PathResponse{Mountpoint: v.Mountpoint}, nil
90+
}
91+
92+
func (d *sshfsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) {
93+
logrus.WithField("method", "mount").Debugf("%#v", r)
94+
95+
d.Lock()
96+
defer d.Unlock()
97+
98+
v, ok := d.volumes[r.Name]
99+
if !ok {
100+
return &volume.MountResponse{}, logError("volume %s not found", r.Name)
101+
}
102+
103+
if v.connections == 0 {
104+
fi, err := os.Lstat(v.Mountpoint)
105+
if os.IsNotExist(err) {
106+
if err := os.MkdirAll(v.Mountpoint, 0755); err != nil {
107+
return &volume.MountResponse{}, logError(err.Error())
108+
}
109+
} else if err != nil {
110+
return &volume.MountResponse{}, logError(err.Error())
111+
}
112+
113+
if fi != nil && !fi.IsDir() {
114+
return &volume.MountResponse{}, logError("%v already exist and it's not a directory", v.Mountpoint)
115+
}
116+
117+
if err := mountVolume(v); err != nil {
118+
return &volume.MountResponse{}, logError(err.Error())
119+
}
120+
}
121+
122+
v.connections++
123+
124+
return &volume.MountResponse{Mountpoint: v.Mountpoint}, nil
125+
}
126+
127+
func (d *sshfsDriver) Unmount(r *volume.UnmountRequest) error {
128+
logrus.WithField("method", "unmount").Debugf("%#v", r)
129+
130+
d.Lock()
131+
defer d.Unlock()
132+
133+
v, ok := d.volumes[r.Name]
134+
if !ok {
135+
return logError("volume %s not found", r.Name)
136+
}
137+
138+
v.connections--
139+
140+
if v.connections <= 0 {
141+
if err := unmountVolume(v.Mountpoint); err != nil {
142+
return logError(err.Error())
143+
}
144+
v.connections = 0
145+
}
146+
147+
return nil
148+
}
149+
150+
func (d *sshfsDriver) Get(r *volume.GetRequest) (*volume.GetResponse, error) {
151+
logrus.WithField("method", "get").Debugf("%#v", r)
152+
153+
d.RLock()
154+
defer d.RUnlock()
155+
156+
v, ok := d.volumes[r.Name]
157+
if !ok {
158+
return &volume.GetResponse{}, logError("volume %s not found", r.Name)
159+
}
160+
161+
return &volume.GetResponse{Volume: &volume.Volume{Name: r.Name, Mountpoint: v.Mountpoint}}, nil
162+
}
163+
164+
func (d *sshfsDriver) List() (*volume.ListResponse, error) {
165+
logrus.WithField("method", "list").Debug("")
166+
167+
d.RLock()
168+
defer d.RUnlock()
169+
170+
var vols []*volume.Volume
171+
for name, v := range d.volumes {
172+
vols = append(vols, &volume.Volume{Name: name, Mountpoint: v.Mountpoint})
173+
}
174+
return &volume.ListResponse{Volumes: vols}, nil
175+
}
176+
177+
func (d *sshfsDriver) Capabilities() *volume.CapabilitiesResponse {
178+
logrus.WithField("method", "capabilities").Debug("")
179+
180+
return &volume.CapabilitiesResponse{Capabilities: volume.Capability{Scope: "local"}}
181+
}

0 commit comments

Comments
 (0)