launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/common/tools.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 errgo "launchpad.net/errgo/errors" 8 "launchpad.net/juju-core/environs" 9 "launchpad.net/juju-core/environs/config" 10 envtools "launchpad.net/juju-core/environs/tools" 11 "launchpad.net/juju-core/errors" 12 "launchpad.net/juju-core/state" 13 "launchpad.net/juju-core/state/api/params" 14 coretools "launchpad.net/juju-core/tools" 15 "launchpad.net/juju-core/version" 16 ) 17 18 type EntityFinderEnvironConfigGetter interface { 19 state.EntityFinder 20 EnvironConfig() (*config.Config, error) 21 } 22 23 // ToolsGetter implements a common Tools method for use by various 24 // facades. 25 type ToolsGetter struct { 26 st EntityFinderEnvironConfigGetter 27 getCanRead GetAuthFunc 28 } 29 30 // NewToolsGetter returns a new ToolsGetter. The GetAuthFunc will be 31 // used on each invocation of Tools to determine current permissions. 32 func NewToolsGetter(st EntityFinderEnvironConfigGetter, getCanRead GetAuthFunc) *ToolsGetter { 33 return &ToolsGetter{ 34 st: st, 35 getCanRead: getCanRead, 36 } 37 } 38 39 // Tools finds the tools necessary for the given agents. 40 func (t *ToolsGetter) Tools(args params.Entities) (params.ToolsResults, error) { 41 result := params.ToolsResults{ 42 Results: make([]params.ToolsResult, len(args.Entities)), 43 } 44 canRead, err := t.getCanRead() 45 if err != nil { 46 return result, mask(err) 47 } 48 agentVersion, cfg, err := t.getGlobalAgentVersion() 49 if err != nil { 50 return result, mask(err) 51 } 52 53 // SSLHostnameVerification defaults to true, so we need to 54 // invert that, for backwards-compatibility (older versions 55 // will have DisableSSLHostnameVerification: false by default). 56 disableSSLHostnameVerification := !cfg.SSLHostnameVerification() 57 env, err := environs.New(cfg) 58 if err != nil { 59 return result, mask(err) 60 } 61 for i, entity := range args.Entities { 62 agentTools, err := t.oneAgentTools(canRead, entity.Tag, agentVersion, env) 63 if err == nil { 64 result.Results[i].Tools = agentTools 65 result.Results[i].DisableSSLHostnameVerification = disableSSLHostnameVerification 66 } 67 result.Results[i].Error = ServerError(err) 68 } 69 return result, nil 70 } 71 72 func (t *ToolsGetter) getGlobalAgentVersion() (version.Number, *config.Config, error) { 73 // Get the Agent Version requested in the Environment Config 74 nothing := version.Number{} 75 cfg, err := t.st.EnvironConfig() 76 if err != nil { 77 return nothing, nil, mask(err) 78 } 79 agentVersion, ok := cfg.AgentVersion() 80 if !ok { 81 return nothing, nil, errgo.Newf("agent version not set in environment config") 82 } 83 return agentVersion, cfg, nil 84 } 85 86 func (t *ToolsGetter) oneAgentTools(canRead AuthFunc, tag string, agentVersion version.Number, env environs.Environ) (*coretools.Tools, error) { 87 if !canRead(tag) { 88 return nil, ErrPerm 89 } 90 entity, err := t.st.FindEntity(tag) 91 if err != nil { 92 return nil, mask(err, errors.IsNotFoundError) 93 } 94 tooler, ok := entity.(state.AgentTooler) 95 if !ok { 96 return nil, NotSupportedError(tag, "agent tools") 97 } 98 existingTools, err := tooler.AgentTools() 99 if err != nil { 100 return nil, mask(err) 101 } 102 // TODO(jam): Avoid searching the provider for every machine 103 // that wants to upgrade. The information could just be cached 104 // in state, or even in the API servers 105 return envtools.FindExactTools(env, agentVersion, existingTools.Version.Series, existingTools.Version.Arch) 106 }