github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/environs/storage/storage.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage 5 6 import ( 7 "fmt" 8 "io" 9 "path" 10 11 "github.com/juju/utils" 12 13 "github.com/juju/juju/environs/simplestreams" 14 ) 15 16 // RemoveAll is a default implementation for StorageWriter.RemoveAll. 17 // Providers may have more efficient implementations, or better error handling, 18 // or safeguards against races with other users of the same storage medium. 19 // But a simple way to implement RemoveAll would be to delegate to here. 20 func RemoveAll(stor Storage) error { 21 files, err := List(stor, "") 22 if err != nil { 23 return fmt.Errorf("unable to list files for deletion: %v", err) 24 } 25 26 // Some limited parallellism might be useful in this loop. 27 for _, file := range files { 28 err = stor.Remove(file) 29 if err != nil { 30 break 31 } 32 } 33 return err 34 } 35 36 // Get gets the named file from stor using the stor's default consistency strategy. 37 func Get(stor StorageReader, name string) (io.ReadCloser, error) { 38 return GetWithRetry(stor, name, stor.DefaultConsistencyStrategy()) 39 } 40 41 // GetWithRetry gets the named file from stor using the specified attempt strategy. 42 // 43 // TODO(katco): 2016-08-09: lp:1611427 44 func GetWithRetry(stor StorageReader, name string, attempt utils.AttemptStrategy) (r io.ReadCloser, err error) { 45 for a := attempt.Start(); a.Next(); { 46 r, err = stor.Get(name) 47 if err == nil || !stor.ShouldRetry(err) { 48 break 49 } 50 } 51 return r, err 52 } 53 54 // List lists the files matching prefix from stor using the stor's default consistency strategy. 55 func List(stor StorageReader, prefix string) ([]string, error) { 56 return ListWithRetry(stor, prefix, stor.DefaultConsistencyStrategy()) 57 } 58 59 // ListWithRetry lists the files matching prefix from stor using the specified attempt strategy. 60 // 61 // TODO(katco): 2016-08-09: lp:1611427 62 func ListWithRetry(stor StorageReader, prefix string, attempt utils.AttemptStrategy) (list []string, err error) { 63 for a := attempt.Start(); a.Next(); { 64 list, err = stor.List(prefix) 65 if err == nil || !stor.ShouldRetry(err) { 66 break 67 } 68 } 69 return list, err 70 } 71 72 // BaseToolsPath is the container where tools tarballs and metadata are found. 73 var BaseToolsPath = "tools" 74 75 // BaseImagesPath is the container where images metadata is found. 76 var BaseImagesPath = "images" 77 78 // A storageSimpleStreamsDataSource retrieves data from a StorageReader. 79 type storageSimpleStreamsDataSource struct { 80 description string 81 basePath string 82 storage StorageReader 83 allowRetry bool 84 priority int 85 requireSigned bool 86 } 87 88 // TestingGetAllowRetry is used in tests which need to see if allowRetry has been 89 // set on a storageSimpleStreamsDataSource. 90 func TestingGetAllowRetry(s simplestreams.DataSource) (bool, ok bool) { 91 if storageDataSource, ok := s.(*storageSimpleStreamsDataSource); ok { 92 return storageDataSource.allowRetry, ok 93 } 94 return false, false 95 } 96 97 // NewStorageSimpleStreamsDataSource returns a new datasource reading from the specified storage. 98 func NewStorageSimpleStreamsDataSource(description string, storage StorageReader, basePath string, priority int, requireSigned bool) simplestreams.DataSource { 99 return &storageSimpleStreamsDataSource{description, basePath, storage, false, priority, requireSigned} 100 } 101 102 func (s *storageSimpleStreamsDataSource) relpath(storagePath string) string { 103 relpath := storagePath 104 if s.basePath != "" { 105 relpath = path.Join(s.basePath, relpath) 106 } 107 return relpath 108 } 109 110 // Description is defined in simplestreams.DataSource. 111 func (s *storageSimpleStreamsDataSource) Description() string { 112 return s.description 113 } 114 115 // Fetch is defined in simplestreams.DataSource. 116 func (s *storageSimpleStreamsDataSource) Fetch(path string) (io.ReadCloser, string, error) { 117 relpath := s.relpath(path) 118 dataURL := relpath 119 fullURL, err := s.storage.URL(relpath) 120 if err == nil { 121 dataURL = fullURL 122 } 123 // TODO(katco): 2016-08-09: lp:1611427 124 var attempt utils.AttemptStrategy 125 if s.allowRetry { 126 attempt = s.storage.DefaultConsistencyStrategy() 127 } 128 rc, err := GetWithRetry(s.storage, relpath, attempt) 129 if err != nil { 130 return nil, dataURL, err 131 } 132 return rc, dataURL, nil 133 } 134 135 // URL is defined in simplestreams.DataSource. 136 func (s *storageSimpleStreamsDataSource) URL(path string) (string, error) { 137 return s.storage.URL(s.relpath(path)) 138 } 139 140 // PublicSigningKey is defined in simplestreams.DataSource. 141 func (u *storageSimpleStreamsDataSource) PublicSigningKey() string { 142 return "" 143 } 144 145 // SetAllowRetry is defined in simplestreams.DataSource. 146 func (s *storageSimpleStreamsDataSource) SetAllowRetry(allow bool) { 147 s.allowRetry = allow 148 } 149 150 // Priority is defined in simplestreams.DataSource. 151 func (s *storageSimpleStreamsDataSource) Priority() int { 152 return s.priority 153 } 154 155 // RequireSigned is defined in simplestreams.DataSource. 156 func (s *storageSimpleStreamsDataSource) RequireSigned() bool { 157 return s.requireSigned 158 }