-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimagemetadata.go
148 lines (133 loc) · 4.56 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
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package environs
import (
"sync"
"github.com/juju/errors"
"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{{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 BootstrapEnviron, dataSourceFactory simplestreams.DataSourceFactory) ([]simplestreams.DataSource, error) {
config := env.Config()
// Add configured and environment-specific datasources.
var sources []simplestreams.DataSource
if userURL, ok := config.ImageMetadataURL(); ok {
publicKey, err := simplestreams.UserPublicSigningKey()
if err != nil {
return nil, errors.Trace(err)
}
cfg := simplestreams.Config{
Description: "image-metadata-url",
BaseURL: userURL,
PublicSigningKey: publicKey,
HostnameVerification: config.SSLHostnameVerification(),
Priority: simplestreams.SPECIFIC_CLOUD_DATA,
}
if err := cfg.Validate(); err != nil {
return nil, errors.Trace(err)
}
dataSource := dataSourceFactory.NewDataSource(cfg)
sources = append(sources, dataSource)
}
envDataSources, err := environmentDataSources(env)
if err != nil {
return nil, err
}
sources = append(sources, envDataSources...)
// Add the official image metadata datasources.
officialDataSources, err := imagemetadata.OfficialDataSources(dataSourceFactory, config.ImageStream())
if err != nil {
return nil, err
}
sources = append(sources, officialDataSources...)
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(bootstrapEnviron BootstrapEnviron) ([]simplestreams.DataSource, error) {
datasourceFuncsMu.RLock()
defer datasourceFuncsMu.RUnlock()
var datasources []simplestreams.DataSource
env, ok := bootstrapEnviron.(Environ)
if !ok {
logger.Debugf("environmentDataSources is supported for IAAS, environ %#v is not Environ", bootstrapEnviron)
// ignore for CAAS
return datasources, nil
}
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
}