github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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  // RegisterUserImageDataSourceFunc registers an ImageDataSourceFunc
    35  // with the specified id at the start of the search path, overwriting
    36  // any function previously registered with the same id.
    37  func RegisterUserImageDataSourceFunc(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  	logger.Debugf("new user image datasource registered: %v", id)
    47  	datasourceFuncs = append([]datasourceFuncId{datasourceFuncId{id, f}}, datasourceFuncs...)
    48  }
    49  
    50  // RegisterImageDataSourceFunc registers an ImageDataSourceFunc
    51  // with the specified id, overwriting any function previously registered
    52  // with the same id.
    53  func RegisterImageDataSourceFunc(id string, f ImageDataSourceFunc) {
    54  	datasourceFuncsMu.Lock()
    55  	defer datasourceFuncsMu.Unlock()
    56  	for i := range datasourceFuncs {
    57  		if datasourceFuncs[i].id == id {
    58  			datasourceFuncs[i].f = f
    59  			return
    60  		}
    61  	}
    62  	logger.Debugf("new model image datasource registered: %v", id)
    63  	datasourceFuncs = append(datasourceFuncs, datasourceFuncId{id, f})
    64  }
    65  
    66  // UnregisterImageDataSourceFunc unregisters an ImageDataSourceFunc
    67  // with the specified id.
    68  func UnregisterImageDataSourceFunc(id string) {
    69  	datasourceFuncsMu.Lock()
    70  	defer datasourceFuncsMu.Unlock()
    71  	for i, f := range datasourceFuncs {
    72  		if f.id == id {
    73  			head := datasourceFuncs[:i]
    74  			tail := datasourceFuncs[i+1:]
    75  			datasourceFuncs = append(head, tail...)
    76  			return
    77  		}
    78  	}
    79  }
    80  
    81  // ImageMetadataSources returns the sources to use when looking for
    82  // simplestreams image id metadata for the given stream.
    83  func ImageMetadataSources(env Environ) ([]simplestreams.DataSource, error) {
    84  	config := env.Config()
    85  
    86  	// Add configured and environment-specific datasources.
    87  	var sources []simplestreams.DataSource
    88  	if userURL, ok := config.ImageMetadataURL(); ok {
    89  		verify := utils.VerifySSLHostnames
    90  		if !config.SSLHostnameVerification() {
    91  			verify = utils.NoVerifySSLHostnames
    92  		}
    93  		publicKey, _ := simplestreams.UserPublicSigningKey()
    94  		sources = append(sources, simplestreams.NewURLSignedDataSource("image-metadata-url", userURL, publicKey, verify, simplestreams.SPECIFIC_CLOUD_DATA, false))
    95  	}
    96  
    97  	envDataSources, err := environmentDataSources(env)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	sources = append(sources, envDataSources...)
   102  
   103  	// Add the official image metadata datasources.
   104  	officialDataSources, err := imagemetadata.OfficialDataSources(config.ImageStream())
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	for _, source := range officialDataSources {
   109  		sources = append(sources, source)
   110  	}
   111  	for _, ds := range sources {
   112  		logger.Debugf("obtained image datasource %q", ds.Description())
   113  	}
   114  	return sources, nil
   115  }
   116  
   117  // environmentDataSources returns simplestreams datasources for the environment
   118  // by calling the functions registered in RegisterImageDataSourceFunc.
   119  // The datasources returned will be in the same order the functions were registered.
   120  func environmentDataSources(env Environ) ([]simplestreams.DataSource, error) {
   121  	datasourceFuncsMu.RLock()
   122  	defer datasourceFuncsMu.RUnlock()
   123  	var datasources []simplestreams.DataSource
   124  	for _, f := range datasourceFuncs {
   125  		datasource, err := f.f(env)
   126  		if err != nil {
   127  			if errors.IsNotSupported(err) {
   128  				continue
   129  			}
   130  			return nil, err
   131  		}
   132  		datasources = append(datasources, datasource)
   133  	}
   134  	return datasources, nil
   135  }