forked from calavera/docker-volume-vault
/
volume.go
104 lines (84 loc) · 2.01 KB
/
volume.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package store
import (
"fmt"
"log"
"os"
"path/filepath"
"sync"
"github.com/ChrisMcKenzie/docker-volume-vault/fs"
"github.com/ChrisMcKenzie/docker-volume-vault/vault"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
type Volume struct {
Name string
Token string
Options map[string]string
server *fuse.Server
lock *sync.Mutex
}
func NewVolume(name, token string, options map[string]string) *Volume {
return &Volume{
Name: name,
Token: token,
Options: options,
lock: new(sync.Mutex),
}
}
func (v *Volume) Mount(root string) (string, error) {
v.lock.Lock()
defer v.lock.Unlock()
m := filepath.Join(root, v.Name)
if v.server != nil {
// Server already mounted
return m, nil
}
log.Printf("[INF]: Mounting volume %s on %s\n", v.Name, m)
fi, err := os.Lstat(m)
if os.IsNotExist(err) {
if err := os.MkdirAll(m, 0755); err != nil {
return "", err
}
} else if err != nil {
return "", err
}
if fi != nil && !fi.IsDir() {
return "", fmt.Errorf("%v already exist and it's not a directory", m)
}
server, err := mountServer(v.Token, m)
if err != nil {
return "", err
}
v.server = server
return m, nil
}
func (vol *Volume) Mounted() bool {
return vol.server != nil
}
func (vol *Volume) Unmount() error {
return vol.server.Unmount()
}
func mountServer(token, mountpoint string) (*fuse.Server, error) {
if err := os.MkdirAll(filepath.Dir(mountpoint), 0755); err != nil {
return nil, err
}
client, err := vault.Client(token)
if err != nil {
return nil, err
}
kwfs, root := fs.NewFs(client)
mountOptions := &fuse.MountOptions{
AllowOther: true,
Name: kwfs.String(),
Options: []string{"default_permissions"},
}
// Empty Options struct avoids setting a global uid/gid override.
conn := nodefs.NewFileSystemConnector(root, &nodefs.Options{})
server, err := fuse.NewServer(conn.RawFS(), mountpoint, mountOptions)
if err != nil {
log.Printf("Mount fail: %v\n", err)
return nil, err
}
go server.Serve()
return server, nil
}