launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/environs/imagemetadata/urls.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package imagemetadata
     5  
     6  import (
     7  	"fmt"
     8  	"net/url"
     9  	"strings"
    10  
    11  	"launchpad.net/juju-core/environs"
    12  	"launchpad.net/juju-core/environs/simplestreams"
    13  	"launchpad.net/juju-core/environs/storage"
    14  )
    15  
    16  // SupportsCustomSources represents an environment that
    17  // can host image metadata at provider specific sources.
    18  type SupportsCustomSources interface {
    19  	GetImageSources() ([]simplestreams.DataSource, error)
    20  }
    21  
    22  // GetMetadataSources returns the sources to use when looking for
    23  // simplestreams image id metadata for the given stream. If env implements
    24  // SupportsCustomSources, the sources returned from that method will also
    25  // be considered.
    26  func GetMetadataSources(env environs.ConfigGetter) ([]simplestreams.DataSource, error) {
    27  	var sources []simplestreams.DataSource
    28  	config := env.Config()
    29  	if userURL, ok := config.ImageMetadataURL(); ok {
    30  		verify := simplestreams.VerifySSLHostnames
    31  		if !config.SSLHostnameVerification() {
    32  			verify = simplestreams.NoVerifySSLHostnames
    33  		}
    34  		sources = append(sources, simplestreams.NewURLDataSource(userURL, verify))
    35  	}
    36  	if custom, ok := env.(SupportsCustomSources); ok {
    37  		customSources, err := custom.GetImageSources()
    38  		if err != nil {
    39  			return nil, err
    40  		}
    41  		sources = append(sources, customSources...)
    42  	}
    43  
    44  	defaultURL, err := ImageMetadataURL(DefaultBaseURL, config.ImageStream())
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	if defaultURL != "" {
    49  		sources = append(sources, simplestreams.NewURLDataSource(defaultURL, simplestreams.VerifySSLHostnames))
    50  	}
    51  	return sources, nil
    52  }
    53  
    54  // ImageMetadataURL returns a valid image metadata URL constructed from source.
    55  // source may be a directory, or a URL like file://foo or http://foo.
    56  func ImageMetadataURL(source, stream string) (string, error) {
    57  	if source == "" {
    58  		return "", nil
    59  	}
    60  	// If the image metadata is coming from the official cloud images site,
    61  	// set up the correct path according to the images stream requested.
    62  	if source == UbuntuCloudImagesURL {
    63  		cloudImagesPath := ReleasedImagesPath
    64  		if stream != "" && stream != ReleasedStream {
    65  			cloudImagesPath = stream
    66  		}
    67  		source = fmt.Sprintf("%s/%s", source, cloudImagesPath)
    68  	}
    69  	// If source is a raw directory, we need to append the file:// prefix
    70  	// so it can be used as a URL.
    71  	defaultURL := source
    72  	u, err := url.Parse(source)
    73  	if err != nil {
    74  		return "", fmt.Errorf("invalid default image metadata URL %s: %v", defaultURL, err)
    75  	}
    76  	if u.Scheme == "" {
    77  		defaultURL = "file://" + defaultURL
    78  		if !strings.HasSuffix(defaultURL, "/"+storage.BaseImagesPath) {
    79  			defaultURL = fmt.Sprintf("%s/%s", defaultURL, storage.BaseImagesPath)
    80  		}
    81  	}
    82  	return defaultURL, nil
    83  }