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 }