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

refactor code #36

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- sudo apt-get update
- sudo apt-get -y install docker-ce
install:
- docker pull rastasheep/ubuntu-sshd
- docker pull busybox
- docker build -t sshd .travis/ssh
env: TESTFILE=integration.sh

script:
Expand Down
98 changes: 48 additions & 50 deletions .travis/integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,65 +5,63 @@ set -x

TAG=test

# before_install
#curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
#sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
#sudo apt-get update
#sudo apt-get -y install docker-ce

# install
sudo docker pull rastasheep/ubuntu-sshd
sudo docker pull busybox

docker build -t sshd .travis/ssh
#script

# make the plugin
sudo PLUGIN_TAG=$TAG make
PLUGIN_TAG=$TAG make
# enable the plugin
sudo docker plugin enable vieux/sshfs:$TAG
PLUGIN_TAG=$TAG make enable
# list plugins
sudo docker plugin ls
docker plugin ls
# start sshd
sudo docker run -d -p 2222:22 sshd
docker run -d --name sshd -p 2222:22 sshd

# test1: simple
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 -o password=root sshvolume
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#sudo cat /var/lib/docker/plugins/sshfs-state.json
sudo docker volume rm sshvolume
echo "# test1: simple"
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 -o password=root sshvolume
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#cat /var/lib/docker/plugins/sshfs-state.json
docker volume rm sshvolume

# test2: allow_other
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o allow_other -o port=2222 -o password=root sshvolume
sudo docker run --rm -v sshvolume:/write -u nobody busybox sh -c "echo hello > /write/world"
echo "# test2: allow_other"
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o allow_other -o port=2222 -o password=root sshvolume
docker run --rm -v sshvolume:/write -u nobody busybox sh -c "echo hello > /write/world"
docker run --rm -v sshvolume:/read -u nobody busybox grep -Fxq hello /read/world
#sudo cat /var/lib/docker/plugins/sshfs-state.json
sudo docker volume rm sshvolume
#cat /var/lib/docker/plugins/sshfs-state.json
docker volume rm sshvolume

echo "# test3: compression"
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o Ciphers=arcfour -o Compression=no -o port=2222 -o password=root sshvolume
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#cat /var/lib/docker/plugins/sshfs-state.json
docker volume rm sshvolume

echo "# test4: restart"
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 -o password=root sshvolume
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
docker restart sshd
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
docker volume rm sshvolume

echo "# test5: source"
docker plugin disable vieux/sshfs:$TAG
docker plugin set vieux/sshfs:$TAG state.source=/tmp
docker plugin enable vieux/sshfs:$TAG
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o Ciphers=arcfour -o Compression=no -o port=2222 -o password=root sshvolume
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#cat /tmp/sshfs-state.json
docker volume rm sshvolume

# test3: compression
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
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#sudo cat /var/lib/docker/plugins/sshfs-state.json
sudo docker volume rm sshvolume
echo "# test6: ssh key"
docker plugin disable vieux/sshfs:$TAG
docker plugin set vieux/sshfs:$TAG sshkey.source=`pwd`/.travis/ssh/
docker plugin enable vieux/sshfs:$TAG
docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 sshvolume
docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#cat /var/lib/docker/plugins/sshfs-state.json
docker volume rm sshvolume

# test4: source
sudo docker plugin disable vieux/sshfs:$TAG
sudo docker plugin set vieux/sshfs:$TAG state.source=/tmp
sudo docker plugin enable vieux/sshfs:$TAG
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
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#sudo cat /tmp/sshfs-state.json
sudo docker volume rm sshvolume

# test5: ssh key
sudo docker plugin disable vieux/sshfs:$TAG
sudo docker plugin set vieux/sshfs:$TAG sshkey.source=`pwd`/.travis/ssh/
sudo docker plugin enable vieux/sshfs:$TAG
sudo docker volume create -d vieux/sshfs:$TAG -o sshcmd=root@localhost:/ -o port=2222 sshvolume
sudo docker run --rm -v sshvolume:/write busybox sh -c "echo hello > /write/world"
sudo docker run --rm -v sshvolume:/read busybox grep -Fxq hello /read/world
#sudo cat /var/lib/docker/plugins/sshfs-state.json
sudo docker volume rm sshvolume
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ create:
@docker plugin create ${PLUGIN_NAME}:${PLUGIN_TAG} ./plugin

enable:
@echo "### enable plugin ${PLUGIN_NAME}:${PLUGIN_TAG}"
@echo "### enable plugin ${PLUGIN_NAME}:${PLUGIN_TAG}"
@docker plugin set ${PLUGIN_NAME}:${PLUGIN_TAG} DEBUG=1
@docker plugin enable ${PLUGIN_NAME}:${PLUGIN_TAG}

