Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 package jujutest | 1 package jujutest |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 . "launchpad.net/gocheck" | 5 . "launchpad.net/gocheck" |
6 "launchpad.net/juju-core/charm" | 6 "launchpad.net/juju-core/charm" |
7 "launchpad.net/juju-core/environs" | 7 "launchpad.net/juju-core/environs" |
8 "launchpad.net/juju-core/environs/config" | 8 "launchpad.net/juju-core/environs/config" |
9 "launchpad.net/juju-core/juju" | 9 "launchpad.net/juju-core/juju" |
10 "launchpad.net/juju-core/state" | 10 "launchpad.net/juju-core/state" |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 | 176 |
177 // Wait for machine agent to come up on the bootstrap | 177 // Wait for machine agent to come up on the bootstrap |
178 // machine and find the deployed series from that. | 178 // machine and find the deployed series from that. |
179 // Wait for machine agent to come up on the bootstrap | 179 // Wait for machine agent to come up on the bootstrap |
180 // machine and find the deployed series from that. | 180 // machine and find the deployed series from that. |
181 m0, err := conn.State.Machine(0) | 181 m0, err := conn.State.Machine(0) |
182 c.Assert(err, IsNil) | 182 c.Assert(err, IsNil) |
183 w0 := newMachineToolWaiter(m0) | 183 w0 := newMachineToolWaiter(m0) |
184 defer w0.Stop() | 184 defer w0.Stop() |
185 | 185 |
186 » tools0 := waitAgentTools(c, w0) | 186 » tools0 := waitAgentTools(c, w0, version.Current) |
187 | 187 |
188 // Create a new service and deploy a unit of it. | 188 // Create a new service and deploy a unit of it. |
189 c.Logf("deploying service") | 189 c.Logf("deploying service") |
190 repoDir := c.MkDir() | 190 repoDir := c.MkDir() |
191 url := testing.Charms.ClonedURL(repoDir, tools0.Series, "dummy") | 191 url := testing.Charms.ClonedURL(repoDir, tools0.Series, "dummy") |
192 sch, err := conn.PutCharm(url, &charm.LocalRepository{repoDir}, false) | 192 sch, err := conn.PutCharm(url, &charm.LocalRepository{repoDir}, false) |
193 | 193 |
194 c.Assert(err, IsNil) | 194 c.Assert(err, IsNil) |
195 svc, err := conn.AddService("", sch) | 195 svc, err := conn.AddService("", sch) |
196 c.Assert(err, IsNil) | 196 c.Assert(err, IsNil) |
197 units, err := conn.AddUnits(svc, 1) | 197 units, err := conn.AddUnits(svc, 1) |
198 c.Assert(err, IsNil) | 198 c.Assert(err, IsNil) |
199 unit := units[0] | 199 unit := units[0] |
200 | 200 |
201 // Wait for the unit's machine and associated agent to come up | 201 // Wait for the unit's machine and associated agent to come up |
202 // and announce itself. | 202 // and announce itself. |
203 mid1, err := unit.AssignedMachineId() | 203 mid1, err := unit.AssignedMachineId() |
204 c.Assert(err, IsNil) | 204 c.Assert(err, IsNil) |
205 m1, err := conn.State.Machine(mid1) | 205 m1, err := conn.State.Machine(mid1) |
206 c.Assert(err, IsNil) | 206 c.Assert(err, IsNil) |
207 w1 := newMachineToolWaiter(m1) | 207 w1 := newMachineToolWaiter(m1) |
208 defer w1.Stop() | 208 defer w1.Stop() |
209 » tools1 := waitAgentTools(c, w1) | 209 » tools1 := waitAgentTools(c, w1, tools0.Binary) |
210 » c.Assert(tools1, NotNil) | 210 |
211 » c.Assert(tools1.Binary, Equals, tools0.Binary) | 211 » err = m1.Refresh() |
212 » instId1, err := w1.tooler.(*state.Machine).InstanceId() | 212 » c.Assert(err, IsNil) |
213 » instId1, err := m1.InstanceId() | |
213 c.Assert(err, IsNil) | 214 c.Assert(err, IsNil) |
214 | 215 |
215 // Check that we can upgrade the environment. | 216 // Check that we can upgrade the environment. |
216 newVersion := tools1.Binary | 217 newVersion := tools1.Binary |
217 newVersion.Patch++ | 218 newVersion.Patch++ |
218 t.checkUpgrade(c, conn, newVersion, w0, w1) | 219 t.checkUpgrade(c, conn, newVersion, w0, w1) |
219 | 220 |
220 // BUG(niemeyer): Logic below is very much wrong. Must be: | 221 // BUG(niemeyer): Logic below is very much wrong. Must be: |
221 // | 222 // |
222 // 1. EnsureDying on the unit and EnsureDying on the machine | 223 // 1. EnsureDying on the unit and EnsureDying on the machine |
223 // 2. Unit dies by itself | 224 // 2. Unit dies by itself |
224 // 3. Machine removes dead unit | 225 // 3. Machine removes dead unit |
225 // 4. Machine dies by itself | 226 // 4. Machine dies by itself |
226 // 5. Provisioner removes dead machine | 227 // 5. Provisioner removes dead machine |
227 // | 228 // |
228 | 229 |
229 // Now remove the unit and its assigned machine and | 230 // Now remove the unit and its assigned machine and |
230 // check that the PA removes it. | 231 // check that the PA removes it. |
231 c.Logf("removing unit") | 232 c.Logf("removing unit") |
232 err = unit.EnsureDead() | 233 err = unit.EnsureDead() |
233 c.Assert(err, IsNil) | 234 c.Assert(err, IsNil) |
234 err = svc.RemoveUnit(unit) | 235 err = svc.RemoveUnit(unit) |
235 c.Assert(err, IsNil) | 236 c.Assert(err, IsNil) |
236 » err = w1.EnsureDead() | 237 » err = m1.EnsureDead() |
237 c.Assert(err, IsNil) | 238 c.Assert(err, IsNil) |
238 err = conn.State.RemoveMachine(mid1) | 239 err = conn.State.RemoveMachine(mid1) |
239 c.Assert(err, IsNil) | 240 c.Assert(err, IsNil) |
240 | 241 |
241 c.Logf("waiting for instance to be removed") | 242 c.Logf("waiting for instance to be removed") |
242 t.assertStopInstance(c, conn.Environ, instId1) | 243 t.assertStopInstance(c, conn.Environ, instId1) |
243 } | 244 } |
244 | 245 |
245 type tooler interface { | 246 type tooler interface { |
246 Life() state.Life | 247 Life() state.Life |
247 EnsureDead() error | |
248 AgentTools() (*state.Tools, error) | 248 AgentTools() (*state.Tools, error) |
249 Refresh() error | 249 Refresh() error |
250 String() string | 250 String() string |
251 } | 251 } |
252 | 252 |
253 type watcher interface { | 253 type watcher interface { |
254 Stop() error | 254 Stop() error |
255 Err() error | 255 Err() error |
256 } | 256 } |
257 | 257 |
258 type toolsWaiter struct { | 258 type toolsWaiter struct { |
259 lastTools *state.Tools | 259 lastTools *state.Tools |
260 » changes chan struct{} | 260 » // changes is a chan of struct{} so that it can |
261 » watcher | 261 » // be used with different kinds of entity watcher. |
262 » tooler | 262 » changes chan struct{} |
263 » watcher watcher | |
264 » tooler tooler | |
263 } | 265 } |
264 | 266 |
265 func newMachineToolWaiter(m *state.Machine) *toolsWaiter { | 267 func newMachineToolWaiter(m *state.Machine) *toolsWaiter { |
266 w := m.Watch() | 268 w := m.Watch() |
267 waiter := &toolsWaiter{ | 269 waiter := &toolsWaiter{ |
268 changes: make(chan struct{}, 1), | 270 changes: make(chan struct{}, 1), |
269 watcher: w, | 271 watcher: w, |
270 tooler: m, | 272 tooler: m, |
271 } | 273 } |
272 go func() { | 274 go func() { |
273 for _ = range w.Changes() { | 275 for _ = range w.Changes() { |
niemeyer
2012/09/26 17:33:37
As far as I can see, this isn't doing anything use
rog
2012/09/27 11:38:44
currently it's not, but as implemented, a toolsWai
niemeyer
2012/09/27 13:15:23
A comment would be nice then, for the next person
rog
2012/09/27 14:08:30
i put a comment on the field.
| |
274 waiter.changes <- struct{}{} | 276 waiter.changes <- struct{}{} |
275 } | 277 } |
276 close(waiter.changes) | 278 close(waiter.changes) |
277 }() | 279 }() |
278 return waiter | 280 return waiter |
279 } | 281 } |
280 | 282 |
281 // nextTools returns the next changed tools. It returns | 283 func (w *toolsWaiter) Stop() error { |
282 // nil if the waiter dies. | 284 » return w.watcher.Stop() |
niemeyer
2012/09/26 17:33:37
It should return the error instead, as usual.
rog
2012/09/27 11:38:44
Done.
| |
283 func (w *toolsWaiter) NextTools(c *C) *state.Tools { | 285 } |
286 | |
287 // NextTools returns the next changed tools, waiting | |
288 // until the tools are actually set. | |
289 func (w *toolsWaiter) NextTools(c *C) (*state.Tools, error) { | |
284 for _ = range w.changes { | 290 for _ = range w.changes { |
285 » » w.Refresh() | 291 » » err := w.tooler.Refresh() |
286 » » if w.Life() == state.Dead { | 292 » » if err != nil { |
287 » » » return nil | 293 » » » return nil, fmt.Errorf("cannot refresh: %v", err) |
288 » » } | 294 » » } |
289 » » tools, err := w.AgentTools() | 295 » » if w.tooler.Life() == state.Dead { |
290 » » c.Assert(err, IsNil) | 296 » » » return nil, fmt.Errorf("object is dead") |
291 » » changed := w.lastTools == nil || *tools == *w.lastTools | 297 » » } |
niemeyer
2012/09/26 17:33:37
The second comparison is inverted. Is this working
rog
2012/09/27 11:38:44
that was indeed the bug i was looking for. thanks!
| |
298 » » tools, err := w.tooler.AgentTools() | |
299 » » if state.IsNotFound(err) { | |
300 » » » c.Logf("tools not yet set") | |
301 » » » continue | |
302 » » } | |
303 » » if err != nil { | |
304 » » » return nil, err | |
305 » » } | |
306 » » changed := w.lastTools == nil || *tools != *w.lastTools | |
292 w.lastTools = tools | 307 w.lastTools = tools |
293 if changed { | 308 if changed { |
294 » » » return tools | 309 » » » return tools, nil |
295 } | 310 } |
296 c.Logf("found same tools") | 311 c.Logf("found same tools") |
297 } | 312 } |
298 » c.Fatalf("watcher finished: %v", w.Err()) | 313 » return nil, fmt.Errorf("watcher closed prematurely: %v", w.watcher.Err() ) |
299 » panic("unreachable") | |
300 } | 314 } |
301 | 315 |
302 // waitAgentTools waits for the given agent | 316 // waitAgentTools waits for the given agent |
303 // to start and returns the tools that it is running. | 317 // to start and returns the tools that it is running. |
304 func waitAgentTools(c *C, w *toolsWaiter) *state.Tools { | 318 func waitAgentTools(c *C, w *toolsWaiter, expect version.Binary) *state.Tools { |
305 » c.Logf("waiting for %v to signal agent version", w) | 319 » c.Logf("waiting for %v to signal agent version", w.tooler.String()) |
306 | 320 » tools, err := w.NextTools(c) |
307 » var tools *state.Tools | 321 » c.Assert(err, IsNil) |
308 » for { | 322 » c.Check(tools.Binary, Equals, expect) |
309 » » tools = w.NextTools(c) | |
310 » » c.Assert(tools, NotNil) | |
niemeyer
2012/09/26 17:33:37
Assert(err, IsNil) would be better.
rog
2012/09/27 11:38:44
Done.
| |
311 » » if tools.URL == "" { | |
312 » » » // Agent hasn't started yet. | |
313 » » » continue | |
314 » » } | |
315 » » break | |
316 » } | |
317 » c.Assert(tools.Binary, Equals, version.Current) | |
318 return tools | 323 return tools |
319 } | 324 } |
320 | 325 |
321 // checkUpgrade sets the environment agent version and checks that | 326 // checkUpgrade sets the environment agent version and checks that |
322 // all the provided watchers upgrade to the requested version. | 327 // all the provided watchers upgrade to the requested version. |
323 func (t *LiveTests) checkUpgrade(c *C, conn *juju.Conn, newVersion version.Binar y, waiters ...*toolsWaiter) { | 328 func (t *LiveTests) checkUpgrade(c *C, conn *juju.Conn, newVersion version.Binar y, waiters ...*toolsWaiter) { |
324 c.Logf("putting testing version of juju tools") | 329 c.Logf("putting testing version of juju tools") |
325 upgradeTools, err := environs.PutTools(t.Env.Storage(), &newVersion) | 330 upgradeTools, err := environs.PutTools(t.Env.Storage(), &newVersion) |
326 c.Assert(err, IsNil) | 331 c.Assert(err, IsNil) |
327 | 332 |
328 // Check that the put version really is the version we expect. | 333 // Check that the put version really is the version we expect. |
329 c.Assert(upgradeTools.Binary, Equals, newVersion) | 334 c.Assert(upgradeTools.Binary, Equals, newVersion) |
330 err = setAgentVersion(conn.State, newVersion.Number) | 335 err = setAgentVersion(conn.State, newVersion.Number) |
331 c.Assert(err, IsNil) | 336 c.Assert(err, IsNil) |
332 | 337 |
333 for i, w := range waiters { | 338 for i, w := range waiters { |
334 » » c.Logf("waiting for upgrade of %d: %v", i, w.String()) | 339 » » c.Logf("waiting for upgrade of %d: %v", i, w.tooler.String()) |
335 | 340 |
336 » » tools := w.NextTools(c) | 341 » » waitAgentTools(c, w, newVersion) |
337 » » c.Assert(tools, NotNil) | 342 » » c.Logf("upgrade %d successful", i) |
niemeyer
2012/09/26 17:33:37
Ditto.
| |
338 » » // N.B. We can't test that the URL is the same because there's | |
339 » » // no guarantee that it is, even though it might be referring to | |
340 » » // the same thing. | |
341 » » if c.Check(tools.Binary, DeepEquals, newVersion) { | |
342 » » » c.Logf("upgrade %d successful", i) | |
343 » » } | |
344 } | 343 } |
345 } | 344 } |
346 | 345 |
347 // setAgentVersion sets the current agent version in the state's | 346 // setAgentVersion sets the current agent version in the state's |
348 // environment configuration. | 347 // environment configuration. |
349 func setAgentVersion(st *state.State, vers version.Number) error { | 348 func setAgentVersion(st *state.State, vers version.Number) error { |
350 cfg, err := st.EnvironConfig() | 349 cfg, err := st.EnvironConfig() |
351 if err != nil { | 350 if err != nil { |
352 return err | 351 return err |
353 } | 352 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 } | 482 } |
484 | 483 |
485 inst, err := t.Env.StartInstance(4, InvalidStateInfo, tools) | 484 inst, err := t.Env.StartInstance(4, InvalidStateInfo, tools) |
486 if inst != nil { | 485 if inst != nil { |
487 err := t.Env.StopInstances([]environs.Instance{inst}) | 486 err := t.Env.StopInstances([]environs.Instance{inst}) |
488 c.Check(err, IsNil) | 487 c.Check(err, IsNil) |
489 } | 488 } |
490 c.Assert(inst, IsNil) | 489 c.Assert(inst, IsNil) |
491 c.Assert(err, ErrorMatches, "cannot find image.*") | 490 c.Assert(err, ErrorMatches, "cannot find image.*") |
492 } | 491 } |
LEFT | RIGHT |