github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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  }