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 }