github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/provider/joyent/provider.go (about)

     1  // Copyright 2013 Joyent Inc.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package joyent
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/joyent/gosign/auth"
    11  	"github.com/juju/loggo"
    12  
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/environs/config"
    15  	"github.com/juju/juju/environs/imagemetadata"
    16  	"github.com/juju/juju/environs/simplestreams"
    17  	envtools "github.com/juju/juju/environs/tools"
    18  )
    19  
    20  var logger = loggo.GetLogger("juju.provider.joyent")
    21  
    22  type joyentProvider struct{}
    23  
    24  var providerInstance = joyentProvider{}
    25  var _ environs.EnvironProvider = providerInstance
    26  
    27  var _ simplestreams.HasRegion = (*joyentEnviron)(nil)
    28  var _ imagemetadata.SupportsCustomSources = (*joyentEnviron)(nil)
    29  var _ envtools.SupportsCustomSources = (*joyentEnviron)(nil)
    30  
    31  func init() {
    32  	environs.RegisterProvider("joyent", providerInstance)
    33  }
    34  
    35  var errNotImplemented = errors.New("not implemented in Joyent provider")
    36  
    37  func (joyentProvider) Prepare(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
    38  	preparedCfg, err := prepareConfig(cfg)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	return providerInstance.Open(preparedCfg)
    43  }
    44  
    45  func credentials(cfg *environConfig) (*auth.Credentials, error) {
    46  	authentication, err := auth.NewAuth(cfg.mantaUser(), cfg.privateKey(), cfg.algorithm())
    47  	if err != nil {
    48  		return nil, fmt.Errorf("cannot create credentials: %v", err)
    49  	}
    50  	return &auth.Credentials{
    51  		UserAuthentication: authentication,
    52  		MantaKeyId:         cfg.mantaKeyId(),
    53  		MantaEndpoint:      auth.Endpoint{URL: cfg.mantaUrl()},
    54  		SdcKeyId:           cfg.sdcKeyId(),
    55  		SdcEndpoint:        auth.Endpoint{URL: cfg.sdcUrl()},
    56  	}, nil
    57  }
    58  
    59  func (joyentProvider) Open(cfg *config.Config) (environs.Environ, error) {
    60  	env, err := newEnviron(cfg)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	return env, nil
    65  }
    66  
    67  func (joyentProvider) Validate(cfg, old *config.Config) (valid *config.Config, err error) {
    68  	newEcfg, err := validateConfig(cfg, old)
    69  	if err != nil {
    70  		return nil, fmt.Errorf("invalid Joyent provider config: %v", err)
    71  	}
    72  	return cfg.Apply(newEcfg.attrs)
    73  }
    74  
    75  func (joyentProvider) SecretAttrs(cfg *config.Config) (map[string]string, error) {
    76  	// If you keep configSecretFields up to date, this method should Just Work.
    77  	ecfg, err := validateConfig(cfg, nil)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	secretAttrs := map[string]string{}
    82  	for _, field := range configSecretFields {
    83  		if value, ok := ecfg.attrs[field]; ok {
    84  			if stringValue, ok := value.(string); ok {
    85  				secretAttrs[field] = stringValue
    86  			} else {
    87  				// All your secret attributes must be strings at the moment. Sorry.
    88  				// It's an expedient and hopefully temporary measure that helps us
    89  				// plug a security hole in the API.
    90  				return nil, fmt.Errorf(
    91  					"secret %q field must have a string value; got %v",
    92  					field, value,
    93  				)
    94  			}
    95  		}
    96  	}
    97  	return secretAttrs, nil
    98  }
    99  
   100  func (joyentProvider) BoilerplateConfig() string {
   101  	return boilerplateConfig
   102  
   103  }
   104  
   105  func GetProviderInstance() environs.EnvironProvider {
   106  	return providerInstance
   107  }
   108  
   109  // MetadataLookupParams returns parameters which are used to query image metadata to
   110  // find matching image information.
   111  func (p joyentProvider) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) {
   112  	if region == "" {
   113  		return nil, fmt.Errorf("region must be specified")
   114  	}
   115  	return &simplestreams.MetadataLookupParams{
   116  		Region:        region,
   117  		Architectures: []string{"amd64", "armhf"},
   118  	}, nil
   119  }
   120  
   121  func (p joyentProvider) newConfig(cfg *config.Config) (*environConfig, error) {
   122  	valid, err := p.Validate(cfg, nil)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	return &environConfig{valid, valid.UnknownAttrs()}, nil
   127  }