github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/provider/gce/environ.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package gce
     5  
     6  import (
     7  	"sync"
     8  
     9  	"github.com/juju/errors"
    10  
    11  	"github.com/juju/juju/environs"
    12  	"github.com/juju/juju/environs/config"
    13  	"github.com/juju/juju/environs/simplestreams"
    14  	"github.com/juju/juju/network"
    15  	"github.com/juju/juju/provider/common"
    16  	"github.com/juju/juju/provider/gce/google"
    17  )
    18  
    19  // Note: This provider/environment does *not* implement storage.
    20  
    21  type gceConnection interface {
    22  	VerifyCredentials() error
    23  
    24  	// Instance gets the up-to-date info about the given instance
    25  	// and returns it.
    26  	Instance(id, zone string) (google.Instance, error)
    27  	Instances(prefix string, statuses ...string) ([]google.Instance, error)
    28  	AddInstance(spec google.InstanceSpec, zones ...string) (*google.Instance, error)
    29  	RemoveInstances(prefix string, ids ...string) error
    30  
    31  	Ports(fwname string) ([]network.PortRange, error)
    32  	OpenPorts(fwname string, ports ...network.PortRange) error
    33  	ClosePorts(fwname string, ports ...network.PortRange) error
    34  
    35  	AvailabilityZones(region string) ([]google.AvailabilityZone, error)
    36  }
    37  
    38  type environ struct {
    39  	common.SupportsUnitPlacementPolicy
    40  
    41  	name string
    42  	uuid string
    43  	gce  gceConnection
    44  
    45  	lock sync.Mutex
    46  	ecfg *environConfig
    47  
    48  	archLock               sync.Mutex
    49  	supportedArchitectures []string
    50  }
    51  
    52  func newEnviron(cfg *config.Config) (*environ, error) {
    53  	ecfg, err := newValidConfig(cfg, configDefaults)
    54  	if err != nil {
    55  		return nil, errors.Annotate(err, "invalid config")
    56  	}
    57  
    58  	uuid, ok := ecfg.UUID()
    59  	if !ok {
    60  		return nil, errors.New("UUID not set")
    61  	}
    62  
    63  	// Connect and authenticate.
    64  	conn, err := newConnection(ecfg)
    65  	if err != nil {
    66  		return nil, errors.Trace(err)
    67  	}
    68  
    69  	env := &environ{
    70  		name: ecfg.Name(),
    71  		uuid: uuid,
    72  		ecfg: ecfg,
    73  		gce:  conn,
    74  	}
    75  	return env, nil
    76  }
    77  
    78  // Name returns the name of the environment.
    79  func (env *environ) Name() string {
    80  	return env.name
    81  }
    82  
    83  // Provider returns the environment provider that created this env.
    84  func (*environ) Provider() environs.EnvironProvider {
    85  	return providerInstance
    86  }
    87  
    88  // Region returns the CloudSpec to use for the provider, as configured.
    89  func (env *environ) Region() (simplestreams.CloudSpec, error) {
    90  	return env.cloudSpec(env.ecfg.region()), nil
    91  }
    92  
    93  func (env *environ) cloudSpec(region string) simplestreams.CloudSpec {
    94  	return simplestreams.CloudSpec{
    95  		Region:   region,
    96  		Endpoint: env.ecfg.imageEndpoint(),
    97  	}
    98  }
    99  
   100  // SetConfig updates the env's configuration.
   101  func (env *environ) SetConfig(cfg *config.Config) error {
   102  	env.lock.Lock()
   103  	defer env.lock.Unlock()
   104  
   105  	if env.ecfg == nil {
   106  		return errors.New("cannot set config on uninitialized env")
   107  	}
   108  
   109  	if err := env.ecfg.update(cfg); err != nil {
   110  		return errors.Annotate(err, "invalid config change")
   111  	}
   112  	return nil
   113  }
   114  
   115  var newConnection = func(ecfg *environConfig) (gceConnection, error) {
   116  	connCfg := ecfg.newConnection()
   117  	auth := ecfg.auth()
   118  	return google.Connect(connCfg, auth)
   119  }
   120  
   121  // getSnapshot returns a copy of the environment. This is useful for
   122  // ensuring the env you are using does not get changed by other code
   123  // while you are using it.
   124  func (env environ) getSnapshot() *environ {
   125  	return &env
   126  }
   127  
   128  // Config returns the configuration data with which the env was created.
   129  func (env *environ) Config() *config.Config {
   130  	return env.getSnapshot().ecfg.Config
   131  }
   132  
   133  var bootstrap = common.Bootstrap
   134  
   135  // Bootstrap creates a new instance, chosing the series and arch out of
   136  // available tools. The series and arch are returned along with a func
   137  // that must be called to finalize the bootstrap process by transferring
   138  // the tools and installing the initial juju state server.
   139  func (env *environ) Bootstrap(ctx environs.BootstrapContext, params environs.BootstrapParams) (arch, series string, _ environs.BootstrapFinalizer, _ error) {
   140  	return bootstrap(ctx, env, params)
   141  }
   142  
   143  var destroyEnv = common.Destroy
   144  
   145  // Destroy shuts down all known machines and destroys the rest of the
   146  // known environment.
   147  func (env *environ) Destroy() error {
   148  	ports, err := env.Ports()
   149  	if err != nil {
   150  		return errors.Trace(err)
   151  	}
   152  
   153  	if len(ports) > 0 {
   154  		if err := env.ClosePorts(ports); err != nil {
   155  			return errors.Trace(err)
   156  		}
   157  	}
   158  
   159  	return destroyEnv(env)
   160  }