github.com/nguyentm83/docker@v1.5.0/volumes/volume.go (about) 1 package volumes 2 3 import ( 4 "encoding/json" 5 "io" 6 "io/ioutil" 7 "os" 8 "path" 9 "path/filepath" 10 "sync" 11 12 "github.com/docker/docker/pkg/archive" 13 "github.com/docker/docker/pkg/symlink" 14 ) 15 16 type Volume struct { 17 ID string 18 Path string 19 IsBindMount bool 20 Writable bool 21 containers map[string]struct{} 22 configPath string 23 repository *Repository 24 lock sync.Mutex 25 } 26 27 func (v *Volume) Export(resource, name string) (io.ReadCloser, error) { 28 if v.IsBindMount && filepath.Base(resource) == name { 29 name = "" 30 } 31 32 basePath, err := v.getResourcePath(resource) 33 if err != nil { 34 return nil, err 35 } 36 stat, err := os.Stat(basePath) 37 if err != nil { 38 return nil, err 39 } 40 var filter []string 41 if !stat.IsDir() { 42 d, f := path.Split(basePath) 43 basePath = d 44 filter = []string{f} 45 } else { 46 filter = []string{path.Base(basePath)} 47 basePath = path.Dir(basePath) 48 } 49 return archive.TarWithOptions(basePath, &archive.TarOptions{ 50 Compression: archive.Uncompressed, 51 Name: name, 52 IncludeFiles: filter, 53 }) 54 } 55 56 func (v *Volume) IsDir() (bool, error) { 57 stat, err := os.Stat(v.Path) 58 if err != nil { 59 return false, err 60 } 61 62 return stat.IsDir(), nil 63 } 64 65 func (v *Volume) Containers() []string { 66 v.lock.Lock() 67 68 var containers []string 69 for c := range v.containers { 70 containers = append(containers, c) 71 } 72 73 v.lock.Unlock() 74 return containers 75 } 76 77 func (v *Volume) RemoveContainer(containerId string) { 78 v.lock.Lock() 79 delete(v.containers, containerId) 80 v.lock.Unlock() 81 } 82 83 func (v *Volume) AddContainer(containerId string) { 84 v.lock.Lock() 85 v.containers[containerId] = struct{}{} 86 v.lock.Unlock() 87 } 88 89 func (v *Volume) initialize() error { 90 v.lock.Lock() 91 defer v.lock.Unlock() 92 93 if _, err := os.Stat(v.Path); err != nil && os.IsNotExist(err) { 94 if err := os.MkdirAll(v.Path, 0755); err != nil { 95 return err 96 } 97 } 98 99 if err := os.MkdirAll(v.configPath, 0755); err != nil { 100 return err 101 } 102 jsonPath, err := v.jsonPath() 103 if err != nil { 104 return err 105 } 106 f, err := os.Create(jsonPath) 107 if err != nil { 108 return err 109 } 110 defer f.Close() 111 112 return v.toDisk() 113 } 114 115 func (v *Volume) ToDisk() error { 116 v.lock.Lock() 117 defer v.lock.Unlock() 118 return v.toDisk() 119 } 120 121 func (v *Volume) toDisk() error { 122 data, err := json.Marshal(v) 123 if err != nil { 124 return err 125 } 126 127 pth, err := v.jsonPath() 128 if err != nil { 129 return err 130 } 131 132 return ioutil.WriteFile(pth, data, 0666) 133 } 134 135 func (v *Volume) FromDisk() error { 136 v.lock.Lock() 137 defer v.lock.Unlock() 138 pth, err := v.jsonPath() 139 if err != nil { 140 return err 141 } 142 143 jsonSource, err := os.Open(pth) 144 if err != nil { 145 return err 146 } 147 defer jsonSource.Close() 148 149 dec := json.NewDecoder(jsonSource) 150 151 return dec.Decode(v) 152 } 153 154 func (v *Volume) jsonPath() (string, error) { 155 return v.getRootResourcePath("config.json") 156 } 157 func (v *Volume) getRootResourcePath(path string) (string, error) { 158 cleanPath := filepath.Join("/", path) 159 return symlink.FollowSymlinkInScope(filepath.Join(v.configPath, cleanPath), v.configPath) 160 } 161 162 func (v *Volume) getResourcePath(path string) (string, error) { 163 cleanPath := filepath.Join("/", path) 164 return symlink.FollowSymlinkInScope(filepath.Join(v.Path, cleanPath), v.Path) 165 }