OLD | NEW |
1 package environs | 1 package environs |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 "launchpad.net/juju-core/environs/tools" | 5 "launchpad.net/juju-core/environs/tools" |
6 "launchpad.net/juju-core/log" | 6 "launchpad.net/juju-core/log" |
7 "launchpad.net/juju-core/state" | 7 "launchpad.net/juju-core/state" |
8 "launchpad.net/juju-core/version" | 8 "launchpad.net/juju-core/version" |
9 ) | 9 ) |
10 | 10 |
11 // ToolsList holds a list of available tools. Private tools take | 11 // ToolsList holds a list of available tools. Private tools take |
12 // precedence over public tools, even if they have a lower | 12 // precedence over public tools, even if they have a lower |
13 // version number. | 13 // version number. |
14 type ToolsList struct { | 14 type ToolsList struct { |
15 Private tools.List | 15 Private tools.List |
16 Public tools.List | 16 Public tools.List |
17 } | 17 } |
18 | 18 |
19 // ListTools returns a ToolsList holding all the tools | 19 // ListTools returns a ToolsList holding all the tools |
20 // available in the given environment that have the | 20 // available in the given environment that have the |
21 // given major version. | 21 // given major version. |
22 func ListTools(env Environ, majorVersion int) (*ToolsList, error) { | 22 func ListTools(env Environ, majorVersion int) (*ToolsList, error) { |
23 private, err := tools.ReadList(env.Storage(), majorVersion) | 23 private, err := tools.ReadList(env.Storage(), majorVersion) |
24 » if err != nil && err != tools.ErrNoMatches { | 24 » if err != nil && !isToolsError(err) { |
25 return nil, err | 25 return nil, err |
26 } | 26 } |
27 public, err := tools.ReadList(env.PublicStorage(), majorVersion) | 27 public, err := tools.ReadList(env.PublicStorage(), majorVersion) |
28 » if err != nil && err != tools.ErrNoMatches { | 28 » if err != nil && !isToolsError(err) { |
29 return nil, err | 29 return nil, err |
30 } | 30 } |
31 return &ToolsList{ | 31 return &ToolsList{ |
32 Private: private, | 32 Private: private, |
33 Public: public, | 33 Public: public, |
34 }, nil | 34 }, nil |
35 } | 35 } |
36 | 36 |
37 // BestTools returns the most recent version | 37 // BestTools returns the most recent version |
38 // from the set of tools in the ToolsList that are | 38 // from the set of tools in the ToolsList that are |
39 // compatible with the given version, using flags | 39 // compatible with the given version, using flags |
40 // to determine possible candidates. | 40 // to determine possible candidates. |
41 // It returns nil if no such tools are found. | 41 // It returns nil if no such tools are found. |
42 func BestTools(list *ToolsList, vers version.Binary, flags ToolsSearchFlags) *st
ate.Tools { | 42 func BestTools(list *ToolsList, vers version.Binary, flags ToolsSearchFlags) *st
ate.Tools { |
43 if flags&CompatVersion == 0 { | 43 if flags&CompatVersion == 0 { |
44 panic("CompatVersion not implemented") | 44 panic("CompatVersion not implemented") |
45 } | 45 } |
46 if tools := bestTools(list.Private, vers, flags); tools != nil { | 46 if tools := bestTools(list.Private, vers, flags); tools != nil { |
47 return tools | 47 return tools |
48 } | 48 } |
49 return bestTools(list.Public, vers, flags) | 49 return bestTools(list.Public, vers, flags) |
50 } | 50 } |
51 | 51 |
52 // bestTools is like BestTools but operates on a single list of tools. | 52 // bestTools is like BestTools but operates on a single list of tools. |
53 func bestTools(toolsList []*state.Tools, vers version.Binary, flags ToolsSearchF
lags) *state.Tools { | 53 func bestTools(toolsList []*state.Tools, vers version.Binary, flags ToolsSearchF
lags) *state.Tools { |
54 var bestTools *state.Tools | 54 var bestTools *state.Tools |
55 allowDev := vers.IsDev() || flags&DevVersion != 0 | 55 allowDev := vers.IsDev() || flags&DevVersion != 0 |
56 allowHigher := flags&HighestVersion != 0 | 56 allowHigher := flags&HighestVersion != 0 |
57 » log.Debugf("finding best tools for version: %v", vers) | 57 » log.Debugf("environs: finding best tools for version %v (dev=%v)", vers,
allowDev) |
58 for _, t := range toolsList { | 58 for _, t := range toolsList { |
59 » » log.Debugf("checking tools %v", t) | 59 » » log.Debugf("environs: checking tools %v", t) |
60 if t.Major != vers.Major || | 60 if t.Major != vers.Major || |
61 t.Series != vers.Series || | 61 t.Series != vers.Series || |
62 t.Arch != vers.Arch || | 62 t.Arch != vers.Arch || |
63 !allowDev && t.IsDev() || | 63 !allowDev && t.IsDev() || |
64 !allowHigher && vers.Number.Less(t.Number) { | 64 !allowHigher && vers.Number.Less(t.Number) { |
65 continue | 65 continue |
66 } | 66 } |
67 if bestTools == nil || bestTools.Number.Less(t.Number) { | 67 if bestTools == nil || bestTools.Number.Less(t.Number) { |
| 68 log.Debugf("environs: new best tools found: %v", t) |
68 bestTools = t | 69 bestTools = t |
69 } | 70 } |
70 } | 71 } |
71 return bestTools | 72 return bestTools |
72 } | 73 } |
73 | 74 |
74 // ToolsSearchFlags gives options when searching | 75 // ToolsSearchFlags gives options when searching |
75 // for tools. | 76 // for tools. |
76 type ToolsSearchFlags int | 77 type ToolsSearchFlags int |
77 | 78 |
(...skipping 24 matching lines...) Expand all Loading... |
102 toolsList, err := ListTools(env, vers.Major) | 103 toolsList, err := ListTools(env, vers.Major) |
103 if err != nil { | 104 if err != nil { |
104 return nil, err | 105 return nil, err |
105 } | 106 } |
106 tools := BestTools(toolsList, vers, flags) | 107 tools := BestTools(toolsList, vers, flags) |
107 if tools == nil { | 108 if tools == nil { |
108 return tools, &NotFoundError{fmt.Errorf("no compatible tools fou
nd")} | 109 return tools, &NotFoundError{fmt.Errorf("no compatible tools fou
nd")} |
109 } | 110 } |
110 return tools, nil | 111 return tools, nil |
111 } | 112 } |
| 113 |
| 114 // FindAvailableTools returns a tools.List containing all tools with a given |
| 115 // major version number available in the environment. |
| 116 // If *any* tools are present in private storage, *only* tools from private |
| 117 // storage are available. |
| 118 // If *no* tools are present in private storage, *only* tools from public |
| 119 // storage are available. |
| 120 // If no *available* tools have the supplied major version number, the function |
| 121 // returns a *NotFoundError. |
| 122 func FindAvailableTools(environ Environ, majorVersion int) (list tools.List, err
error) { |
| 123 defer convertToolsError(&err) |
| 124 list, err = tools.ReadList(environ.Storage(), majorVersion) |
| 125 if err == tools.ErrNoTools { |
| 126 list, err = tools.ReadList(environ.PublicStorage(), majorVersion
) |
| 127 } |
| 128 return list, err |
| 129 } |
| 130 |
| 131 // FindExactTools returns only the tools that match the supplied version. |
| 132 // TODO(fwereade) this should not exist: it's used by cmd/jujud/Upgrader, |
| 133 // which needs to run on every agent and must absolutely *not* in general |
| 134 // have access to an Environ. |
| 135 func FindExactTools(environ Environ, vers version.Binary) (t *state.Tools, err e
rror) { |
| 136 defer convertToolsError(&err) |
| 137 list, err := FindAvailableTools(environ, vers.Major) |
| 138 if err != nil { |
| 139 return nil, err |
| 140 } |
| 141 list, err = list.Match(tools.Filter{ |
| 142 Number: vers.Number, |
| 143 Series: vers.Series, |
| 144 Arch: vers.Arch, |
| 145 }) |
| 146 if err != nil { |
| 147 return nil, err |
| 148 } |
| 149 return list[0], nil |
| 150 } |
| 151 |
| 152 func isToolsError(err error) bool { |
| 153 switch err { |
| 154 case tools.ErrNoTools, tools.ErrNoMatches: |
| 155 return true |
| 156 } |
| 157 return false |
| 158 } |
| 159 |
| 160 func convertToolsError(err *error) { |
| 161 if isToolsError(*err) { |
| 162 *err = &NotFoundError{*err} |
| 163 } |
| 164 } |
OLD | NEW |