LEFT | RIGHT |
1 package main | 1 package main |
2 | 2 |
3 import ( | 3 import ( |
4 "bytes" | 4 "bytes" |
5 "fmt" | 5 "fmt" |
6 "io/ioutil" | 6 "io/ioutil" |
7 . "launchpad.net/gocheck" | 7 . "launchpad.net/gocheck" |
8 "launchpad.net/juju-core/environs" | 8 "launchpad.net/juju-core/environs" |
9 "launchpad.net/juju-core/environs/config" | 9 "launchpad.net/juju-core/environs/config" |
10 "launchpad.net/juju-core/environs/dummy" | 10 "launchpad.net/juju-core/environs/dummy" |
11 "launchpad.net/juju-core/juju" | |
12 "launchpad.net/juju-core/juju/testing" | 11 "launchpad.net/juju-core/juju/testing" |
13 "launchpad.net/juju-core/state" | 12 "launchpad.net/juju-core/state" |
14 coretesting "launchpad.net/juju-core/testing" | 13 coretesting "launchpad.net/juju-core/testing" |
15 "launchpad.net/juju-core/version" | 14 "launchpad.net/juju-core/version" |
16 "net/http" | 15 "net/http" |
17 "path/filepath" | 16 "path/filepath" |
18 "time" | 17 "time" |
19 ) | 18 ) |
20 | 19 |
21 var _ = Suite(&UpgraderSuite{}) | 20 var _ = Suite(&UpgraderSuite{}) |
(...skipping 12 matching lines...) Expand all Loading... |
34 version.Current = s.oldVersion | 33 version.Current = s.oldVersion |
35 s.JujuConnSuite.TearDownTest(c) | 34 s.JujuConnSuite.TearDownTest(c) |
36 } | 35 } |
37 | 36 |
38 func (s *UpgraderSuite) TestUpgraderStop(c *C) { | 37 func (s *UpgraderSuite) TestUpgraderStop(c *C) { |
39 u := startUpgrader(c, s.State, c.MkDir(), &state.Tools{Binary: version.C
urrent}) | 38 u := startUpgrader(c, s.State, c.MkDir(), &state.Tools{Binary: version.C
urrent}) |
40 err := u.Stop() | 39 err := u.Stop() |
41 c.Assert(err, IsNil) | 40 c.Assert(err, IsNil) |
42 } | 41 } |
43 | 42 |
| 43 func (s *UpgraderSuite) proposeVersion(c *C, vers version.Number, development bo
ol) { |
| 44 cfg, err := s.State.EnvironConfig() |
| 45 c.Assert(err, IsNil) |
| 46 attrs := cfg.AllAttrs() |
| 47 attrs["agent-version"] = vers.String() |
| 48 attrs["development"] = development |
| 49 newCfg, err := config.New(attrs) |
| 50 c.Assert(err, IsNil) |
| 51 err = s.State.SetEnvironConfig(newCfg) |
| 52 c.Assert(err, IsNil) |
| 53 } |
| 54 |
| 55 func (s *UpgraderSuite) uploadTools(c *C, vers version.Binary) *state.Tools { |
| 56 tgz := coretesting.TarGz( |
| 57 coretesting.NewTarFile("juju", 0777, "juju contents "+vers.Strin
g()), |
| 58 coretesting.NewTarFile("jujuc", 0777, "jujuc contents "+vers.Str
ing()), |
| 59 coretesting.NewTarFile("jujud", 0777, "jujud contents "+vers.Str
ing()), |
| 60 ) |
| 61 storage := s.Conn.Environ.Storage() |
| 62 err := storage.Put(environs.ToolsStoragePath(vers), bytes.NewReader(tgz)
, int64(len(tgz))) |
| 63 c.Assert(err, IsNil) |
| 64 url, err := s.Conn.Environ.Storage().URL(environs.ToolsStoragePath(vers)
) |
| 65 c.Assert(err, IsNil) |
| 66 return &state.Tools{URL: url, Binary: vers} |
| 67 } |
| 68 |
44 type proposal struct { | 69 type proposal struct { |
45 version string | 70 version string |
46 devVersion bool | 71 devVersion bool |
47 } | 72 } |
48 | 73 |
49 var upgraderTests = []struct { | 74 var upgraderTests = []struct { |
50 about string | 75 about string |
51 current string // current version. | 76 current string // current version. |
52 upload []string // Upload these tools versions. | 77 upload []string // Upload these tools versions. |
53 propose string // Propose this version... | 78 propose string // Propose this version... |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 propose: "2.0.5", | 113 propose: "2.0.5", |
89 upgradeTo: "2.0.5", | 114 upgradeTo: "2.0.5", |
90 }, { | 115 }, { |
91 about: "upgrade with no proposal", | 116 about: "upgrade with no proposal", |
92 current: "2.0.6-foo-bar", | 117 current: "2.0.6-foo-bar", |
93 upgradeTo: "2.0.5", | 118 upgradeTo: "2.0.5", |
94 }, | 119 }, |
95 } | 120 } |
96 | 121 |
97 func (s *UpgraderSuite) TestUpgrader(c *C) { | 122 func (s *UpgraderSuite) TestUpgrader(c *C) { |
98 » dataDir, currentTools := primeTools(c, s.Conn, version.MustParseBinary("
2.0.0-foo-bar")) | 123 » dataDir, currentTools := s.primeTools(c, version.MustParseBinary("2.0.0-
foo-bar")) |
99 // Remove the tools from the storage so that we're sure that the | 124 // Remove the tools from the storage so that we're sure that the |
100 // uploader isn't trying to fetch them. | 125 // uploader isn't trying to fetch them. |
101 resp, err := http.Get(currentTools.URL) | 126 resp, err := http.Get(currentTools.URL) |
102 c.Assert(err, IsNil) | 127 c.Assert(err, IsNil) |
103 err = environs.UnpackTools(dataDir, currentTools, resp.Body) | 128 err = environs.UnpackTools(dataDir, currentTools, resp.Body) |
104 c.Assert(err, IsNil) | 129 c.Assert(err, IsNil) |
105 s.removeVersion(c, currentTools.Binary) | 130 s.removeVersion(c, currentTools.Binary) |
106 | 131 |
107 var ( | 132 var ( |
108 u *Upgrader | 133 u *Upgrader |
109 upgraderDone <-chan error | 134 upgraderDone <-chan error |
110 ) | 135 ) |
111 | 136 |
112 defer func() { | 137 defer func() { |
113 if u != nil { | 138 if u != nil { |
114 c.Assert(u.Stop(), IsNil) | 139 c.Assert(u.Stop(), IsNil) |
115 } | 140 } |
116 }() | 141 }() |
117 | 142 |
118 uploaded := make(map[version.Number]*state.Tools) | 143 uploaded := make(map[version.Number]*state.Tools) |
119 for i, test := range upgraderTests { | 144 for i, test := range upgraderTests { |
120 c.Logf("%d. %s; current version: %v", i, test.about, version.Cur
rent) | 145 c.Logf("%d. %s; current version: %v", i, test.about, version.Cur
rent) |
121 for _, v := range test.upload { | 146 for _, v := range test.upload { |
122 vers := version.Current | 147 vers := version.Current |
123 vers.Number = version.MustParse(v) | 148 vers.Number = version.MustParse(v) |
124 » » » tools := uploadTools(c, s.Conn, vers) | 149 » » » tools := s.uploadTools(c, vers) |
125 uploaded[vers.Number] = tools | 150 uploaded[vers.Number] = tools |
126 } | 151 } |
127 if test.current != "" { | 152 if test.current != "" { |
128 version.Current = version.MustParseBinary(test.current) | 153 version.Current = version.MustParseBinary(test.current) |
129 currentTools, err = environs.ReadTools(dataDir, version.
Current) | 154 currentTools, err = environs.ReadTools(dataDir, version.
Current) |
130 c.Assert(err, IsNil) | 155 c.Assert(err, IsNil) |
131 } | 156 } |
132 if u == nil { | 157 if u == nil { |
133 u = startUpgrader(c, s.State, dataDir, currentTools) | 158 u = startUpgrader(c, s.State, dataDir, currentTools) |
134 } | 159 } |
135 if test.propose != "" { | 160 if test.propose != "" { |
136 » » » proposeVersion(c, s.State, version.MustParse(test.propos
e), test.devVersion) | 161 » » » s.proposeVersion(c, version.MustParse(test.propose), tes
t.devVersion) |
137 s.State.StartSync() | 162 s.State.StartSync() |
138 } | 163 } |
139 if test.upgradeTo == "" { | 164 if test.upgradeTo == "" { |
140 s.State.StartSync() | 165 s.State.StartSync() |
141 assertNothingHappens(c, upgraderDone) | 166 assertNothingHappens(c, upgraderDone) |
142 } else { | 167 } else { |
143 ug := waitDeath(c, u) | 168 ug := waitDeath(c, u) |
144 tools := uploaded[version.MustParse(test.upgradeTo)] | 169 tools := uploaded[version.MustParse(test.upgradeTo)] |
145 » » » c.Check(ug.Tools, DeepEquals, tools) | 170 » » » c.Check(ug.NewTools, DeepEquals, tools) |
146 c.Check(ug.OldTools.Binary, Equals, version.Current) | 171 c.Check(ug.OldTools.Binary, Equals, version.Current) |
147 c.Check(ug.DataDir, Equals, dataDir) | 172 c.Check(ug.DataDir, Equals, dataDir) |
148 c.Check(ug.AgentName, Equals, "testagent") | 173 c.Check(ug.AgentName, Equals, "testagent") |
149 | 174 |
150 // Check that the upgraded version was really downloaded
. | 175 // Check that the upgraded version was really downloaded
. |
151 data, err := ioutil.ReadFile(filepath.Join(environs.Tool
sDir(dataDir, tools.Binary), "jujud")) | 176 data, err := ioutil.ReadFile(filepath.Join(environs.Tool
sDir(dataDir, tools.Binary), "jujud")) |
152 c.Assert(err, IsNil) | 177 c.Assert(err, IsNil) |
153 c.Assert(string(data), Equals, "jujud contents "+tools.B
inary.String()) | 178 c.Assert(string(data), Equals, "jujud contents "+tools.B
inary.String()) |
154 | 179 |
155 u, upgraderDone = nil, nil | 180 u, upgraderDone = nil, nil |
(...skipping 28 matching lines...) Expand all Loading... |
184 upgraderKillDelay: 10 * time.Millisecond, | 209 upgraderKillDelay: 10 * time.Millisecond, |
185 err: "upgrader aborted download.*", | 210 err: "upgrader aborted download.*", |
186 }, { | 211 }, { |
187 about: "successful upgrade", | 212 about: "successful upgrade", |
188 upgraderKillDelay: time.Second, | 213 upgraderKillDelay: time.Second, |
189 propose: "2.0.6", | 214 propose: "2.0.6", |
190 // enough delay that the stop will probably arrive before the | 215 // enough delay that the stop will probably arrive before the |
191 // tools have downloaded, thus checking that the | 216 // tools have downloaded, thus checking that the |
192 // upgrader really did wait for the download. | 217 // upgrader really did wait for the download. |
193 storageDelay: 5 * time.Millisecond, | 218 storageDelay: 5 * time.Millisecond, |
194 » err: `must restart: agent has been upgraded`, | 219 » err: `must restart: an agent upgrade is available`, |
195 }, { | 220 }, { |
196 about: "fetch error", | 221 about: "fetch error", |
197 upgraderKillDelay: time.Second, | 222 upgraderKillDelay: time.Second, |
198 propose: "2.0.7", | 223 propose: "2.0.7", |
199 }, | 224 }, |
200 } | 225 } |
201 | 226 |
202 func (s *UpgraderSuite) TestDelayedStop(c *C) { | 227 func (s *UpgraderSuite) TestDelayedStop(c *C) { |
203 defer dummy.SetStorageDelay(0) | 228 defer dummy.SetStorageDelay(0) |
204 » dataDir, tools := primeTools(c, s.Conn, version.MustParseBinary("2.0.3-f
oo-bar")) | 229 » dataDir, tools := s.primeTools(c, version.MustParseBinary("2.0.3-foo-bar
")) |
205 » uploadTools(c, s.Conn, version.MustParseBinary("2.0.5-foo-bar")) | 230 » s.uploadTools(c, version.MustParseBinary("2.0.5-foo-bar")) |
206 » uploadTools(c, s.Conn, version.MustParseBinary("2.0.6-foo-bar")) | 231 » s.uploadTools(c, version.MustParseBinary("2.0.6-foo-bar")) |
207 » uploadTools(c, s.Conn, version.MustParseBinary("2.0.6-foo-bar")) | 232 » s.uploadTools(c, version.MustParseBinary("2.0.6-foo-bar")) |
208 » uploadTools(c, s.Conn, version.MustParseBinary("2.0.7-foo-bar")) | 233 » s.uploadTools(c, version.MustParseBinary("2.0.7-foo-bar")) |
209 s.poisonVersion(version.MustParseBinary("2.0.7-foo-bar")) | 234 s.poisonVersion(version.MustParseBinary("2.0.7-foo-bar")) |
210 | 235 |
211 for i, test := range delayedStopTests { | 236 for i, test := range delayedStopTests { |
212 c.Logf("%d. %v", i, test.about) | 237 c.Logf("%d. %v", i, test.about) |
213 upgraderKillDelay = test.upgraderKillDelay | 238 upgraderKillDelay = test.upgraderKillDelay |
214 dummy.SetStorageDelay(test.storageDelay) | 239 dummy.SetStorageDelay(test.storageDelay) |
215 proposed := version.MustParse(test.propose) | 240 proposed := version.MustParse(test.propose) |
216 » » proposeVersion(c, s.State, proposed, true) | 241 » » s.proposeVersion(c, proposed, true) |
217 u := startUpgrader(c, s.State, dataDir, tools) | 242 u := startUpgrader(c, s.State, dataDir, tools) |
218 t0 := time.Now() | 243 t0 := time.Now() |
219 err := u.Stop() | 244 err := u.Stop() |
220 d := time.Now().Sub(t0) | 245 d := time.Now().Sub(t0) |
221 if d > 100*time.Millisecond { | 246 if d > 100*time.Millisecond { |
222 c.Errorf("upgrader took took too long: %v", d) | 247 c.Errorf("upgrader took took too long: %v", d) |
223 } | 248 } |
224 if test.err == "" { | 249 if test.err == "" { |
225 c.Check(err, IsNil) | 250 c.Check(err, IsNil) |
226 } else { | 251 } else { |
227 c.Check(err, ErrorMatches, test.err) | 252 c.Check(err, ErrorMatches, test.err) |
228 } | 253 } |
229 } | 254 } |
230 } | 255 } |
231 | 256 |
232 func (s *UpgraderSuite) poisonVersion(vers version.Binary) { | 257 func (s *UpgraderSuite) poisonVersion(vers version.Binary) { |
233 path := environs.ToolsStoragePath(vers) | 258 path := environs.ToolsStoragePath(vers) |
234 dummy.Poison(s.Conn.Environ.Storage(), path, fmt.Errorf("poisoned file")
) | 259 dummy.Poison(s.Conn.Environ.Storage(), path, fmt.Errorf("poisoned file")
) |
235 } | 260 } |
236 | 261 |
237 func (s *UpgraderSuite) removeVersion(c *C, vers version.Binary) { | 262 func (s *UpgraderSuite) removeVersion(c *C, vers version.Binary) { |
238 path := environs.ToolsStoragePath(vers) | 263 path := environs.ToolsStoragePath(vers) |
239 err := s.Conn.Environ.Storage().Remove(path) | 264 err := s.Conn.Environ.Storage().Remove(path) |
240 c.Assert(err, IsNil) | 265 c.Assert(err, IsNil) |
241 } | 266 } |
242 | 267 |
| 268 // primeTools sets up the current version of the tools to vers and |
| 269 // makes sure that they're available in the returned dataDir. |
| 270 func (s *UpgraderSuite) primeTools(c *C, vers version.Binary) (dataDir string, t
ools *state.Tools) { |
| 271 dataDir = c.MkDir() |
| 272 // Set up the current version and tools. |
| 273 version.Current = vers |
| 274 tools = s.uploadTools(c, vers) |
| 275 resp, err := http.Get(tools.URL) |
| 276 c.Assert(err, IsNil) |
| 277 defer resp.Body.Close() |
| 278 err = environs.UnpackTools(dataDir, tools, resp.Body) |
| 279 c.Assert(err, IsNil) |
| 280 return dataDir, tools |
| 281 } |
| 282 |
243 func (s *UpgraderSuite) TestUpgraderReadyErrorUpgrade(c *C) { | 283 func (s *UpgraderSuite) TestUpgraderReadyErrorUpgrade(c *C) { |
244 » dataDir, currentTools := primeTools(c, s.Conn, version.MustParseBinary("
2.0.2-foo-bar")) | 284 » dataDir, currentTools := s.primeTools(c, version.MustParseBinary("2.0.2-
foo-bar")) |
245 ug := &UpgradeReadyError{ | 285 ug := &UpgradeReadyError{ |
246 AgentName: "foo", | 286 AgentName: "foo", |
247 OldTools: &state.Tools{Binary: version.MustParseBinary("2.0.0-f
oo-bar")}, | 287 OldTools: &state.Tools{Binary: version.MustParseBinary("2.0.0-f
oo-bar")}, |
248 » » Tools: currentTools, | 288 » » NewTools: currentTools, |
249 DataDir: dataDir, | 289 DataDir: dataDir, |
250 } | 290 } |
251 » err := ug.Upgrade() | 291 » err := ug.ChangeAgentTools() |
252 c.Assert(err, IsNil) | 292 c.Assert(err, IsNil) |
253 d := environs.AgentToolsDir(dataDir, "foo") | 293 d := environs.AgentToolsDir(dataDir, "foo") |
254 data, err := ioutil.ReadFile(filepath.Join(d, "jujud")) | 294 data, err := ioutil.ReadFile(filepath.Join(d, "jujud")) |
255 c.Assert(err, IsNil) | 295 c.Assert(err, IsNil) |
256 c.Assert(string(data), Equals, "jujud contents 2.0.2-foo-bar") | 296 c.Assert(string(data), Equals, "jujud contents 2.0.2-foo-bar") |
257 } | 297 } |
258 | 298 |
259 func assertNothingHappens(c *C, upgraderDone <-chan error) { | 299 func assertNothingHappens(c *C, upgraderDone <-chan error) { |
260 select { | 300 select { |
261 case got := <-upgraderDone: | 301 case got := <-upgraderDone: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 | 346 |
307 func (as testAgentState) SetAgentTools(tools *state.Tools) error { | 347 func (as testAgentState) SetAgentTools(tools *state.Tools) error { |
308 t := *tools | 348 t := *tools |
309 as <- &t | 349 as <- &t |
310 return nil | 350 return nil |
311 } | 351 } |
312 | 352 |
313 func (as testAgentState) PathKey() string { | 353 func (as testAgentState) PathKey() string { |
314 return "testagent" | 354 return "testagent" |
315 } | 355 } |
316 | |
317 func proposeVersion(c *C, st *state.State, vers version.Number, development bool
) { | |
318 cfg, err := st.EnvironConfig() | |
319 c.Assert(err, IsNil) | |
320 attrs := cfg.AllAttrs() | |
321 attrs["agent-version"] = vers.String() | |
322 attrs["development"] = development | |
323 newCfg, err := config.New(attrs) | |
324 c.Assert(err, IsNil) | |
325 err = st.SetEnvironConfig(newCfg) | |
326 c.Assert(err, IsNil) | |
327 } | |
328 | |
329 func uploadTools(c *C, conn *juju.Conn, vers version.Binary) *state.Tools { | |
330 tgz := coretesting.TarGz( | |
331 coretesting.NewTarFile("juju", 0777, "juju contents "+vers.Strin
g()), | |
332 coretesting.NewTarFile("jujuc", 0777, "jujuc contents "+vers.Str
ing()), | |
333 coretesting.NewTarFile("jujud", 0777, "jujud contents "+vers.Str
ing()), | |
334 ) | |
335 storage := conn.Environ.Storage() | |
336 err := storage.Put(environs.ToolsStoragePath(vers), bytes.NewReader(tgz)
, int64(len(tgz))) | |
337 c.Assert(err, IsNil) | |
338 url, err := conn.Environ.Storage().URL(environs.ToolsStoragePath(vers)) | |
339 c.Assert(err, IsNil) | |
340 return &state.Tools{URL: url, Binary: vers} | |
341 } | |
342 | |
343 // primeTools sets up the current version of the tools to vers and | |
344 // makes sure that they're available in the returned dataDir. | |
345 func primeTools(c *C, conn *juju.Conn, vers version.Binary) (dataDir string, too
ls *state.Tools) { | |
346 dataDir = c.MkDir() | |
347 // Set up the current version and tools. | |
348 version.Current = vers | |
349 tools = uploadTools(c, conn, vers) | |
350 resp, err := http.Get(tools.URL) | |
351 c.Assert(err, IsNil) | |
352 defer resp.Body.Close() | |
353 err = environs.UnpackTools(dataDir, tools, resp.Body) | |
354 c.Assert(err, IsNil) | |
355 return dataDir, tools | |
356 } | |
LEFT | RIGHT |