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

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package tools
     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 tools metadata at provider specific sources.
    18  type SupportsCustomSources interface {
    19  	GetToolsSources() ([]simplestreams.DataSource, error)
    20  }
    21  
    22  // GetMetadataSources returns the sources to use when looking for
    23  // simplestreams tools metadata. If env implements SupportsCustomSurces,
    24  // the sources returned from that method will also be considered.
    25  // The sources are configured to not use retries.
    26  func GetMetadataSources(env environs.ConfigGetter) ([]simplestreams.DataSource, error) {
    27  	return GetMetadataSourcesWithRetries(env, false)
    28  }
    29  
    30  // GetMetadataSourcesWithRetries returns the sources to use when looking for
    31  // simplestreams tools metadata. If env implements SupportsCustomSurces,
    32  // the sources returned from that method will also be considered.
    33  // The sources are configured to use retries according to the value of allowRetry.
    34  func GetMetadataSourcesWithRetries(env environs.ConfigGetter, allowRetry bool) ([]simplestreams.DataSource, error) {
    35  	var sources []simplestreams.DataSource
    36  	config := env.Config()
    37  	if userURL, ok := config.ToolsURL(); ok {
    38  		verify := simplestreams.VerifySSLHostnames
    39  		if !config.SSLHostnameVerification() {
    40  			verify = simplestreams.NoVerifySSLHostnames
    41  		}
    42  		sources = append(sources, simplestreams.NewURLDataSource(userURL, verify))
    43  	}
    44  	if custom, ok := env.(SupportsCustomSources); ok {
    45  		customSources, err := custom.GetToolsSources()
    46  		if err != nil {
    47  			return nil, err
    48  		}
    49  		sources = append(sources, customSources...)
    50  	}
    51  
    52  	defaultURL, err := ToolsURL(DefaultBaseURL)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	if defaultURL != "" {
    57  		sources = append(sources, simplestreams.NewURLDataSource(defaultURL, simplestreams.VerifySSLHostnames))
    58  	}
    59  	for _, source := range sources {
    60  		source.SetAllowRetry(allowRetry)
    61  	}
    62  	return sources, nil
    63  }
    64  
    65  // ToolsURL returns a valid tools URL constructed from source.
    66  // source may be a directory, or a URL like file://foo or http://foo.
    67  func ToolsURL(source string) (string, error) {
    68  	if source == "" {
    69  		return "", nil
    70  	}
    71  	// If source is a raw directory, we need to append the file:// prefix
    72  	// so it can be used as a URL.
    73  	defaultURL := source
    74  	u, err := url.Parse(source)
    75  	if err != nil {
    76  		return "", fmt.Errorf("invalid default tools URL %s: %v", defaultURL, err)
    77  	}
    78  	if u.Scheme == "" {
    79  		defaultURL = "file://" + defaultURL
    80  		if !strings.HasSuffix(defaultURL, "/"+storage.BaseToolsPath) {
    81  			defaultURL = fmt.Sprintf("%s/%s", defaultURL, storage.BaseToolsPath)
    82  		}
    83  	}
    84  	return defaultURL, nil
    85  }