github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/provider/azure/environprovider.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azure 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "launchpad.net/gwacl" 10 11 "github.com/juju/juju/environs" 12 "github.com/juju/juju/environs/config" 13 ) 14 15 // Logger for the Azure provider. 16 var logger = loggo.GetLogger("juju.provider.azure") 17 18 type azureEnvironProvider struct{} 19 20 // azureEnvironProvider implements EnvironProvider. 21 var _ environs.EnvironProvider = (*azureEnvironProvider)(nil) 22 23 // Open is specified in the EnvironProvider interface. 24 func (prov azureEnvironProvider) Open(cfg *config.Config) (environs.Environ, error) { 25 logger.Debugf("opening environment %q.", cfg.Name()) 26 // We can't return NewEnviron(cfg) directly here because otherwise, 27 // when err is not nil, we end up with a non-nil returned environ and 28 // this breaks the loop in cmd/jujud/upgrade.go:run() (see 29 // http://golang.org/doc/faq#nil_error for the gory details). 30 environ, err := NewEnviron(cfg) 31 if err != nil { 32 return nil, err 33 } 34 return environ, nil 35 } 36 37 // RestrictedConfigAttributes is specified in the EnvironProvider interface. 38 func (prov azureEnvironProvider) RestrictedConfigAttributes() []string { 39 return []string{"location"} 40 } 41 42 // PrepareForCreateEnvironment is specified in the EnvironProvider interface. 43 func (p azureEnvironProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) { 44 // Set availability-sets-enabled to true 45 // by default, unless the user set a value. 46 if _, ok := cfg.AllAttrs()["availability-sets-enabled"]; !ok { 47 var err error 48 cfg, err = cfg.Apply(map[string]interface{}{"availability-sets-enabled": true}) 49 if err != nil { 50 return nil, errors.Trace(err) 51 } 52 } 53 return cfg, nil 54 } 55 56 // PrepareForBootstrap is specified in the EnvironProvider interface. 57 func (prov azureEnvironProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) { 58 cfg, err := prov.PrepareForCreateEnvironment(cfg) 59 if err != nil { 60 return nil, errors.Trace(err) 61 } 62 env, err := prov.Open(cfg) 63 if err != nil { 64 return nil, errors.Trace(err) 65 } 66 if ctx.ShouldVerifyCredentials() { 67 if err := verifyCredentials(env.(*azureEnviron)); err != nil { 68 return nil, errors.Trace(err) 69 } 70 } 71 return env, nil 72 } 73 74 // verifyCredentials issues a cheap, non-modifying request to Azure to 75 // verify the configured credentials. If verification fails, a user-friendly 76 // error will be returned, and the original error will be logged at debug 77 // level. 78 var verifyCredentials = func(e *azureEnviron) error { 79 _, err := e.updateStorageAccountKey(e.getSnapshot()) 80 switch err := errors.Cause(err).(type) { 81 case *gwacl.AzureError: 82 if err.Code == "ForbiddenError" { 83 logger.Debugf("azure request failed: %v", err) 84 return errors.New(`authentication failed 85 86 Please ensure the Azure subscription ID and certificate you have specified 87 are correct. You can obtain your subscription ID from the "Settings" page 88 in the Azure management console, where you can also upload a new certificate 89 if necessary.`) 90 } 91 } 92 return err 93 }