/
imagemetadata.go
116 lines (102 loc) · 3.38 KB
/
imagemetadata.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
// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package environs
import (
"sync"
"github.com/juju/errors"
"github.com/juju/utils"
"github.com/juju/juju/environs/imagemetadata"
"github.com/juju/juju/environs/simplestreams"
)
type datasourceFuncId struct {
id string
f ImageDataSourceFunc
}
var (
datasourceFuncsMu sync.RWMutex
datasourceFuncs []datasourceFuncId
)
// ImageDataSourceFunc is a function type that takes an environment and
// returns a simplestreams datasource.
//
// ImageDataSourceFunc will be used in ImageMetadataSources.
// Any error satisfying errors.IsNotSupported will be ignored;
// any other error will be cause ImageMetadataSources to fail.
type ImageDataSourceFunc func(Environ) (simplestreams.DataSource, error)
// RegisterImageDataSourceFunc registers an ImageDataSourceFunc
// with the specified id, overwriting any function previously registered
// with the same id.
func RegisterImageDataSourceFunc(id string, f ImageDataSourceFunc) {
datasourceFuncsMu.Lock()
defer datasourceFuncsMu.Unlock()
for i := range datasourceFuncs {
if datasourceFuncs[i].id == id {
datasourceFuncs[i].f = f
return
}
}
datasourceFuncs = append(datasourceFuncs, datasourceFuncId{id, f})
}
// UnregisterImageDataSourceFunc unregisters an ImageDataSourceFunc
// with the specified id.
func UnregisterImageDataSourceFunc(id string) {
datasourceFuncsMu.Lock()
defer datasourceFuncsMu.Unlock()
for i, f := range datasourceFuncs {
if f.id == id {
head := datasourceFuncs[:i]
tail := datasourceFuncs[i+1:]
datasourceFuncs = append(head, tail...)
return
}
}
}
// ImageMetadataSources returns the sources to use when looking for
// simplestreams image id metadata for the given stream.
func ImageMetadataSources(env Environ) ([]simplestreams.DataSource, error) {
config := env.Config()
// Add configured and environment-specific datasources.
var sources []simplestreams.DataSource
if userURL, ok := config.ImageMetadataURL(); ok {
verify := utils.VerifySSLHostnames
if !config.SSLHostnameVerification() {
verify = utils.NoVerifySSLHostnames
}
sources = append(sources, simplestreams.NewURLDataSource("image-metadata-url", userURL, verify))
}
envDataSources, err := environmentDataSources(env)
if err != nil {
return nil, err
}
sources = append(sources, envDataSources...)
// Add the default, public datasource.
defaultURL, err := imagemetadata.ImageMetadataURL(imagemetadata.DefaultBaseURL, config.ImageStream())
if err != nil {
return nil, err
}
if defaultURL != "" {
sources = append(sources,
simplestreams.NewURLDataSource("default cloud images", defaultURL, utils.VerifySSLHostnames))
}
return sources, nil
}
// environmentDataSources returns simplestreams datasources for the environment
// by calling the functions registered in RegisterImageDataSourceFunc.
// The datasources returned will be in the same order the functions were registered.
func environmentDataSources(env Environ) ([]simplestreams.DataSource, error) {
datasourceFuncsMu.RLock()
defer datasourceFuncsMu.RUnlock()
var datasources []simplestreams.DataSource
for _, f := range datasourceFuncs {
logger.Debugf("trying datasource %q", f.id)
datasource, err := f.f(env)
if err != nil {
if errors.IsNotSupported(err) {
continue
}
return nil, err
}
datasources = append(datasources, datasource)
}
return datasources, nil
}