-
Notifications
You must be signed in to change notification settings - Fork 0
/
imagemetadata.go
135 lines (120 loc) · 4.11 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// 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)
// RegisterUserImageDataSourceFunc registers an ImageDataSourceFunc
// with the specified id at the start of the search path, overwriting
// any function previously registered with the same id.
func RegisterUserImageDataSourceFunc(id string, f ImageDataSourceFunc) {
datasourceFuncsMu.Lock()
defer datasourceFuncsMu.Unlock()
for i := range datasourceFuncs {
if datasourceFuncs[i].id == id {
datasourceFuncs[i].f = f
return
}
}
logger.Debugf("new user image datasource registered: %v", id)
datasourceFuncs = append([]datasourceFuncId{datasourceFuncId{id, f}}, datasourceFuncs...)
}
// 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
}
}
logger.Debugf("new model image datasource registered: %v", id)
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
}
publicKey, _ := simplestreams.UserPublicSigningKey()
sources = append(sources, simplestreams.NewURLSignedDataSource("image-metadata-url", userURL, publicKey, verify, simplestreams.SPECIFIC_CLOUD_DATA, false))
}
envDataSources, err := environmentDataSources(env)
if err != nil {
return nil, err
}
sources = append(sources, envDataSources...)
// Add the official image metadata datasources.
officialDataSources, err := imagemetadata.OfficialDataSources(config.ImageStream())
if err != nil {
return nil, err
}
for _, source := range officialDataSources {
sources = append(sources, source)
}
for _, ds := range sources {
logger.Debugf("obtained image datasource %q", ds.Description())
}
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 {
datasource, err := f.f(env)
if err != nil {
if errors.IsNotSupported(err) {
continue
}
return nil, err
}
datasources = append(datasources, datasource)
}
return datasources, nil
}