~rogpeppe/juju-core/438-local-instance-Addresses

« back to all changes in this revision

Viewing changes to state/apiserver/common/tools.go

[r=fwereade],[bug=1234035] Fix upgrade 1.14 -> 1.15

This adds a Tools() API call to provisioner API,
similarly to the upgrader API. Common code factored
out into apiserver/common/tools.go.

SetAgentTools() renamed to SetAgentVersion() in
machine and unit state types. Also renamed a few
types in params to be shorter or better reflect
what are they about. Added DEPRECATE(v1.18) tags
to bits of the API that need cleanup.

Live tested on EC2 - after copying the tools from
/tools/releases/ to /tools/ the upgrade proceeds
and finishes successfully.

https://codereview.appspot.com/14231044/

R=fwereade, jameinel

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package common
 
5
 
 
6
import (
 
7
        "fmt"
 
8
 
 
9
        "launchpad.net/juju-core/environs"
 
10
        "launchpad.net/juju-core/environs/config"
 
11
        envtools "launchpad.net/juju-core/environs/tools"
 
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, err
 
47
        }
 
48
        agentVersion, cfg, err := t.getGlobalAgentVersion()
 
49
        if err != nil {
 
50
                return result, err
 
51
        }
 
52
        env, err := environs.New(cfg)
 
53
        if err != nil {
 
54
                return result, err
 
55
        }
 
56
        for i, entity := range args.Entities {
 
57
                agentTools, err := t.oneAgentTools(canRead, entity.Tag, agentVersion, env)
 
58
                if err == nil {
 
59
                        result.Results[i].Tools = agentTools
 
60
                }
 
61
                result.Results[i].Error = ServerError(err)
 
62
        }
 
63
        return result, nil
 
64
}
 
65
 
 
66
func (t *ToolsGetter) getGlobalAgentVersion() (version.Number, *config.Config, error) {
 
67
        // Get the Agent Version requested in the Environment Config
 
68
        nothing := version.Number{}
 
69
        cfg, err := t.st.EnvironConfig()
 
70
        if err != nil {
 
71
                return nothing, nil, err
 
72
        }
 
73
        agentVersion, ok := cfg.AgentVersion()
 
74
        if !ok {
 
75
                return nothing, nil, fmt.Errorf("agent version not set in environment config")
 
76
        }
 
77
        return agentVersion, cfg, nil
 
78
}
 
79
 
 
80
func (t *ToolsGetter) oneAgentTools(canRead AuthFunc, tag string, agentVersion version.Number, env environs.Environ) (*coretools.Tools, error) {
 
81
        if !canRead(tag) {
 
82
                return nil, ErrPerm
 
83
        }
 
84
        entity, err := t.st.FindEntity(tag)
 
85
        if err != nil {
 
86
                return nil, err
 
87
        }
 
88
        tooler, ok := entity.(state.AgentTooler)
 
89
        if !ok {
 
90
                return nil, NotSupportedError(tag, "agent tools")
 
91
        }
 
92
        existingTools, err := tooler.AgentTools()
 
93
        if err != nil {
 
94
                return nil, err
 
95
        }
 
96
        // TODO(jam): Avoid searching the provider for every machine
 
97
        // that wants to upgrade. The information could just be cached
 
98
        // in state, or even in the API servers
 
99
        return envtools.FindExactTools(env, agentVersion, existingTools.Version.Series, existingTools.Version.Arch)
 
100
}