github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/cloudsigma/provider.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // Juju provider for CloudSigma
     5  
     6  package cloudsigma
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/jsonschema"
    13  	"github.com/juju/loggo"
    14  	"github.com/juju/utils"
    15  
    16  	"github.com/juju/juju/cloud"
    17  	"github.com/juju/juju/environs"
    18  	"github.com/juju/juju/environs/config"
    19  	"github.com/juju/juju/environs/context"
    20  	"github.com/juju/juju/environs/simplestreams"
    21  )
    22  
    23  var logger = loggo.GetLogger("juju.provider.cloudsigma")
    24  
    25  const (
    26  	providerType = "cloudsigma"
    27  )
    28  
    29  func getImageSource(env environs.Environ) (simplestreams.DataSource, error) {
    30  	e, ok := env.(*environ)
    31  	if !ok {
    32  		return nil, errors.NotSupportedf("non-cloudsigma model")
    33  	}
    34  	return simplestreams.NewURLDataSource(
    35  		"cloud images",
    36  		fmt.Sprintf(CloudsigmaCloudImagesURLTemplate, e.cloud.Region),
    37  		utils.VerifySSLHostnames,
    38  		simplestreams.SPECIFIC_CLOUD_DATA,
    39  		false,
    40  	), nil
    41  }
    42  
    43  type environProvider struct {
    44  	environProviderCredentials
    45  }
    46  
    47  var providerInstance = environProvider{}
    48  
    49  // check the provider implements environs.EnvironProvider interface
    50  var _ environs.CloudEnvironProvider = (*environProvider)(nil)
    51  
    52  func init() {
    53  	// This will only happen in binaries that actually import this provider
    54  	// somewhere. To enable a provider, import it in the "providers/all"
    55  	// package; please do *not* import individual providers anywhere else,
    56  	// except in direct tests for that provider.
    57  	environs.RegisterProvider("cloudsigma", providerInstance)
    58  	environs.RegisterImageDataSourceFunc("cloud sigma image source", getImageSource)
    59  }
    60  
    61  // Version is part of the EnvironProvider interface.
    62  func (environProvider) Version() int {
    63  	return 0
    64  }
    65  
    66  // Open opens the environment and returns it.
    67  // The configuration must have come from a previously
    68  // prepared environment.
    69  func (environProvider) Open(args environs.OpenParams) (environs.Environ, error) {
    70  	logger.Infof("opening model %q", args.Config.Name())
    71  	if err := validateCloudSpec(args.Cloud); err != nil {
    72  		return nil, errors.Annotate(err, "validating cloud spec")
    73  	}
    74  
    75  	client, err := newClient(args.Cloud, args.Config.UUID())
    76  	if err != nil {
    77  		return nil, errors.Trace(err)
    78  	}
    79  	env := &environ{
    80  		name:   args.Config.Name(),
    81  		cloud:  args.Cloud,
    82  		client: client,
    83  	}
    84  	if err := env.SetConfig(args.Config); err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	return env, nil
    89  }
    90  
    91  // CloudSchema returns the schema used to validate input for add-cloud.  Since
    92  // this provider does not support custom clouds, this always returns nil.
    93  func (p environProvider) CloudSchema() *jsonschema.Schema {
    94  	return nil
    95  }
    96  
    97  // Ping tests the connection to the cloud, to verify the endpoint is valid.
    98  func (p environProvider) Ping(ctx context.ProviderCallContext, endpoint string) error {
    99  	return errors.NotImplementedf("Ping")
   100  }
   101  
   102  // PrepareConfig is defined by EnvironProvider.
   103  func (environProvider) PrepareConfig(args environs.PrepareConfigParams) (*config.Config, error) {
   104  	if err := validateCloudSpec(args.Cloud); err != nil {
   105  		return nil, errors.Annotate(err, "validating cloud spec")
   106  	}
   107  	return args.Config, nil
   108  }
   109  
   110  // Validate ensures that config is a valid configuration for this
   111  // provider, applying changes to it if necessary, and returns the
   112  // validated configuration.
   113  // If old is not nil, it holds the previous environment configuration
   114  // for consideration when validating changes.
   115  func (environProvider) Validate(cfg, old *config.Config) (*config.Config, error) {
   116  	logger.Infof("validating model %q", cfg.Name())
   117  
   118  	// You should almost certainly not change this method; if you need to change
   119  	// how configs are validated, you should edit validateConfig itself, to ensure
   120  	// that your checks are always applied.
   121  	newEcfg, err := validateConfig(cfg, nil)
   122  	if err != nil {
   123  		return nil, errors.Errorf("invalid config: %v", err)
   124  	}
   125  	if old != nil {
   126  		oldEcfg, err := validateConfig(old, nil)
   127  		if err != nil {
   128  			return nil, errors.Errorf("invalid base config: %v", err)
   129  		}
   130  		if newEcfg, err = validateConfig(cfg, oldEcfg); err != nil {
   131  			return nil, errors.Errorf("invalid config change: %v", err)
   132  		}
   133  	}
   134  
   135  	return newEcfg.Config, nil
   136  }
   137  
   138  func validateCloudSpec(spec environs.CloudSpec) error {
   139  	if err := spec.Validate(); err != nil {
   140  		return errors.Trace(err)
   141  	}
   142  	if spec.Credential == nil {
   143  		return errors.NotValidf("missing credential")
   144  	}
   145  	if authType := spec.Credential.AuthType(); authType != cloud.UserPassAuthType {
   146  		return errors.NotSupportedf("%q auth-type", authType)
   147  	}
   148  	return nil
   149  }