~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/environs/storage/storage.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}