github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/environs/imagemetadata.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package environs 5 6 import ( 7 "sync" 8 9 "github.com/juju/errors" 10 "github.com/juju/utils" 11 12 "github.com/juju/juju/environs/imagemetadata" 13 "github.com/juju/juju/environs/simplestreams" 14 ) 15 16 type datasourceFuncId struct { 17 id string 18 f ImageDataSourceFunc 19 } 20 21 var ( 22 datasourceFuncsMu sync.RWMutex 23 datasourceFuncs []datasourceFuncId 24 ) 25 26 // ImageDataSourceFunc is a function type that takes an environment and 27 // returns a simplestreams datasource. 28 // 29 // ImageDataSourceFunc will be used in ImageMetadataSources. 30 // Any error satisfying errors.IsNotSupported will be ignored; 31 // any other error will be cause ImageMetadataSources to fail. 32 type ImageDataSourceFunc func(Environ) (simplestreams.DataSource, error) 33 34 // RegisterImageDataSourceFunc registers an ImageDataSourceFunc 35 // with the specified id, overwriting any function previously registered 36 // with the same id. 37 func RegisterImageDataSourceFunc(id string, f ImageDataSourceFunc) { 38 datasourceFuncsMu.Lock() 39 defer datasourceFuncsMu.Unlock() 40 for i := range datasourceFuncs { 41 if datasourceFuncs[i].id == id { 42 datasourceFuncs[i].f = f 43 return 44 } 45 } 46 datasourceFuncs = append(datasourceFuncs, datasourceFuncId{id, f}) 47 } 48 49 // UnregisterImageDataSourceFunc unregisters an ImageDataSourceFunc 50 // with the specified id. 51 func UnregisterImageDataSourceFunc(id string) { 52 datasourceFuncsMu.Lock() 53 defer datasourceFuncsMu.Unlock() 54 for i, f := range datasourceFuncs { 55 if f.id == id { 56 head := datasourceFuncs[:i] 57 tail := datasourceFuncs[i+1:] 58 datasourceFuncs = append(head, tail...) 59 return 60 } 61 } 62 } 63 64 // ImageMetadataSources returns the sources to use when looking for 65 // simplestreams image id metadata for the given stream. 66 func ImageMetadataSources(env Environ) ([]simplestreams.DataSource, error) { 67 config := env.Config() 68 69 // Add configured and environment-specific datasources. 70 var sources []simplestreams.DataSource 71 if userURL, ok := config.ImageMetadataURL(); ok { 72 verify := utils.VerifySSLHostnames 73 if !config.SSLHostnameVerification() { 74 verify = utils.NoVerifySSLHostnames 75 } 76 sources = append(sources, simplestreams.NewURLDataSource("image-metadata-url", userURL, verify)) 77 } 78 79 envDataSources, err := environmentDataSources(env) 80 if err != nil { 81 return nil, err 82 } 83 sources = append(sources, envDataSources...) 84 85 // Add the default, public datasource. 86 defaultURL, err := imagemetadata.ImageMetadataURL(imagemetadata.DefaultBaseURL, config.ImageStream()) 87 if err != nil { 88 return nil, err 89 } 90 if defaultURL != "" { 91 sources = append(sources, 92 simplestreams.NewURLDataSource("default cloud images", defaultURL, utils.VerifySSLHostnames)) 93 } 94 return sources, nil 95 } 96 97 // environmentDataSources returns simplestreams datasources for the environment 98 // by calling the functions registered in RegisterImageDataSourceFunc. 99 // The datasources returned will be in the same order the functions were registered. 100 func environmentDataSources(env Environ) ([]simplestreams.DataSource, error) { 101 datasourceFuncsMu.RLock() 102 defer datasourceFuncsMu.RUnlock() 103 var datasources []simplestreams.DataSource 104 for _, f := range datasourceFuncs { 105 logger.Debugf("trying datasource %q", f.id) 106 datasource, err := f.f(env) 107 if err != nil { 108 if errors.IsNotSupported(err) { 109 continue 110 } 111 return nil, err 112 } 113 datasources = append(datasources, datasource) 114 } 115 return datasources, nil 116 }