-
Notifications
You must be signed in to change notification settings - Fork 492
/
storage.go
138 lines (117 loc) · 4.08 KB
/
storage.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package storage
import (
"fmt"
"io"
"path"
"github.com/juju/utils/v3"
"github.com/juju/juju/environs/simplestreams"
)
// RemoveAll is a default implementation for StorageWriter.RemoveAll.
// Providers may have more efficient implementations, or better error handling,
// or safeguards against races with other users of the same storage medium.
// But a simple way to implement RemoveAll would be to delegate to here.
func RemoveAll(stor Storage) error {
files, err := List(stor, "")
if err != nil {
return fmt.Errorf("unable to list files for deletion: %v", err)
}
// Some limited parallellism might be useful in this loop.
for _, file := range files {
err = stor.Remove(file)
if err != nil {
break
}
}
return err
}
// Get gets the named file from stor using the stor's default consistency strategy.
func Get(stor StorageReader, name string) (io.ReadCloser, error) {
return GetWithRetry(stor, name, stor.DefaultConsistencyStrategy())
}
// GetWithRetry gets the named file from stor using the specified attempt strategy.
//
// TODO(katco): 2016-08-09: lp:1611427
func GetWithRetry(stor StorageReader, name string, attempt utils.AttemptStrategy) (r io.ReadCloser, err error) {
for a := attempt.Start(); a.Next(); {
r, err = stor.Get(name)
if err == nil || !stor.ShouldRetry(err) {
break
}
}
return r, err
}
// List lists the files matching prefix from stor using the stor's default consistency strategy.
func List(stor StorageReader, prefix string) ([]string, error) {
return ListWithRetry(stor, prefix, stor.DefaultConsistencyStrategy())
}
// ListWithRetry lists the files matching prefix from stor using the specified attempt strategy.
//
// TODO(katco): 2016-08-09: lp:1611427
func ListWithRetry(stor StorageReader, prefix string, attempt utils.AttemptStrategy) (list []string, err error) {
for a := attempt.Start(); a.Next(); {
list, err = stor.List(prefix)
if err == nil || !stor.ShouldRetry(err) {
break
}
}
return list, err
}
// BaseToolsPath is the container where tools tarballs and metadata are found.
var BaseToolsPath = "tools"
// BaseImagesPath is the container where images metadata is found.
var BaseImagesPath = "images"
// A storageSimpleStreamsDataSource retrieves data from a StorageReader.
type storageSimpleStreamsDataSource struct {
description string
basePath string
storage StorageReader
priority int
requireSigned bool
}
// NewStorageSimpleStreamsDataSource returns a new datasource reading from the specified storage.
func NewStorageSimpleStreamsDataSource(description string, storage StorageReader, basePath string, priority int, requireSigned bool) simplestreams.DataSource {
return &storageSimpleStreamsDataSource{description, basePath, storage, priority, requireSigned}
}
func (s *storageSimpleStreamsDataSource) relpath(storagePath string) string {
relpath := storagePath
if s.basePath != "" {
relpath = path.Join(s.basePath, relpath)
}
return relpath
}
// Description is defined in simplestreams.DataSource.
func (s *storageSimpleStreamsDataSource) Description() string {
return s.description
}
// Fetch is defined in simplestreams.DataSource.
func (s *storageSimpleStreamsDataSource) Fetch(path string) (io.ReadCloser, string, error) {
relpath := s.relpath(path)
dataURL := relpath
fullURL, err := s.storage.URL(relpath)
if err == nil {
dataURL = fullURL
}
rc, err := Get(s.storage, relpath)
if err != nil {
return nil, dataURL, err
}
return rc, dataURL, nil
}
// URL is defined in simplestreams.DataSource.
func (s *storageSimpleStreamsDataSource) URL(path string) (string, error) {
return s.storage.URL(s.relpath(path))
}
// PublicSigningKey is defined in simplestreams.DataSource.
func (u *storageSimpleStreamsDataSource) PublicSigningKey() string {
return ""
}
// Priority is defined in simplestreams.DataSource.
func (s *storageSimpleStreamsDataSource) Priority() int {
return s.priority
}
// RequireSigned is defined in simplestreams.DataSource.
func (s *storageSimpleStreamsDataSource) RequireSigned() bool {
return s.requireSigned
}