push: clean rootfs create enable
Expand Down
181 changes: 181 additions & 0 deletions driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package main

import (
"os"
"path/filepath"
"sync"

"github.com/Sirupsen/logrus"
"github.com/docker/go-plugins-helpers/volume"
)

const socketAddress = "/run/docker/plugins/sshfs.sock"

type sshfsDriver struct {
sync.RWMutex

root string
statePath string
volumes map[string]*sshfsVolume
}

func newSshfsDriver(root string) (*sshfsDriver, error) {
logrus.WithField("method", "new driver").Debug(root)

statePath := filepath.Join(root, "state", "sshfs-state.json")
volumes, err := readState(statePath)
if err != nil {
return nil, err
}

return &sshfsDriver{
root: filepath.Join(root, "volumes"),
statePath: statePath,
volumes: volumes,
}, nil
}

func (d *sshfsDriver) Create(r *volume.CreateRequest) error {
logrus.WithField("method", "create").Debugf("%#v", r)

v, err := newSshfsVolume(d.root, r.Options)
if err != nil {
return err
}

d.Lock()
defer d.Unlock()

d.volumes[r.Name] = v

return saveState(d.statePath, d.volumes)
}

func (d *sshfsDriver) Remove(r *volume.RemoveRequest) error {
logrus.WithField("method", "remove").Debugf("%#v", r)

d.Lock()
defer d.Unlock()

v, ok := d.volumes[r.Name]
if !ok {
return logError("volume %s not found", r.Name)
}

if v.connections != 0 {
return logError("volume %s is currently used by a container", r.Name)
}

if err := os.RemoveAll(v.Mountpoint); err != nil {
return logError(err.Error())
}

delete(d.volumes, r.Name)

return saveState(d.statePath, d.volumes)
}

func (d *sshfsDriver) Path(r *volume.PathRequest) (*volume.PathResponse, error) {
logrus.WithField("method", "path").Debugf("%#v", r)

d.RLock()
defer d.RUnlock()

v, ok := d.volumes[r.Name]
if !ok {
return &volume.PathResponse{}, logError("volume %s not found", r.Name)
}

return &volume.PathResponse{Mountpoint: v.Mountpoint}, nil
}

func (d *sshfsDriver) Mount(r *volume.MountRequest) (*volume.MountResponse, error) {
logrus.WithField("method", "mount").Debugf("%#v", r)

d.Lock()
defer d.Unlock()

v, ok := d.volumes[r.Name]
if !ok {
return &volume.MountResponse{}, logError("volume %s not found", r.Name)
}

if v.connections == 0 {
fi, err := os.Lstat(v.Mountpoint)
if os.IsNotExist(err) {
if err := os.MkdirAll(v.Mountpoint, 0755); err != nil {
return &volume.MountResponse{}, logError(err.Error())
}
} else if err != nil {
return &volume.MountResponse{}, logError(err.Error())
}

if fi != nil && !fi.IsDir() {
return &volume.MountResponse{}, logError("%v already exist and it's not a directory", v.Mountpoint)
}

if err := mountVolume(v); err != nil {
return &volume.MountResponse{}, logError(err.Error())
}
}

v.connections++

return &volume.MountResponse{Mountpoint: v.Mountpoint}, nil
}

func (d *sshfsDriver) Unmount(r *volume.UnmountRequest) error {
logrus.WithField("method", "unmount").Debugf("%#v", r)

d.Lock()
defer d.Unlock()

v, ok := d.volumes[r.Name]
if !ok {
return logError("volume %s not found", r.Name)
}

v.connections--

if v.connections <= 0 {
if err := unmountVolume(v.Mountpoint); err != nil {
return logError(err.Error())
}
v.connections = 0
}

return nil
}

func (d *sshfsDriver) Get(r *volume.GetRequest) (*volume.GetResponse, error) {
logrus.WithField("method", "get").Debugf("%#v", r)

d.RLock()
defer d.RUnlock()

v, ok := d.volumes[r.Name]
if !ok {
return &volume.GetResponse{}, logError("volume %s not found", r.Name)
}

return &volume.GetResponse{Volume: &volume.Volume{Name: r.Name, Mountpoint: v.Mountpoint}}, nil
}

func (d *sshfsDriver) List() (*volume.ListResponse, error) {
logrus.WithField("method", "list").Debug("")

d.RLock()
defer d.RUnlock()

var vols []*volume.Volume
for name, v := range d.volumes {
vols = append(vols, &volume.Volume{Name: name, Mountpoint: v.Mountpoint})
}
return &volume.ListResponse{Volumes: vols}, nil
}

func (d *sshfsDriver) Capabilities() *volume.CapabilitiesResponse {
logrus.WithField("method", "capabilities").Debug("")

return &volume.CapabilitiesResponse{Capabilities: volume.Capability{Scope: "local"}}
}
Loading