github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/apiserver/environment/toolsversionupdate.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package environment
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  
     9  	"github.com/juju/loggo"
    10  
    11  	"github.com/juju/juju/apiserver/common"
    12  	"github.com/juju/juju/environs"
    13  	"github.com/juju/juju/environs/config"
    14  	"github.com/juju/juju/environs/tools"
    15  	"github.com/juju/juju/state"
    16  	coretools "github.com/juju/juju/tools"
    17  	"github.com/juju/juju/version"
    18  )
    19  
    20  var logger = loggo.GetLogger("juju.apiserver.environment")
    21  
    22  var (
    23  	findTools = tools.FindTools
    24  )
    25  
    26  // EnvironGetter represents a struct that can provide a state.Environment.
    27  type EnvironGetter interface {
    28  	Environment() (*state.Environment, error)
    29  }
    30  
    31  type toolsFinder func(environs.Environ, int, int, string, coretools.Filter) (coretools.List, error)
    32  type envVersionUpdater func(*state.Environment, version.Number) error
    33  
    34  var newEnvirons = environs.New
    35  
    36  func checkToolsAvailability(cfg *config.Config, finder toolsFinder) (version.Number, error) {
    37  	currentVersion, ok := cfg.AgentVersion()
    38  	if !ok || currentVersion == version.Zero {
    39  		return version.Zero, nil
    40  	}
    41  
    42  	env, err := newEnvirons(cfg)
    43  	if err != nil {
    44  		return version.Zero, errors.Annotatef(err, "cannot make environ")
    45  	}
    46  
    47  	// finder receives major and minor as parameters as it uses them to filter versions and
    48  	// only return patches for the passed major.minor (from major.minor.patch).
    49  	vers, err := finder(env, currentVersion.Major, currentVersion.Minor, tools.ReleasedStream, coretools.Filter{})
    50  	if err != nil {
    51  		return version.Zero, errors.Annotatef(err, "canot find available tools")
    52  	}
    53  	// Newest also returns a list of the items in this list matching with the
    54  	// newest version.
    55  	newest, _ := vers.Newest()
    56  	return newest, nil
    57  }
    58  
    59  var envConfig = func(e *state.Environment) (*config.Config, error) {
    60  	return e.Config()
    61  }
    62  
    63  // Base implementation of envVersionUpdater
    64  func envVersionUpdate(env *state.Environment, ver version.Number) error {
    65  	return env.UpdateLatestToolsVersion(ver)
    66  }
    67  
    68  func updateToolsAvailability(st EnvironGetter, finder toolsFinder, update envVersionUpdater) error {
    69  	env, err := st.Environment()
    70  	if err != nil {
    71  		return errors.Annotate(err, "cannot get environment")
    72  	}
    73  	cfg, err := envConfig(env)
    74  	if err != nil {
    75  		return errors.Annotate(err, "cannot get config")
    76  	}
    77  	ver, err := checkToolsAvailability(cfg, finder)
    78  	if err != nil {
    79  		return errors.Annotate(err, "cannot get latest version")
    80  	}
    81  	if ver == version.Zero {
    82  		logger.Debugf("tools lookup returned version Zero, this should only happen during bootstrap.")
    83  		return nil
    84  	}
    85  	return update(env, ver)
    86  }
    87  
    88  // EnvironTools holds the required tools for an environ facade.
    89  type EnvironTools struct {
    90  	st         EnvironGetter
    91  	authorizer common.Authorizer
    92  	// tools lookup
    93  	findTools        toolsFinder
    94  	envVersionUpdate envVersionUpdater
    95  }
    96  
    97  // NewEnvironTools returns a new environ tools pointer with the passed attributes
    98  // and some defaults that are only for changed during tests.
    99  func NewEnvironTools(st EnvironGetter, authorizer common.Authorizer) *EnvironTools {
   100  	return &EnvironTools{
   101  		st:               st,
   102  		authorizer:       authorizer,
   103  		findTools:        findTools,
   104  		envVersionUpdate: envVersionUpdate,
   105  	}
   106  }
   107  
   108  // UpdateToolsAvailable invokes a lookup and further update in environ
   109  // for new patches of the current tool versions.
   110  func (e *EnvironTools) UpdateToolsAvailable() error {
   111  	if !e.authorizer.AuthEnvironManager() {
   112  		return common.ErrPerm
   113  	}
   114  	return updateToolsAvailability(e.st, e.findTools, e.envVersionUpdate)
   115  }