LEFT | RIGHT |
1 package server_test | 1 package server_test |
2 | 2 |
3 import ( | 3 import ( |
4 "fmt" | 4 "fmt" |
5 "io/ioutil" | 5 "io/ioutil" |
6 . "launchpad.net/gocheck" | 6 . "launchpad.net/gocheck" |
7 "launchpad.net/juju-core/charm" | 7 "launchpad.net/juju-core/charm" |
8 "launchpad.net/juju-core/cmd/jujuc/server" | 8 "launchpad.net/juju-core/cmd/jujuc/server" |
9 "launchpad.net/juju-core/state" | 9 "launchpad.net/juju-core/state" |
10 "launchpad.net/juju-core/state/testing" | 10 "launchpad.net/juju-core/state/testing" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 AssertEnvContains(c, lines, map[string]string{ | 94 AssertEnvContains(c, lines, map[string]string{ |
95 "PATH": os.Getenv("PATH"), | 95 "PATH": os.Getenv("PATH"), |
96 "DEBIAN_FRONTEND": "noninteractive", | 96 "DEBIAN_FRONTEND": "noninteractive", |
97 "APT_LISTCHANGES_FRONTEND": "none", | 97 "APT_LISTCHANGES_FRONTEND": "none", |
98 "CHARM_DIR": charmDir, | 98 "CHARM_DIR": charmDir, |
99 "JUJU_AGENT_SOCKET": "/path/to/socket", | 99 "JUJU_AGENT_SOCKET": "/path/to/socket", |
100 }) | 100 }) |
101 } | 101 } |
102 | 102 |
103 var runHookTests = []struct { | 103 var runHookTests = []struct { |
104 » relid int | 104 » summary string |
105 » remote string | 105 » relid int |
106 » perms os.FileMode | 106 » remote string |
107 » code int | 107 » perms os.FileMode |
108 » err string | 108 » code int |
109 » env map[string]string | 109 » err string |
| 110 » env map[string]string |
110 }{ | 111 }{ |
111 » // Missing hook is not an error. | 112 » { |
112 » {-1, "", 0, 0, "", nil}, | 113 » » summary: "missing hook is not an error", |
113 » // Report failure to execute hook. | 114 » » relid: -1, |
114 » {-1, "", 0600, 0, `exec: .*something-happened": permission denied`, nil}
, | 115 » }, { |
115 » // Report error indicated by hook's exit status. | 116 » » summary: "report failure to execute hook", |
116 » {-1, "", 0700, 99, `exit status 99`, nil}, | 117 » » relid: -1, |
117 » // Check shell environment for non-relation hook context. | 118 » » perms: 0600, |
118 » {-1, "", 0700, 0, "", map[string]string{ | 119 » » err: `exec: .*something-happened": permission denied`, |
119 » » "JUJU_UNIT_NAME": "u/0", | 120 » }, { |
120 » }}, | 121 » » summary: "report error indicated by hook's exit status", |
121 » // Check shell environment for relation-broken hook context. | 122 » » relid: -1, |
122 » {0, "", 0700, 0, "", map[string]string{ | 123 » » perms: 0700, |
123 » » "JUJU_UNIT_NAME": "u/0", | 124 » » code: 99, |
124 » » "JUJU_RELATION": "peer0", | 125 » » err: "exit status 99", |
125 » » "JUJU_RELATION_ID": "peer0:0", | 126 » }, { |
126 » }}, | 127 » » summary: "check shell environment for non-relation hook context"
, |
127 » // Check shell environment for normal relation hook context. | 128 » » relid: -1, |
128 » {0, "u/1", 0700, 0, "", map[string]string{ | 129 » » perms: 0700, |
129 » » "JUJU_UNIT_NAME": "u/0", | 130 » » env: map[string]string{ |
130 » » "JUJU_RELATION": "peer0", | 131 » » » "JUJU_UNIT_NAME": "u/0", |
131 » » "JUJU_RELATION_ID": "peer0:0", | 132 » » }, |
132 » » "JUJU_REMOTE_UNIT": "u/1", | 133 » }, { |
133 » }}, | 134 » » summary: "check shell environment for relation-broken hook conte
xt", |
| 135 » » relid: 1, |
| 136 » » perms: 0700, |
| 137 » » env: map[string]string{ |
| 138 » » » "JUJU_UNIT_NAME": "u/0", |
| 139 » » » "JUJU_RELATION": "peer1", |
| 140 » » » "JUJU_RELATION_ID": "peer1:1", |
| 141 » » }, |
| 142 » }, { |
| 143 » » summary: "check shell environment for relation hook context", |
| 144 » » relid: 1, |
| 145 » » remote: "u/1", |
| 146 » » perms: 0700, |
| 147 » » env: map[string]string{ |
| 148 » » » "JUJU_UNIT_NAME": "u/0", |
| 149 » » » "JUJU_RELATION": "peer1", |
| 150 » » » "JUJU_RELATION_ID": "peer1:1", |
| 151 » » » "JUJU_REMOTE_UNIT": "u/1", |
| 152 » » }, |
| 153 » }, |
134 } | 154 } |
135 | 155 |
136 func (s *RunHookSuite) TestRunHook(c *C) { | 156 func (s *RunHookSuite) TestRunHook(c *C) { |
137 for i, t := range runHookTests { | 157 for i, t := range runHookTests { |
138 » » c.Logf("test %d", i) | 158 » » c.Logf("test %d: %s", i, t.summary) |
139 ctx := s.GetHookContext(c, t.relid, t.remote) | 159 ctx := s.GetHookContext(c, t.relid, t.remote) |
140 var charmDir, outPath string | 160 var charmDir, outPath string |
141 if t.perms == 0 { | 161 if t.perms == 0 { |
142 charmDir = c.MkDir() | 162 charmDir = c.MkDir() |
143 } else { | 163 } else { |
144 charmDir, outPath = makeCharm(c, "something-happened", t
.perms, t.code) | 164 charmDir, outPath = makeCharm(c, "something-happened", t
.perms, t.code) |
145 } | 165 } |
146 err := ctx.RunHook("something-happened", charmDir, "/path/to/soc
ket") | 166 err := ctx.RunHook("something-happened", charmDir, "/path/to/soc
ket") |
147 if t.err == "" { | 167 if t.err == "" { |
148 c.Assert(err, IsNil) | 168 c.Assert(err, IsNil) |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 c.Assert(err, IsNil) | 267 c.Assert(err, IsNil) |
248 s.ru, err = s.rel.Unit(unit) | 268 s.ru, err = s.rel.Unit(unit) |
249 c.Assert(err, IsNil) | 269 c.Assert(err, IsNil) |
250 // Quickest way to get needed ZK paths in place: | 270 // Quickest way to get needed ZK paths in place: |
251 p, err := s.ru.Join() | 271 p, err := s.ru.Join() |
252 c.Assert(err, IsNil) | 272 c.Assert(err, IsNil) |
253 err = p.Kill() | 273 err = p.Kill() |
254 c.Assert(err, IsNil) | 274 c.Assert(err, IsNil) |
255 } | 275 } |
256 | 276 |
257 func (s *RelationContextSuite) TestUpdateMembers(c *C) { | 277 func (s *RelationContextSuite) TestSetMembers(c *C) { |
258 ctx := server.NewRelationContext(s.ru, nil) | 278 ctx := server.NewRelationContext(s.ru, nil) |
259 c.Assert(ctx.Units(), HasLen, 0) | 279 c.Assert(ctx.Units(), HasLen, 0) |
260 | 280 |
261 // Check the units and settings after a simple update. | 281 // Check the units and settings after a simple update. |
262 » ctx.Update(map[string]map[string]interface{}{ | 282 » ctx.SetMembers(server.SettingsMap{ |
263 "u/2": {"baz": 2}, | 283 "u/2": {"baz": 2}, |
264 }) | 284 }) |
265 c.Assert(ctx.Units(), DeepEquals, []string{"u/2"}) | 285 c.Assert(ctx.Units(), DeepEquals, []string{"u/2"}) |
266 settings, err := ctx.ReadSettings("u/2") | 286 settings, err := ctx.ReadSettings("u/2") |
267 c.Assert(err, IsNil) | 287 c.Assert(err, IsNil) |
268 c.Assert(settings, DeepEquals, map[string]interface{}{"baz": 2}) | 288 c.Assert(settings, DeepEquals, map[string]interface{}{"baz": 2}) |
269 | 289 |
270 // Check that a second update entirely overwrites the first. | 290 // Check that a second update entirely overwrites the first. |
271 » ctx.Update(map[string]map[string]interface{}{ | 291 » ctx.SetMembers(server.SettingsMap{ |
272 "u/1": {"foo": 1}, | 292 "u/1": {"foo": 1}, |
273 "u/3": {"bar": 3}, | 293 "u/3": {"bar": 3}, |
274 }) | 294 }) |
275 c.Assert(ctx.Units(), DeepEquals, []string{"u/1", "u/3"}) | 295 c.Assert(ctx.Units(), DeepEquals, []string{"u/1", "u/3"}) |
276 | 296 |
277 // Check that the second settings were cached. | 297 // Check that the second settings were cached. |
278 settings, err = ctx.ReadSettings("u/1") | 298 settings, err = ctx.ReadSettings("u/1") |
279 c.Assert(err, IsNil) | 299 c.Assert(err, IsNil) |
280 c.Assert(settings, DeepEquals, map[string]interface{}{"foo": 1}) | 300 c.Assert(settings, DeepEquals, map[string]interface{}{"foo": 1}) |
281 settings, err = ctx.ReadSettings("u/3") | 301 settings, err = ctx.ReadSettings("u/3") |
(...skipping 24 matching lines...) Expand all Loading... |
306 c.Assert(settings, DeepEquals, expect) | 326 c.Assert(settings, DeepEquals, expect) |
307 | 327 |
308 // Check that changes to state do not affect the cached settings. | 328 // Check that changes to state do not affect the cached settings. |
309 node.Set("ping", "pow") | 329 node.Set("ping", "pow") |
310 _, err = node.Write() | 330 _, err = node.Write() |
311 c.Assert(err, IsNil) | 331 c.Assert(err, IsNil) |
312 settings, err = ctx.ReadSettings("u/1") | 332 settings, err = ctx.ReadSettings("u/1") |
313 c.Assert(err, IsNil) | 333 c.Assert(err, IsNil) |
314 c.Assert(settings, DeepEquals, expect) | 334 c.Assert(settings, DeepEquals, expect) |
315 | 335 |
316 » // Check that flushing the context does not affect the cached settings. | 336 » // Check that ClearCache spares the members cache. |
317 » err = ctx.Flush(true) | 337 » ctx.ClearCache() |
318 » c.Assert(err, IsNil) | |
319 settings, err = ctx.ReadSettings("u/1") | 338 settings, err = ctx.ReadSettings("u/1") |
320 c.Assert(err, IsNil) | 339 c.Assert(err, IsNil) |
321 c.Assert(settings, DeepEquals, expect) | 340 c.Assert(settings, DeepEquals, expect) |
322 | 341 |
323 // Check that updating the context overwrites the cached settings, and | 342 // Check that updating the context overwrites the cached settings, and |
324 // that the contents of state are ignored. | 343 // that the contents of state are ignored. |
325 » ctx.Update(map[string]map[string]interface{}{"u/1": {"entirely": "differ
ent"}}) | 344 » ctx.SetMembers(server.SettingsMap{"u/1": {"entirely": "different"}}) |
326 settings, err = ctx.ReadSettings("u/1") | 345 settings, err = ctx.ReadSettings("u/1") |
327 c.Assert(err, IsNil) | 346 c.Assert(err, IsNil) |
328 c.Assert(settings, DeepEquals, map[string]interface{}{"entirely": "diffe
rent"}) | 347 c.Assert(settings, DeepEquals, map[string]interface{}{"entirely": "diffe
rent"}) |
329 } | 348 } |
330 | 349 |
331 func (s *RelationContextSuite) TestNonMemberCaching(c *C) { | 350 func (s *RelationContextSuite) TestNonMemberCaching(c *C) { |
332 unit, err := s.svc.AddUnit() | 351 unit, err := s.svc.AddUnit() |
333 c.Assert(err, IsNil) | 352 c.Assert(err, IsNil) |
334 ru, err := s.rel.Unit(unit) | 353 ru, err := s.rel.Unit(unit) |
335 c.Assert(err, IsNil) | 354 c.Assert(err, IsNil) |
(...skipping 11 matching lines...) Expand all Loading... |
347 c.Assert(settings, DeepEquals, expect) | 366 c.Assert(settings, DeepEquals, expect) |
348 | 367 |
349 // Check that changes to state do not affect the obtained settings... | 368 // Check that changes to state do not affect the obtained settings... |
350 node.Set("ping", "pow") | 369 node.Set("ping", "pow") |
351 _, err = node.Write() | 370 _, err = node.Write() |
352 c.Assert(err, IsNil) | 371 c.Assert(err, IsNil) |
353 settings, err = ctx.ReadSettings("u/1") | 372 settings, err = ctx.ReadSettings("u/1") |
354 c.Assert(err, IsNil) | 373 c.Assert(err, IsNil) |
355 c.Assert(settings, DeepEquals, expect) | 374 c.Assert(settings, DeepEquals, expect) |
356 | 375 |
357 » // ...until the context is flushed. | 376 » // ...until the caches are cleared. |
358 » err = ctx.Flush(true) | 377 » ctx.ClearCache() |
359 c.Assert(err, IsNil) | 378 c.Assert(err, IsNil) |
360 settings, err = ctx.ReadSettings("u/1") | 379 settings, err = ctx.ReadSettings("u/1") |
361 c.Assert(err, IsNil) | 380 c.Assert(err, IsNil) |
362 c.Assert(settings, DeepEquals, map[string]interface{}{"ping": "pow"}) | 381 c.Assert(settings, DeepEquals, map[string]interface{}{"ping": "pow"}) |
363 } | 382 } |
364 | 383 |
365 func (s *RelationContextSuite) TestSettings(c *C) { | 384 func (s *RelationContextSuite) TestSettings(c *C) { |
366 ctx := server.NewRelationContext(s.ru, nil) | 385 ctx := server.NewRelationContext(s.ru, nil) |
367 | 386 |
368 » // Change Settings, then flush without writing. | 387 » // Change Settings, then clear cache without writing. |
369 node, err := ctx.Settings() | 388 node, err := ctx.Settings() |
370 c.Assert(err, IsNil) | 389 c.Assert(err, IsNil) |
371 expect := node.Map() | 390 expect := node.Map() |
372 node.Set("change", "exciting") | 391 node.Set("change", "exciting") |
373 » ctx.Flush(false) | 392 » ctx.ClearCache() |
374 | 393 |
375 // Check that the change is not cached... | 394 // Check that the change is not cached... |
376 node, err = ctx.Settings() | 395 node, err = ctx.Settings() |
377 c.Assert(err, IsNil) | 396 c.Assert(err, IsNil) |
378 c.Assert(node.Map(), DeepEquals, expect) | 397 c.Assert(node.Map(), DeepEquals, expect) |
379 | 398 |
380 // ...and not written to state. | 399 // ...and not written to state. |
381 settings, err := s.ru.ReadSettings("u/0") | 400 settings, err := s.ru.ReadSettings("u/0") |
382 c.Assert(err, IsNil) | 401 c.Assert(err, IsNil) |
383 c.Assert(settings, DeepEquals, expect) | 402 c.Assert(settings, DeepEquals, expect) |
384 | 403 |
385 » // Change again, and flush with a write. | 404 » // Change again, write settings, and clear caches. |
386 node.Set("change", "exciting") | 405 node.Set("change", "exciting") |
387 » ctx.Flush(true) | 406 » err = ctx.WriteSettings() |
| 407 » c.Assert(err, IsNil) |
| 408 » ctx.ClearCache() |
388 | 409 |
389 // Check that the change is reflected in Settings... | 410 // Check that the change is reflected in Settings... |
390 expect["change"] = "exciting" | 411 expect["change"] = "exciting" |
391 node, err = ctx.Settings() | 412 node, err = ctx.Settings() |
392 c.Assert(err, IsNil) | 413 c.Assert(err, IsNil) |
393 c.Assert(node.Map(), DeepEquals, expect) | 414 c.Assert(node.Map(), DeepEquals, expect) |
394 | 415 |
395 » // ...and written to state. | 416 » // ...and was written to state. |
396 settings, err = s.ru.ReadSettings("u/0") | 417 settings, err = s.ru.ReadSettings("u/0") |
397 c.Assert(err, IsNil) | 418 c.Assert(err, IsNil) |
398 c.Assert(settings, DeepEquals, expect) | 419 c.Assert(settings, DeepEquals, expect) |
399 } | 420 } |
LEFT | RIGHT |