Merge lp:~rogpeppe/juju-core/391-1.14-avoid-allFatal into lp:juju-core/1.14
- 391-1.14-avoid-allFatal
- Merge into 1.14
Proposed by
Roger Peppe
Status: | Merged |
---|---|
Approved by: | Roger Peppe |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1741 |
Proposed branch: | lp:~rogpeppe/juju-core/391-1.14-avoid-allFatal |
Merge into: | lp:juju-core/1.14 |
Diff against target: |
761 lines (+313/-65) 13 files modified
cmd/jujud/agent.go (+21/-0) cmd/jujud/agent_test.go (+66/-0) cmd/jujud/machine.go (+14/-8) cmd/jujud/machine_test.go (+6/-6) cmd/jujud/unit.go (+2/-2) juju/testing/conn.go (+48/-36) state/api/apiclient.go (+5/-4) state/apiserver/pinger_test.go (+12/-0) state/state.go (+6/-0) state/state_test.go (+6/-0) testing/checkers/set.go (+35/-0) testing/checkers/set_test.go (+54/-0) testing/mgo.go (+38/-9) |
To merge this branch: | bzr merge lp:~rogpeppe/juju-core/391-1.14-avoid-allFatal |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+185445@code.launchpad.net |
Commit message
cmd/jujud: avoid using allFatal
This is a backport of the https:/
now proposed for 1.14, with selected other patches from other revisions
to make it compile.
Description of the change
cmd/jujud: avoid using allFatal
This is a backport of the https:/
now proposed for 1.14, with selected other patches from other revisions
to make it compile.
To post a comment you must log in.
Revision history for this message
Roger Peppe (rogpeppe) wrote : | # |
Revision history for this message
Dimiter Naydenov (dimitern) wrote : | # |
Revision history for this message
William Reade (fwereade) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'cmd/jujud/agent.go' | |||
2 | --- cmd/jujud/agent.go 2013-09-11 06:27:05 +0000 | |||
3 | +++ cmd/jujud/agent.go 2013-09-13 09:26:01 +0000 | |||
4 | @@ -111,6 +111,27 @@ | |||
5 | 111 | return ok | 111 | return ok |
6 | 112 | } | 112 | } |
7 | 113 | 113 | ||
8 | 114 | type pinger interface { | ||
9 | 115 | Ping() error | ||
10 | 116 | } | ||
11 | 117 | |||
12 | 118 | // connectionIsFatal returns a function suitable for passing | ||
13 | 119 | // as the isFatal argument to worker.NewRunner, | ||
14 | 120 | // that diagnoses an error as fatal if the connection | ||
15 | 121 | // has failed or if the error is otherwise fatal. | ||
16 | 122 | func connectionIsFatal(conn pinger) func(err error) bool { | ||
17 | 123 | return func(err error) bool { | ||
18 | 124 | if isFatal(err) { | ||
19 | 125 | return true | ||
20 | 126 | } | ||
21 | 127 | if err := conn.Ping(); err != nil { | ||
22 | 128 | log.Infof("error pinging %T: %v", conn, err) | ||
23 | 129 | return true | ||
24 | 130 | } | ||
25 | 131 | return false | ||
26 | 132 | } | ||
27 | 133 | } | ||
28 | 134 | |||
29 | 114 | // isleep waits for the given duration or until it receives a value on | 135 | // isleep waits for the given duration or until it receives a value on |
30 | 115 | // stop. It returns whether the full duration was slept without being | 136 | // stop. It returns whether the full duration was slept without being |
31 | 116 | // stopped. | 137 | // stopped. |
32 | 117 | 138 | ||
33 | === modified file 'cmd/jujud/agent_test.go' | |||
34 | --- cmd/jujud/agent_test.go 2013-08-24 13:50:05 +0000 | |||
35 | +++ cmd/jujud/agent_test.go 2013-09-13 09:26:01 +0000 | |||
36 | @@ -20,7 +20,9 @@ | |||
37 | 20 | envtools "launchpad.net/juju-core/environs/tools" | 20 | envtools "launchpad.net/juju-core/environs/tools" |
38 | 21 | "launchpad.net/juju-core/juju/testing" | 21 | "launchpad.net/juju-core/juju/testing" |
39 | 22 | "launchpad.net/juju-core/state" | 22 | "launchpad.net/juju-core/state" |
40 | 23 | "launchpad.net/juju-core/state/api/params" | ||
41 | 23 | coretesting "launchpad.net/juju-core/testing" | 24 | coretesting "launchpad.net/juju-core/testing" |
42 | 25 | jc "launchpad.net/juju-core/testing/checkers" | ||
43 | 24 | coretools "launchpad.net/juju-core/tools" | 26 | coretools "launchpad.net/juju-core/tools" |
44 | 25 | "launchpad.net/juju-core/version" | 27 | "launchpad.net/juju-core/version" |
45 | 26 | "launchpad.net/juju-core/worker" | 28 | "launchpad.net/juju-core/worker" |
46 | @@ -48,6 +50,70 @@ | |||
47 | 48 | } | 50 | } |
48 | 49 | } | 51 | } |
49 | 50 | 52 | ||
50 | 53 | var isFatalTests = []struct { | ||
51 | 54 | err error | ||
52 | 55 | isFatal bool | ||
53 | 56 | }{{ | ||
54 | 57 | err: worker.ErrTerminateAgent, | ||
55 | 58 | isFatal: true, | ||
56 | 59 | }, { | ||
57 | 60 | err: &upgrader.UpgradeReadyError{}, | ||
58 | 61 | isFatal: true, | ||
59 | 62 | }, { | ||
60 | 63 | err: ¶ms.Error{ | ||
61 | 64 | Message: "blah", | ||
62 | 65 | Code: params.CodeNotProvisioned, | ||
63 | 66 | }, | ||
64 | 67 | isFatal: true, | ||
65 | 68 | }, { | ||
66 | 69 | err: &fatalError{"some fatal error"}, | ||
67 | 70 | isFatal: true, | ||
68 | 71 | }, { | ||
69 | 72 | err: stderrors.New("foo"), | ||
70 | 73 | isFatal: false, | ||
71 | 74 | }, { | ||
72 | 75 | err: ¶ms.Error{ | ||
73 | 76 | Message: "blah", | ||
74 | 77 | Code: params.CodeNotFound, | ||
75 | 78 | }, | ||
76 | 79 | isFatal: false, | ||
77 | 80 | }} | ||
78 | 81 | |||
79 | 82 | func (*toolSuite) TestIsFatal(c *gc.C) { | ||
80 | 83 | for i, test := range isFatalTests { | ||
81 | 84 | c.Logf("test %d: %s", i, test.err) | ||
82 | 85 | c.Assert(isFatal(test.err), gc.Equals, test.isFatal) | ||
83 | 86 | } | ||
84 | 87 | } | ||
85 | 88 | |||
86 | 89 | type testPinger func() error | ||
87 | 90 | |||
88 | 91 | func (f testPinger) Ping() error { | ||
89 | 92 | return f() | ||
90 | 93 | } | ||
91 | 94 | |||
92 | 95 | func (s *toolSuite) TestConnectionIsFatal(c *gc.C) { | ||
93 | 96 | var ( | ||
94 | 97 | errPinger testPinger = func() error { | ||
95 | 98 | return stderrors.New("ping error") | ||
96 | 99 | } | ||
97 | 100 | okPinger testPinger = func() error { | ||
98 | 101 | return nil | ||
99 | 102 | } | ||
100 | 103 | ) | ||
101 | 104 | for i, pinger := range []testPinger{errPinger, okPinger} { | ||
102 | 105 | for j, test := range isFatalTests { | ||
103 | 106 | c.Logf("test %d.%d: %s", i, j, test.err) | ||
104 | 107 | fatal := connectionIsFatal(pinger)(test.err) | ||
105 | 108 | if test.isFatal { | ||
106 | 109 | c.Check(fatal, jc.IsTrue) | ||
107 | 110 | } else { | ||
108 | 111 | c.Check(fatal, gc.Equals, i == 0) | ||
109 | 112 | } | ||
110 | 113 | } | ||
111 | 114 | } | ||
112 | 115 | } | ||
113 | 116 | |||
114 | 51 | func mkTools(s string) *coretools.Tools { | 117 | func mkTools(s string) *coretools.Tools { |
115 | 52 | return &coretools.Tools{ | 118 | return &coretools.Tools{ |
116 | 53 | Version: version.MustParseBinary(s + "-foo-bar"), | 119 | Version: version.MustParseBinary(s + "-foo-bar"), |
117 | 54 | 120 | ||
118 | === modified file 'cmd/jujud/machine.go' | |||
119 | --- cmd/jujud/machine.go 2013-09-11 06:27:05 +0000 | |||
120 | +++ cmd/jujud/machine.go 2013-09-13 09:26:01 +0000 | |||
121 | @@ -34,6 +34,16 @@ | |||
122 | 34 | "launchpad.net/juju-core/worker/upgrader" | 34 | "launchpad.net/juju-core/worker/upgrader" |
123 | 35 | ) | 35 | ) |
124 | 36 | 36 | ||
125 | 37 | type workerRunner interface { | ||
126 | 38 | worker.Worker | ||
127 | 39 | StartWorker(id string, startFunc func() (worker.Worker, error)) error | ||
128 | 40 | StopWorker(id string) error | ||
129 | 41 | } | ||
130 | 42 | |||
131 | 43 | var newRunner = func(isFatal func(error) bool, moreImportant func(e0, e1 error) bool) workerRunner { | ||
132 | 44 | return worker.NewRunner(isFatal, moreImportant) | ||
133 | 45 | } | ||
134 | 46 | |||
135 | 37 | const bootstrapMachineId = "0" | 47 | const bootstrapMachineId = "0" |
136 | 38 | 48 | ||
137 | 39 | var retryDelay = 3 * time.Second | 49 | var retryDelay = 3 * time.Second |
138 | @@ -44,7 +54,7 @@ | |||
139 | 44 | tomb tomb.Tomb | 54 | tomb tomb.Tomb |
140 | 45 | Conf AgentConf | 55 | Conf AgentConf |
141 | 46 | MachineId string | 56 | MachineId string |
143 | 47 | runner *worker.Runner | 57 | runner workerRunner |
144 | 48 | } | 58 | } |
145 | 49 | 59 | ||
146 | 50 | // Info returns usage information for the command. | 60 | // Info returns usage information for the command. |
147 | @@ -68,7 +78,7 @@ | |||
148 | 68 | if err := a.Conf.checkArgs(args); err != nil { | 78 | if err := a.Conf.checkArgs(args); err != nil { |
149 | 69 | return err | 79 | return err |
150 | 70 | } | 80 | } |
152 | 71 | a.runner = worker.NewRunner(isFatal, moreImportant) | 81 | a.runner = newRunner(isFatal, moreImportant) |
153 | 72 | return nil | 82 | return nil |
154 | 73 | } | 83 | } |
155 | 74 | 84 | ||
156 | @@ -127,10 +137,6 @@ | |||
157 | 127 | return err | 137 | return err |
158 | 128 | } | 138 | } |
159 | 129 | 139 | ||
160 | 130 | func allFatal(error) bool { | ||
161 | 131 | return true | ||
162 | 132 | } | ||
163 | 133 | |||
164 | 134 | var stateJobs = map[params.MachineJob]bool{ | 140 | var stateJobs = map[params.MachineJob]bool{ |
165 | 135 | params.JobHostUnits: true, | 141 | params.JobHostUnits: true, |
166 | 136 | params.JobManageEnviron: true, | 142 | params.JobManageEnviron: true, |
167 | @@ -164,7 +170,7 @@ | |||
168 | 164 | if needsStateWorker { | 170 | if needsStateWorker { |
169 | 165 | ensureStateWorker() | 171 | ensureStateWorker() |
170 | 166 | } | 172 | } |
172 | 167 | runner := worker.NewRunner(allFatal, moreImportant) | 173 | runner := newRunner(connectionIsFatal(st), moreImportant) |
173 | 168 | // Only the machiner currently connects to the API. | 174 | // Only the machiner currently connects to the API. |
174 | 169 | // Add other workers here as they are ready. | 175 | // Add other workers here as they are ready. |
175 | 170 | runner.StartWorker("machiner", func() (worker.Worker, error) { | 176 | runner.StartWorker("machiner", func() (worker.Worker, error) { |
176 | @@ -208,7 +214,7 @@ | |||
177 | 208 | // TODO(rog) use more discriminating test for errors | 214 | // TODO(rog) use more discriminating test for errors |
178 | 209 | // rather than taking everything down indiscriminately. | 215 | // rather than taking everything down indiscriminately. |
179 | 210 | dataDir := a.Conf.dataDir | 216 | dataDir := a.Conf.dataDir |
181 | 211 | runner := worker.NewRunner(allFatal, moreImportant) | 217 | runner := newRunner(connectionIsFatal(st), moreImportant) |
182 | 212 | // At this stage, since we don't embed lxc containers, just start an lxc | 218 | // At this stage, since we don't embed lxc containers, just start an lxc |
183 | 213 | // provisioner task for non-lxc containers. Since we have only LXC | 219 | // provisioner task for non-lxc containers. Since we have only LXC |
184 | 214 | // containers and normal machines, this effectively means that we only | 220 | // containers and normal machines, this effectively means that we only |
185 | 215 | 221 | ||
186 | === modified file 'cmd/jujud/machine_test.go' | |||
187 | --- cmd/jujud/machine_test.go 2013-09-11 06:27:05 +0000 | |||
188 | +++ cmd/jujud/machine_test.go 2013-09-13 09:26:01 +0000 | |||
189 | @@ -24,7 +24,7 @@ | |||
190 | 24 | "launchpad.net/juju-core/state/api/params" | 24 | "launchpad.net/juju-core/state/api/params" |
191 | 25 | "launchpad.net/juju-core/state/watcher" | 25 | "launchpad.net/juju-core/state/watcher" |
192 | 26 | "launchpad.net/juju-core/testing" | 26 | "launchpad.net/juju-core/testing" |
194 | 27 | "launchpad.net/juju-core/testing/checkers" | 27 | jc "launchpad.net/juju-core/testing/checkers" |
195 | 28 | "launchpad.net/juju-core/tools" | 28 | "launchpad.net/juju-core/tools" |
196 | 29 | "launchpad.net/juju-core/version" | 29 | "launchpad.net/juju-core/version" |
197 | 30 | "launchpad.net/juju-core/worker/deployer" | 30 | "launchpad.net/juju-core/worker/deployer" |
198 | @@ -33,7 +33,7 @@ | |||
199 | 33 | type MachineSuite struct { | 33 | type MachineSuite struct { |
200 | 34 | agentSuite | 34 | agentSuite |
201 | 35 | lxc.TestSuite | 35 | lxc.TestSuite |
203 | 36 | oldCacheDir string | 36 | restoreCacheDir jc.Restorer |
204 | 37 | } | 37 | } |
205 | 38 | 38 | ||
206 | 39 | var _ = gc.Suite(&MachineSuite{}) | 39 | var _ = gc.Suite(&MachineSuite{}) |
207 | @@ -41,11 +41,11 @@ | |||
208 | 41 | func (s *MachineSuite) SetUpSuite(c *gc.C) { | 41 | func (s *MachineSuite) SetUpSuite(c *gc.C) { |
209 | 42 | s.agentSuite.SetUpSuite(c) | 42 | s.agentSuite.SetUpSuite(c) |
210 | 43 | s.TestSuite.SetUpSuite(c) | 43 | s.TestSuite.SetUpSuite(c) |
212 | 44 | s.oldCacheDir = charm.CacheDir | 44 | s.restoreCacheDir = jc.Set(&charm.CacheDir, c.MkDir()) |
213 | 45 | } | 45 | } |
214 | 46 | 46 | ||
215 | 47 | func (s *MachineSuite) TearDownSuite(c *gc.C) { | 47 | func (s *MachineSuite) TearDownSuite(c *gc.C) { |
217 | 48 | charm.CacheDir = s.oldCacheDir | 48 | s.restoreCacheDir() |
218 | 49 | s.TestSuite.TearDownSuite(c) | 49 | s.TestSuite.TearDownSuite(c) |
219 | 50 | s.agentSuite.TearDownSuite(c) | 50 | s.agentSuite.TearDownSuite(c) |
220 | 51 | } | 51 | } |
221 | @@ -231,7 +231,7 @@ | |||
222 | 231 | if err == nil && attempt.HasNext() { | 231 | if err == nil && attempt.HasNext() { |
223 | 232 | continue | 232 | continue |
224 | 233 | } | 233 | } |
226 | 234 | c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) | 234 | c.Assert(err, jc.Satisfies, errors.IsNotFoundError) |
227 | 235 | } | 235 | } |
228 | 236 | 236 | ||
229 | 237 | // short-circuit-remove u1 after it's been deployed; check it's recalled | 237 | // short-circuit-remove u1 after it's been deployed; check it's recalled |
230 | @@ -239,7 +239,7 @@ | |||
231 | 239 | err = u1.Destroy() | 239 | err = u1.Destroy() |
232 | 240 | c.Assert(err, gc.IsNil) | 240 | c.Assert(err, gc.IsNil) |
233 | 241 | err = u1.Refresh() | 241 | err = u1.Refresh() |
235 | 242 | c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) | 242 | c.Assert(err, jc.Satisfies, errors.IsNotFoundError) |
236 | 243 | ctx.waitDeployed(c) | 243 | ctx.waitDeployed(c) |
237 | 244 | } | 244 | } |
238 | 245 | 245 | ||
239 | 246 | 246 | ||
240 | === modified file 'cmd/jujud/unit.go' | |||
241 | --- cmd/jujud/unit.go 2013-09-11 06:27:05 +0000 | |||
242 | +++ cmd/jujud/unit.go 2013-09-13 09:26:01 +0000 | |||
243 | @@ -85,7 +85,7 @@ | |||
244 | 85 | } | 85 | } |
245 | 86 | unit := entity.(*state.Unit) | 86 | unit := entity.(*state.Unit) |
246 | 87 | dataDir := a.Conf.dataDir | 87 | dataDir := a.Conf.dataDir |
248 | 88 | runner := worker.NewRunner(allFatal, moreImportant) | 88 | runner := worker.NewRunner(connectionIsFatal(st), moreImportant) |
249 | 89 | runner.StartWorker("uniter", func() (worker.Worker, error) { | 89 | runner.StartWorker("uniter", func() (worker.Worker, error) { |
250 | 90 | return uniter.NewUniter(st, unit.Name(), dataDir), nil | 90 | return uniter.NewUniter(st, unit.Name(), dataDir), nil |
251 | 91 | }) | 91 | }) |
252 | @@ -98,7 +98,7 @@ | |||
253 | 98 | return nil, err | 98 | return nil, err |
254 | 99 | } | 99 | } |
255 | 100 | dataDir := a.Conf.dataDir | 100 | dataDir := a.Conf.dataDir |
257 | 101 | runner := worker.NewRunner(allFatal, moreImportant) | 101 | runner := worker.NewRunner(connectionIsFatal(st), moreImportant) |
258 | 102 | runner.StartWorker("upgrader", func() (worker.Worker, error) { | 102 | runner.StartWorker("upgrader", func() (worker.Worker, error) { |
259 | 103 | return upgrader.New(st.Upgrader(), entity.Tag(), dataDir), nil | 103 | return upgrader.New(st.Upgrader(), entity.Tag(), dataDir), nil |
260 | 104 | }) | 104 | }) |
261 | 105 | 105 | ||
262 | === modified file 'juju/testing/conn.go' | |||
263 | --- juju/testing/conn.go 2013-09-11 06:27:05 +0000 | |||
264 | +++ juju/testing/conn.go 2013-09-13 09:26:01 +0000 | |||
265 | @@ -9,7 +9,7 @@ | |||
266 | 9 | "os" | 9 | "os" |
267 | 10 | "path/filepath" | 10 | "path/filepath" |
268 | 11 | 11 | ||
270 | 12 | . "launchpad.net/gocheck" | 12 | gc "launchpad.net/gocheck" |
271 | 13 | 13 | ||
272 | 14 | "launchpad.net/juju-core/charm" | 14 | "launchpad.net/juju-core/charm" |
273 | 15 | "launchpad.net/juju-core/constraints" | 15 | "launchpad.net/juju-core/constraints" |
274 | @@ -85,13 +85,13 @@ | |||
275 | 85 | 85 | ||
276 | 86 | // StartInstance is a test helper function that starts an instance on the | 86 | // StartInstance is a test helper function that starts an instance on the |
277 | 87 | // environment using the current series and invalid info states. | 87 | // environment using the current series and invalid info states. |
279 | 88 | func StartInstance(c *C, env environs.Environ, machineId string) (instance.Instance, *instance.HardwareCharacteristics) { | 88 | func StartInstance(c *gc.C, env environs.Environ, machineId string) (instance.Instance, *instance.HardwareCharacteristics) { |
280 | 89 | return StartInstanceWithConstraints(c, env, machineId, constraints.Value{}) | 89 | return StartInstanceWithConstraints(c, env, machineId, constraints.Value{}) |
281 | 90 | } | 90 | } |
282 | 91 | 91 | ||
283 | 92 | // StartInstanceWithConstraints is a test helper function that starts an instance on the | 92 | // StartInstanceWithConstraints is a test helper function that starts an instance on the |
284 | 93 | // environment with the specified constraints, using the current series and invalid info states. | 93 | // environment with the specified constraints, using the current series and invalid info states. |
286 | 94 | func StartInstanceWithConstraints(c *C, env environs.Environ, machineId string, | 94 | func StartInstanceWithConstraints(c *gc.C, env environs.Environ, machineId string, |
287 | 95 | cons constraints.Value) (instance.Instance, *instance.HardwareCharacteristics) { | 95 | cons constraints.Value) (instance.Instance, *instance.HardwareCharacteristics) { |
288 | 96 | series := config.DefaultSeries | 96 | series := config.DefaultSeries |
289 | 97 | inst, metadata, err := provider.StartInstance( | 97 | inst, metadata, err := provider.StartInstance( |
290 | @@ -103,7 +103,7 @@ | |||
291 | 103 | FakeStateInfo(machineId), | 103 | FakeStateInfo(machineId), |
292 | 104 | FakeAPIInfo(machineId), | 104 | FakeAPIInfo(machineId), |
293 | 105 | ) | 105 | ) |
295 | 106 | c.Assert(err, IsNil) | 106 | c.Assert(err, gc.IsNil) |
296 | 107 | return inst, metadata | 107 | return inst, metadata |
297 | 108 | } | 108 | } |
298 | 109 | 109 | ||
299 | @@ -119,24 +119,24 @@ | |||
300 | 119 | agent-version: %s | 119 | agent-version: %s |
301 | 120 | ` | 120 | ` |
302 | 121 | 121 | ||
304 | 122 | func (s *JujuConnSuite) SetUpSuite(c *C) { | 122 | func (s *JujuConnSuite) SetUpSuite(c *gc.C) { |
305 | 123 | s.LoggingSuite.SetUpSuite(c) | 123 | s.LoggingSuite.SetUpSuite(c) |
306 | 124 | s.MgoSuite.SetUpSuite(c) | 124 | s.MgoSuite.SetUpSuite(c) |
307 | 125 | } | 125 | } |
308 | 126 | 126 | ||
310 | 127 | func (s *JujuConnSuite) TearDownSuite(c *C) { | 127 | func (s *JujuConnSuite) TearDownSuite(c *gc.C) { |
311 | 128 | s.MgoSuite.TearDownSuite(c) | 128 | s.MgoSuite.TearDownSuite(c) |
312 | 129 | s.LoggingSuite.TearDownSuite(c) | 129 | s.LoggingSuite.TearDownSuite(c) |
313 | 130 | } | 130 | } |
314 | 131 | 131 | ||
316 | 132 | func (s *JujuConnSuite) SetUpTest(c *C) { | 132 | func (s *JujuConnSuite) SetUpTest(c *gc.C) { |
317 | 133 | s.oldJujuHome = config.SetJujuHome(c.MkDir()) | 133 | s.oldJujuHome = config.SetJujuHome(c.MkDir()) |
318 | 134 | s.LoggingSuite.SetUpTest(c) | 134 | s.LoggingSuite.SetUpTest(c) |
319 | 135 | s.MgoSuite.SetUpTest(c) | 135 | s.MgoSuite.SetUpTest(c) |
320 | 136 | s.setUpConn(c) | 136 | s.setUpConn(c) |
321 | 137 | } | 137 | } |
322 | 138 | 138 | ||
324 | 139 | func (s *JujuConnSuite) TearDownTest(c *C) { | 139 | func (s *JujuConnSuite) TearDownTest(c *gc.C) { |
325 | 140 | s.tearDownConn(c) | 140 | s.tearDownConn(c) |
326 | 141 | s.MgoSuite.TearDownTest(c) | 141 | s.MgoSuite.TearDownTest(c) |
327 | 142 | s.LoggingSuite.TearDownTest(c) | 142 | s.LoggingSuite.TearDownTest(c) |
328 | @@ -145,51 +145,63 @@ | |||
329 | 145 | 145 | ||
330 | 146 | // Reset returns environment state to that which existed at the start of | 146 | // Reset returns environment state to that which existed at the start of |
331 | 147 | // the test. | 147 | // the test. |
333 | 148 | func (s *JujuConnSuite) Reset(c *C) { | 148 | func (s *JujuConnSuite) Reset(c *gc.C) { |
334 | 149 | s.tearDownConn(c) | 149 | s.tearDownConn(c) |
335 | 150 | s.setUpConn(c) | 150 | s.setUpConn(c) |
336 | 151 | } | 151 | } |
337 | 152 | 152 | ||
339 | 153 | func (s *JujuConnSuite) StateInfo(c *C) *state.Info { | 153 | func (s *JujuConnSuite) StateInfo(c *gc.C) *state.Info { |
340 | 154 | info, _, err := s.Conn.Environ.StateInfo() | 154 | info, _, err := s.Conn.Environ.StateInfo() |
342 | 155 | c.Assert(err, IsNil) | 155 | c.Assert(err, gc.IsNil) |
343 | 156 | info.Password = "dummy-secret" | 156 | info.Password = "dummy-secret" |
344 | 157 | return info | 157 | return info |
345 | 158 | } | 158 | } |
346 | 159 | 159 | ||
348 | 160 | func (s *JujuConnSuite) APIInfo(c *C) *api.Info { | 160 | func (s *JujuConnSuite) APIInfo(c *gc.C) *api.Info { |
349 | 161 | _, apiInfo, err := s.APIConn.Environ.StateInfo() | 161 | _, apiInfo, err := s.APIConn.Environ.StateInfo() |
351 | 162 | c.Assert(err, IsNil) | 162 | c.Assert(err, gc.IsNil) |
352 | 163 | apiInfo.Tag = "user-admin" | 163 | apiInfo.Tag = "user-admin" |
353 | 164 | apiInfo.Password = "dummy-secret" | 164 | apiInfo.Password = "dummy-secret" |
354 | 165 | return apiInfo | 165 | return apiInfo |
355 | 166 | } | 166 | } |
356 | 167 | 167 | ||
358 | 168 | func (s *JujuConnSuite) openAPIAs(c *C, tag, password, nonce string) *api.State { | 168 | func (s *JujuConnSuite) openAPIAs(c *gc.C, tag, password, nonce string) *api.State { |
359 | 169 | _, info, err := s.APIConn.Environ.StateInfo() | 169 | _, info, err := s.APIConn.Environ.StateInfo() |
361 | 170 | c.Assert(err, IsNil) | 170 | c.Assert(err, gc.IsNil) |
362 | 171 | info.Tag = tag | 171 | info.Tag = tag |
363 | 172 | info.Password = password | 172 | info.Password = password |
364 | 173 | info.Nonce = nonce | 173 | info.Nonce = nonce |
365 | 174 | st, err := api.Open(info, api.DialOpts{}) | 174 | st, err := api.Open(info, api.DialOpts{}) |
368 | 175 | c.Assert(err, IsNil) | 175 | c.Assert(err, gc.IsNil) |
369 | 176 | c.Assert(st, NotNil) | 176 | c.Assert(st, gc.NotNil) |
370 | 177 | return st | 177 | return st |
371 | 178 | } | 178 | } |
372 | 179 | 179 | ||
373 | 180 | // OpenAPIAs opens the API using the given identity tag | 180 | // OpenAPIAs opens the API using the given identity tag |
374 | 181 | // and password for authentication. | 181 | // and password for authentication. |
376 | 182 | func (s *JujuConnSuite) OpenAPIAs(c *C, tag, password string) *api.State { | 182 | func (s *JujuConnSuite) OpenAPIAs(c *gc.C, tag, password string) *api.State { |
377 | 183 | return s.openAPIAs(c, tag, password, "") | 183 | return s.openAPIAs(c, tag, password, "") |
378 | 184 | } | 184 | } |
379 | 185 | 185 | ||
380 | 186 | // OpenAPIAsMachine opens the API using the given machine tag, | 186 | // OpenAPIAsMachine opens the API using the given machine tag, |
381 | 187 | // password and nonce for authentication. | 187 | // password and nonce for authentication. |
383 | 188 | func (s *JujuConnSuite) OpenAPIAsMachine(c *C, tag, password, nonce string) *api.State { | 188 | func (s *JujuConnSuite) OpenAPIAsMachine(c *gc.C, tag, password, nonce string) *api.State { |
384 | 189 | return s.openAPIAs(c, tag, password, nonce) | 189 | return s.openAPIAs(c, tag, password, nonce) |
385 | 190 | } | 190 | } |
386 | 191 | 191 | ||
388 | 192 | func (s *JujuConnSuite) setUpConn(c *C) { | 192 | // OpenAPIAsNewMachine creates a new machine entry that lives in system state, and |
389 | 193 | // then uses that to open the API. | ||
390 | 194 | func (s *JujuConnSuite) OpenAPIAsNewMachine(c *gc.C) (*api.State, *state.Machine) { | ||
391 | 195 | machine, err := s.State.AddMachine("series", state.JobHostUnits) | ||
392 | 196 | c.Assert(err, gc.IsNil) | ||
393 | 197 | err = machine.SetPassword("test-password") | ||
394 | 198 | c.Assert(err, gc.IsNil) | ||
395 | 199 | err = machine.SetProvisioned("foo", "fake_nonce", nil) | ||
396 | 200 | c.Assert(err, gc.IsNil) | ||
397 | 201 | return s.openAPIAs(c, machine.Tag(), "test-password", "fake_nonce"), machine | ||
398 | 202 | } | ||
399 | 203 | |||
400 | 204 | func (s *JujuConnSuite) setUpConn(c *gc.C) { | ||
401 | 193 | if s.RootDir != "" { | 205 | if s.RootDir != "" { |
402 | 194 | panic("JujuConnSuite.setUpConn without teardown") | 206 | panic("JujuConnSuite.setUpConn without teardown") |
403 | 195 | } | 207 | } |
404 | @@ -197,38 +209,38 @@ | |||
405 | 197 | s.oldHome = os.Getenv("HOME") | 209 | s.oldHome = os.Getenv("HOME") |
406 | 198 | home := filepath.Join(s.RootDir, "/home/ubuntu") | 210 | home := filepath.Join(s.RootDir, "/home/ubuntu") |
407 | 199 | err := os.MkdirAll(home, 0777) | 211 | err := os.MkdirAll(home, 0777) |
409 | 200 | c.Assert(err, IsNil) | 212 | c.Assert(err, gc.IsNil) |
410 | 201 | os.Setenv("HOME", home) | 213 | os.Setenv("HOME", home) |
411 | 202 | 214 | ||
412 | 203 | dataDir := filepath.Join(s.RootDir, "/var/lib/juju") | 215 | dataDir := filepath.Join(s.RootDir, "/var/lib/juju") |
413 | 204 | err = os.MkdirAll(dataDir, 0777) | 216 | err = os.MkdirAll(dataDir, 0777) |
415 | 205 | c.Assert(err, IsNil) | 217 | c.Assert(err, gc.IsNil) |
416 | 206 | 218 | ||
417 | 207 | yaml := []byte(fmt.Sprintf(envConfig, version.Current.Number)) | 219 | yaml := []byte(fmt.Sprintf(envConfig, version.Current.Number)) |
418 | 208 | err = ioutil.WriteFile(config.JujuHomePath("environments.yaml"), yaml, 0600) | 220 | err = ioutil.WriteFile(config.JujuHomePath("environments.yaml"), yaml, 0600) |
420 | 209 | c.Assert(err, IsNil) | 221 | c.Assert(err, gc.IsNil) |
421 | 210 | 222 | ||
422 | 211 | err = ioutil.WriteFile(config.JujuHomePath("dummyenv-cert.pem"), []byte(testing.CACert), 0666) | 223 | err = ioutil.WriteFile(config.JujuHomePath("dummyenv-cert.pem"), []byte(testing.CACert), 0666) |
424 | 212 | c.Assert(err, IsNil) | 224 | c.Assert(err, gc.IsNil) |
425 | 213 | 225 | ||
426 | 214 | err = ioutil.WriteFile(config.JujuHomePath("dummyenv-private-key.pem"), []byte(testing.CAKey), 0600) | 226 | err = ioutil.WriteFile(config.JujuHomePath("dummyenv-private-key.pem"), []byte(testing.CAKey), 0600) |
428 | 215 | c.Assert(err, IsNil) | 227 | c.Assert(err, gc.IsNil) |
429 | 216 | 228 | ||
430 | 217 | environ, err := environs.PrepareFromName("dummyenv") | 229 | environ, err := environs.PrepareFromName("dummyenv") |
432 | 218 | c.Assert(err, IsNil) | 230 | c.Assert(err, gc.IsNil) |
433 | 219 | // sanity check we've got the correct environment. | 231 | // sanity check we've got the correct environment. |
436 | 220 | c.Assert(environ.Name(), Equals, "dummyenv") | 232 | c.Assert(environ.Name(), gc.Equals, "dummyenv") |
437 | 221 | c.Assert(bootstrap.Bootstrap(environ, constraints.Value{}), IsNil) | 233 | c.Assert(bootstrap.Bootstrap(environ, constraints.Value{}), gc.IsNil) |
438 | 222 | 234 | ||
439 | 223 | s.BackingState = environ.(GetStater).GetStateInAPIServer() | 235 | s.BackingState = environ.(GetStater).GetStateInAPIServer() |
440 | 224 | 236 | ||
441 | 225 | conn, err := juju.NewConn(environ) | 237 | conn, err := juju.NewConn(environ) |
443 | 226 | c.Assert(err, IsNil) | 238 | c.Assert(err, gc.IsNil) |
444 | 227 | s.Conn = conn | 239 | s.Conn = conn |
445 | 228 | s.State = conn.State | 240 | s.State = conn.State |
446 | 229 | 241 | ||
447 | 230 | apiConn, err := juju.NewAPIConn(environ, api.DialOpts{}) | 242 | apiConn, err := juju.NewAPIConn(environ, api.DialOpts{}) |
449 | 231 | c.Assert(err, IsNil) | 243 | c.Assert(err, gc.IsNil) |
450 | 232 | s.APIConn = apiConn | 244 | s.APIConn = apiConn |
451 | 233 | s.APIState = apiConn.State | 245 | s.APIState = apiConn.State |
452 | 234 | s.environ = environ | 246 | s.environ = environ |
453 | @@ -238,7 +250,7 @@ | |||
454 | 238 | GetStateInAPIServer() *state.State | 250 | GetStateInAPIServer() *state.State |
455 | 239 | } | 251 | } |
456 | 240 | 252 | ||
458 | 241 | func (s *JujuConnSuite) tearDownConn(c *C) { | 253 | func (s *JujuConnSuite) tearDownConn(c *gc.C) { |
459 | 242 | // Bootstrap will set the admin password, and render non-authorized use | 254 | // Bootstrap will set the admin password, and render non-authorized use |
460 | 243 | // impossible. s.State may still hold the right password, so try to reset | 255 | // impossible. s.State may still hold the right password, so try to reset |
461 | 244 | // the password so that the MgoSuite soft-resetting works. If that fails, | 256 | // the password so that the MgoSuite soft-resetting works. If that fails, |
462 | @@ -247,8 +259,8 @@ | |||
463 | 247 | if err := s.State.SetAdminMongoPassword(""); err != nil { | 259 | if err := s.State.SetAdminMongoPassword(""); err != nil { |
464 | 248 | c.Logf("cannot reset admin password: %v", err) | 260 | c.Logf("cannot reset admin password: %v", err) |
465 | 249 | } | 261 | } |
468 | 250 | c.Assert(s.Conn.Close(), IsNil) | 262 | c.Assert(s.Conn.Close(), gc.IsNil) |
469 | 251 | c.Assert(s.APIConn.Close(), IsNil) | 263 | c.Assert(s.APIConn.Close(), gc.IsNil) |
470 | 252 | dummy.Reset() | 264 | dummy.Reset() |
471 | 253 | s.Conn = nil | 265 | s.Conn = nil |
472 | 254 | s.State = nil | 266 | s.State = nil |
473 | @@ -276,13 +288,13 @@ | |||
474 | 276 | } | 288 | } |
475 | 277 | } | 289 | } |
476 | 278 | 290 | ||
478 | 279 | func (s *JujuConnSuite) AddTestingCharm(c *C, name string) *state.Charm { | 291 | func (s *JujuConnSuite) AddTestingCharm(c *gc.C, name string) *state.Charm { |
479 | 280 | ch := testing.Charms.Dir(name) | 292 | ch := testing.Charms.Dir(name) |
480 | 281 | ident := fmt.Sprintf("%s-%d", ch.Meta().Name, ch.Revision()) | 293 | ident := fmt.Sprintf("%s-%d", ch.Meta().Name, ch.Revision()) |
481 | 282 | curl := charm.MustParseURL("local:series/" + ident) | 294 | curl := charm.MustParseURL("local:series/" + ident) |
482 | 283 | repo, err := charm.InferRepository(curl, testing.Charms.Path) | 295 | repo, err := charm.InferRepository(curl, testing.Charms.Path) |
484 | 284 | c.Assert(err, IsNil) | 296 | c.Assert(err, gc.IsNil) |
485 | 285 | sch, err := s.Conn.PutCharm(curl, repo, false) | 297 | sch, err := s.Conn.PutCharm(curl, repo, false) |
487 | 286 | c.Assert(err, IsNil) | 298 | c.Assert(err, gc.IsNil) |
488 | 287 | return sch | 299 | return sch |
489 | 288 | } | 300 | } |
490 | 289 | 301 | ||
491 | === modified file 'state/api/apiclient.go' | |||
492 | --- state/api/apiclient.go 2013-09-11 06:27:05 +0000 | |||
493 | +++ state/api/apiclient.go 2013-09-13 09:26:01 +0000 | |||
494 | @@ -133,11 +133,8 @@ | |||
495 | 133 | } | 133 | } |
496 | 134 | 134 | ||
497 | 135 | func (s *State) heartbeatMonitor() { | 135 | func (s *State) heartbeatMonitor() { |
498 | 136 | ping := func() error { | ||
499 | 137 | return s.Call("Pinger", "", "Ping", nil, nil) | ||
500 | 138 | } | ||
501 | 139 | for { | 136 | for { |
503 | 140 | if err := ping(); err != nil { | 137 | if err := s.Ping(); err != nil { |
504 | 141 | close(s.broken) | 138 | close(s.broken) |
505 | 142 | return | 139 | return |
506 | 143 | } | 140 | } |
507 | @@ -145,6 +142,10 @@ | |||
508 | 145 | } | 142 | } |
509 | 146 | } | 143 | } |
510 | 147 | 144 | ||
511 | 145 | func (s *State) Ping() error { | ||
512 | 146 | return s.Call("Pinger", "", "Ping", nil, nil) | ||
513 | 147 | } | ||
514 | 148 | |||
515 | 148 | // Call invokes a low-level RPC method of the given objType, id, and | 149 | // Call invokes a low-level RPC method of the given objType, id, and |
516 | 149 | // request, passing the given parameters and filling in the response | 150 | // request, passing the given parameters and filling in the response |
517 | 150 | // results. This should not be used directly by clients. | 151 | // results. This should not be used directly by clients. |
518 | 151 | 152 | ||
519 | === modified file 'state/apiserver/pinger_test.go' | |||
520 | --- state/apiserver/pinger_test.go 2013-09-11 06:27:05 +0000 | |||
521 | +++ state/apiserver/pinger_test.go 2013-09-13 09:26:01 +0000 | |||
522 | @@ -6,6 +6,7 @@ | |||
523 | 6 | import ( | 6 | import ( |
524 | 7 | gc "launchpad.net/gocheck" | 7 | gc "launchpad.net/gocheck" |
525 | 8 | "launchpad.net/juju-core/juju/testing" | 8 | "launchpad.net/juju-core/juju/testing" |
526 | 9 | "launchpad.net/juju-core/rpc" | ||
527 | 9 | "launchpad.net/juju-core/state" | 10 | "launchpad.net/juju-core/state" |
528 | 10 | "launchpad.net/juju-core/state/api" | 11 | "launchpad.net/juju-core/state/api" |
529 | 11 | "time" | 12 | "time" |
530 | @@ -54,3 +55,14 @@ | |||
531 | 54 | return | 55 | return |
532 | 55 | } | 56 | } |
533 | 56 | } | 57 | } |
534 | 58 | |||
535 | 59 | func (s *stateSuite) TestPing(c *gc.C) { | ||
536 | 60 | st, _ := s.OpenAPIAsNewMachine(c) | ||
537 | 61 | defer st.Close() | ||
538 | 62 | err := st.Ping() | ||
539 | 63 | c.Assert(err, gc.IsNil) | ||
540 | 64 | err = st.Close() | ||
541 | 65 | c.Assert(err, gc.IsNil) | ||
542 | 66 | err = st.Ping() | ||
543 | 67 | c.Assert(err, gc.Equals, rpc.ErrShutdown) | ||
544 | 68 | } | ||
545 | 57 | 69 | ||
546 | === modified file 'state/state.go' | |||
547 | --- state/state.go 2013-09-11 06:27:05 +0000 | |||
548 | +++ state/state.go 2013-09-13 09:26:01 +0000 | |||
549 | @@ -102,6 +102,12 @@ | |||
550 | 102 | return st.runner.Run(ops, "", nil) | 102 | return st.runner.Run(ops, "", nil) |
551 | 103 | } | 103 | } |
552 | 104 | 104 | ||
553 | 105 | // Ping probes the state's database connection to ensure | ||
554 | 106 | // that it is still alive. | ||
555 | 107 | func (st *State) Ping() error { | ||
556 | 108 | return st.db.Session.Ping() | ||
557 | 109 | } | ||
558 | 110 | |||
559 | 105 | func (st *State) Watch() *multiwatcher.Watcher { | 111 | func (st *State) Watch() *multiwatcher.Watcher { |
560 | 106 | st.mu.Lock() | 112 | st.mu.Lock() |
561 | 107 | if st.allManager == nil { | 113 | if st.allManager == nil { |
562 | 108 | 114 | ||
563 | === modified file 'state/state_test.go' | |||
564 | --- state/state_test.go 2013-09-11 06:27:05 +0000 | |||
565 | +++ state/state_test.go 2013-09-13 09:26:01 +0000 | |||
566 | @@ -63,6 +63,12 @@ | |||
567 | 63 | c.Assert(s.State.CACert(), gc.DeepEquals, info.CACert) | 63 | c.Assert(s.State.CACert(), gc.DeepEquals, info.CACert) |
568 | 64 | } | 64 | } |
569 | 65 | 65 | ||
570 | 66 | func (s *StateSuite) TestPing(c *gc.C) { | ||
571 | 67 | c.Assert(s.State.Ping(), gc.IsNil) | ||
572 | 68 | testing.MgoRestart() | ||
573 | 69 | c.Assert(s.State.Ping(), gc.NotNil) | ||
574 | 70 | } | ||
575 | 71 | |||
576 | 66 | func (s *StateSuite) TestAPIAddresses(c *gc.C) { | 72 | func (s *StateSuite) TestAPIAddresses(c *gc.C) { |
577 | 67 | config, err := s.State.EnvironConfig() | 73 | config, err := s.State.EnvironConfig() |
578 | 68 | c.Assert(err, gc.IsNil) | 74 | c.Assert(err, gc.IsNil) |
579 | 69 | 75 | ||
580 | === added file 'testing/checkers/set.go' | |||
581 | --- testing/checkers/set.go 1970-01-01 00:00:00 +0000 | |||
582 | +++ testing/checkers/set.go 2013-09-13 09:26:01 +0000 | |||
583 | @@ -0,0 +1,35 @@ | |||
584 | 1 | package checkers | ||
585 | 2 | |||
586 | 3 | import ( | ||
587 | 4 | "reflect" | ||
588 | 5 | ) | ||
589 | 6 | |||
590 | 7 | // Restorer holds a function that can be used | ||
591 | 8 | // to restore some previous state. | ||
592 | 9 | type Restorer func() | ||
593 | 10 | |||
594 | 11 | // Restore restores some previous state. | ||
595 | 12 | func (r Restorer) Restore() { | ||
596 | 13 | r() | ||
597 | 14 | } | ||
598 | 15 | |||
599 | 16 | // Set sets the value pointed to by the given | ||
600 | 17 | // destination to the given value, and returns | ||
601 | 18 | // a function to restore it to its original value. | ||
602 | 19 | // The value must be assignable to the element | ||
603 | 20 | // type of the destination. | ||
604 | 21 | func Set(dest, value interface{}) Restorer { | ||
605 | 22 | destv := reflect.ValueOf(dest).Elem() | ||
606 | 23 | oldv := reflect.New(destv.Type()).Elem() | ||
607 | 24 | oldv.Set(destv) | ||
608 | 25 | valuev := reflect.ValueOf(value) | ||
609 | 26 | if !valuev.IsValid() { | ||
610 | 27 | // This isn't quite right when the destination type is not | ||
611 | 28 | // nilable, but it's better than the complex alternative. | ||
612 | 29 | valuev = reflect.Zero(destv.Type()) | ||
613 | 30 | } | ||
614 | 31 | destv.Set(valuev) | ||
615 | 32 | return func() { | ||
616 | 33 | destv.Set(oldv) | ||
617 | 34 | } | ||
618 | 35 | } | ||
619 | 0 | 36 | ||
620 | === added file 'testing/checkers/set_test.go' | |||
621 | --- testing/checkers/set_test.go 1970-01-01 00:00:00 +0000 | |||
622 | +++ testing/checkers/set_test.go 2013-09-13 09:26:01 +0000 | |||
623 | @@ -0,0 +1,54 @@ | |||
624 | 1 | package checkers_test | ||
625 | 2 | |||
626 | 3 | import ( | ||
627 | 4 | "errors" | ||
628 | 5 | |||
629 | 6 | gc "launchpad.net/gocheck" | ||
630 | 7 | jc "launchpad.net/juju-core/testing/checkers" | ||
631 | 8 | ) | ||
632 | 9 | |||
633 | 10 | type SetSuite struct{} | ||
634 | 11 | |||
635 | 12 | var _ = gc.Suite(&SetSuite{}) | ||
636 | 13 | |||
637 | 14 | func (*SetSuite) TestSetInt(c *gc.C) { | ||
638 | 15 | i := 99 | ||
639 | 16 | restore := jc.Set(&i, 88) | ||
640 | 17 | c.Assert(i, gc.Equals, 88) | ||
641 | 18 | restore() | ||
642 | 19 | c.Assert(i, gc.Equals, 99) | ||
643 | 20 | } | ||
644 | 21 | |||
645 | 22 | func (*SetSuite) TestSetError(c *gc.C) { | ||
646 | 23 | oldErr := errors.New("foo") | ||
647 | 24 | newErr := errors.New("bar") | ||
648 | 25 | err := oldErr | ||
649 | 26 | restore := jc.Set(&err, newErr) | ||
650 | 27 | c.Assert(err, gc.Equals, newErr) | ||
651 | 28 | restore() | ||
652 | 29 | c.Assert(err, gc.Equals, oldErr) | ||
653 | 30 | } | ||
654 | 31 | |||
655 | 32 | func (*SetSuite) TestSetErrorToNil(c *gc.C) { | ||
656 | 33 | oldErr := errors.New("foo") | ||
657 | 34 | err := oldErr | ||
658 | 35 | restore := jc.Set(&err, nil) | ||
659 | 36 | c.Assert(err, gc.Equals, nil) | ||
660 | 37 | restore() | ||
661 | 38 | c.Assert(err, gc.Equals, oldErr) | ||
662 | 39 | } | ||
663 | 40 | |||
664 | 41 | func (*SetSuite) TestSetMapToNil(c *gc.C) { | ||
665 | 42 | oldMap := map[string]int{"foo": 1234} | ||
666 | 43 | m := oldMap | ||
667 | 44 | restore := jc.Set(&m, nil) | ||
668 | 45 | c.Assert(m, gc.IsNil) | ||
669 | 46 | restore() | ||
670 | 47 | c.Assert(m, gc.DeepEquals, oldMap) | ||
671 | 48 | } | ||
672 | 49 | |||
673 | 50 | func (*SetSuite) TestSetPanicsWhenNotAssignable(c *gc.C) { | ||
674 | 51 | i := 99 | ||
675 | 52 | type otherInt int | ||
676 | 53 | c.Assert(func() { jc.Set(&i, otherInt(88)) }, gc.PanicMatches, `reflect\.Set: value of type checkers_test\.otherInt is not assignable to type int`) | ||
677 | 54 | } | ||
678 | 0 | 55 | ||
679 | === modified file 'testing/mgo.go' | |||
680 | --- testing/mgo.go 2013-08-27 07:28:22 +0000 | |||
681 | +++ testing/mgo.go 2013-09-13 09:26:01 +0000 | |||
682 | @@ -57,7 +57,6 @@ | |||
683 | 57 | } | 57 | } |
684 | 58 | 58 | ||
685 | 59 | // startMgoServer starts a MongoDB server in a temporary directory. | 59 | // startMgoServer starts a MongoDB server in a temporary directory. |
686 | 60 | // It panics if it encounters an error. | ||
687 | 61 | func startMgoServer() error { | 60 | func startMgoServer() error { |
688 | 62 | dbdir, err := ioutil.TempDir("", "test-mgo") | 61 | dbdir, err := ioutil.TempDir("", "test-mgo") |
689 | 63 | if err != nil { | 62 | if err != nil { |
690 | @@ -69,12 +68,30 @@ | |||
691 | 69 | return fmt.Errorf("cannot write cert/key PEM: %v", err) | 68 | return fmt.Errorf("cannot write cert/key PEM: %v", err) |
692 | 70 | } | 69 | } |
693 | 71 | MgoPort = FindTCPPort() | 70 | MgoPort = FindTCPPort() |
694 | 71 | MgoAddr = fmt.Sprintf("localhost:%d", MgoPort) | ||
695 | 72 | mgoDir = dbdir | ||
696 | 73 | if err := runMgoServer(); err != nil { | ||
697 | 74 | MgoAddr = "" | ||
698 | 75 | MgoPort = 0 | ||
699 | 76 | os.RemoveAll(mgoDir) | ||
700 | 77 | mgoDir = "" | ||
701 | 78 | return err | ||
702 | 79 | } | ||
703 | 80 | return nil | ||
704 | 81 | } | ||
705 | 82 | |||
706 | 83 | // runMgoServer runs the MongoDB server at the | ||
707 | 84 | // address and directory already configured. | ||
708 | 85 | func runMgoServer() error { | ||
709 | 86 | if mgoServer != nil { | ||
710 | 87 | panic("mongo server is already running") | ||
711 | 88 | } | ||
712 | 72 | mgoport := strconv.Itoa(MgoPort) | 89 | mgoport := strconv.Itoa(MgoPort) |
713 | 73 | mgoargs := []string{ | 90 | mgoargs := []string{ |
714 | 74 | "--auth", | 91 | "--auth", |
716 | 75 | "--dbpath", dbdir, | 92 | "--dbpath", mgoDir, |
717 | 76 | "--sslOnNormalPorts", | 93 | "--sslOnNormalPorts", |
719 | 77 | "--sslPEMKeyFile", pemPath, | 94 | "--sslPEMKeyFile", filepath.Join(mgoDir, "server.pem"), |
720 | 78 | "--sslPEMKeyPassword", "ignored", | 95 | "--sslPEMKeyPassword", "ignored", |
721 | 79 | "--bind_ip", "localhost", | 96 | "--bind_ip", "localhost", |
722 | 80 | "--port", mgoport, | 97 | "--port", mgoport, |
723 | @@ -106,21 +123,33 @@ | |||
724 | 106 | }() | 123 | }() |
725 | 107 | mgoExited = exited | 124 | mgoExited = exited |
726 | 108 | if err := server.Start(); err != nil { | 125 | if err := server.Start(); err != nil { |
727 | 109 | os.RemoveAll(dbdir) | ||
728 | 110 | return err | 126 | return err |
729 | 111 | } | 127 | } |
730 | 112 | MgoAddr = "localhost:" + mgoport | ||
731 | 113 | mgoServer = server | 128 | mgoServer = server |
732 | 114 | mgoDir = dbdir | ||
733 | 115 | return nil | 129 | return nil |
734 | 116 | } | 130 | } |
735 | 117 | 131 | ||
736 | 132 | func mgoKill() { | ||
737 | 133 | mgoServer.Process.Kill() | ||
738 | 134 | <-mgoExited | ||
739 | 135 | mgoServer = nil | ||
740 | 136 | mgoExited = nil | ||
741 | 137 | } | ||
742 | 138 | |||
743 | 118 | func destroyMgoServer() { | 139 | func destroyMgoServer() { |
744 | 119 | if mgoServer != nil { | 140 | if mgoServer != nil { |
747 | 120 | mgoServer.Process.Kill() | 141 | mgoKill() |
746 | 121 | <-mgoExited | ||
748 | 122 | os.RemoveAll(mgoDir) | 142 | os.RemoveAll(mgoDir) |
750 | 123 | MgoAddr, mgoServer, mgoExited, mgoDir = "", nil, nil, "" | 143 | MgoAddr, mgoDir = "", "" |
751 | 144 | } | ||
752 | 145 | } | ||
753 | 146 | |||
754 | 147 | // MgoRestart restarts the mongo server, useful for | ||
755 | 148 | // testing what happens when a state server goes down. | ||
756 | 149 | func MgoRestart() { | ||
757 | 150 | mgoKill() | ||
758 | 151 | if err := startMgoServer(); err != nil { | ||
759 | 152 | panic(err) | ||
760 | 124 | } | 153 | } |
761 | 125 | } | 154 | } |
762 | 126 | 155 |
Reviewers: mp+185445_ code.launchpad. net,
Message:
Please take a look.
Description:
cmd/jujud: avoid using allFatal
This is a backport of the /code.launchpad .net/~rogpeppe/ juju-core/ 384-avoid- allfatal/ +merge/ 184743
https:/
now proposed for 1.14, with selected other patches from other revisions
to make it compile.
https:/ /code.launchpad .net/~rogpeppe/ juju-core/ 391-1.14- avoid-allFatal/ +merge/ 185445
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/13696043/
Affected files (+315, -65 lines): agent_test. go machine. go machine_ test.go conn.go apiclient. go /pinger_ test.go checkers/ set.go checkers/ set_test. go
A [revision details]
M cmd/jujud/agent.go
M cmd/jujud/
M cmd/jujud/
M cmd/jujud/
M cmd/jujud/unit.go
M juju/testing/
M state/api/
M state/apiserver
M state/state.go
M state/state_test.go
A testing/
A testing/
M testing/mgo.go