Merge lp:~niemeyer/juju-core/resource-not-found into lp:~juju/juju-core/trunk
- resource-not-found
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 562 |
Proposed branch: | lp:~niemeyer/juju-core/resource-not-found |
Merge into: | lp:~juju/juju-core/trunk |
Diff against target: |
427 lines (+94/-47) 14 files modified
cmd/juju/deploy_test.go (+2/-2) cmd/juju/expose_test.go (+1/-1) cmd/juju/unexpose_test.go (+1/-1) state/assign_test.go (+2/-2) state/charm_test.go (+4/-4) state/confignode.go (+0/-9) state/machine.go (+1/-2) state/machine_test.go (+5/-4) state/relation_test.go (+9/-4) state/service_test.go (+2/-2) state/state.go (+37/-5) state/state_test.go (+20/-7) state/unit.go (+4/-4) state/unit_test.go (+6/-0) |
To merge this branch: | bzr merge lp:~niemeyer/juju-core/resource-not-found |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
The Go Language Gophers | Pending | ||
Review via email: mp+125917@code.launchpad.net |
Commit message
Description of the change
state: getter methods return NotFoundError
Due to the in-progress lifecycle changes, client code
must be able to distinguish not found errors.
Gustavo Niemeyer (niemeyer) wrote : | # |
Gustavo Niemeyer (niemeyer) wrote : | # |
Please take a look.
Roger Peppe (rogpeppe) wrote : | # |
looks reasonable, but one thought below.
https:/
File state/state.go (right):
https:/
state/state.go:46: format string
i'm not sure that i see the benefit in storing the format and args here.
are we really concerned that the work involved in formatting the error
message is going to slow us down?
it's also potentially dangerous - if we pass in a mutable value whose
String value can change, the error may change value after creation.
Gustavo Niemeyer (niemeyer) wrote : | # |
*** Submitted:
state: getter methods return NotFoundError
Due to the in-progress lifecycle changes, client code
must be able to distinguish not found errors.
R=dfc, TheMue, rog
CC=
https:/
https:/
File state/state.go (right):
https:/
state/state.go:46: format string
On 2012/09/24 14:12:04, rog wrote:
> i'm not sure that i see the benefit in storing the format and args
here. are we
> really concerned that the work involved in formatting the error
message is going
> to slow us down?
I certainly don't care enough to argue. I'll change it.
https:/
state/state.go:53:
On 2012/09/24 05:20:35, dfc wrote:
> comment please.
I honestly think it's not worth it in this case. Reading the body of the
function is more clear and takes less time than reading any comments we
add here, and since it's a private function it won't show up in the
docs.
https:/
state/state.go:55: return &NotFoundError{
On 2012/09/24 09:37:11, TheMue wrote:
> If no later access to the args is planned the error message could
already be
Changed so NotFoundError has a dumb msg argument.
https:/
state/state.go:384: func (s *State) Relation(endpoints
...RelationEndp
On 2012/09/24 05:20:35, dfc wrote:
> suggestion: drop the named return values as we're not using defer
ErrorContextf
> anymore in this method.
Done.
Preview Diff
1 | === modified file 'cmd/juju/deploy_test.go' |
2 | --- cmd/juju/deploy_test.go 2012-09-21 19:11:50 +0000 |
3 | +++ cmd/juju/deploy_test.go 2012-09-24 03:51:21 +0000 |
4 | @@ -149,9 +149,9 @@ |
5 | // Verify state not touched... |
6 | curl := charm.MustParseURL("local:precise/dummy-1") |
7 | _, err = s.State.Charm(curl) |
8 | - c.Assert(err, ErrorMatches, `cannot get charm "local:precise/dummy-1": not found`) |
9 | + c.Assert(err, ErrorMatches, `charm "local:precise/dummy-1" not found`) |
10 | _, err = s.State.Service("dummy") |
11 | - c.Assert(err, ErrorMatches, `cannot get service "dummy": not found`) |
12 | + c.Assert(err, ErrorMatches, `service "dummy" not found`) |
13 | } |
14 | |
15 | func (s *DeploySuite) TestAddsPeerRelations(c *C) { |
16 | |
17 | === modified file 'cmd/juju/expose_test.go' |
18 | --- cmd/juju/expose_test.go 2012-09-21 19:14:11 +0000 |
19 | +++ cmd/juju/expose_test.go 2012-09-24 03:51:21 +0000 |
20 | @@ -40,5 +40,5 @@ |
21 | s.assertExposed(c, "some-service-name") |
22 | |
23 | err = runExpose(c, "nonexistent-service") |
24 | - c.Assert(err, ErrorMatches, `cannot get service "nonexistent-service": not found`) |
25 | + c.Assert(err, ErrorMatches, `service "nonexistent-service" not found`) |
26 | } |
27 | |
28 | === modified file 'cmd/juju/unexpose_test.go' |
29 | --- cmd/juju/unexpose_test.go 2012-09-21 19:14:11 +0000 |
30 | +++ cmd/juju/unexpose_test.go 2012-09-24 03:51:21 +0000 |
31 | @@ -44,5 +44,5 @@ |
32 | s.assertExposed(c, "some-service-name", false) |
33 | |
34 | err = runUnexpose(c, "nonexistent-service") |
35 | - c.Assert(err, ErrorMatches, `cannot get service "nonexistent-service": not found`) |
36 | + c.Assert(err, ErrorMatches, `service "nonexistent-service" not found`) |
37 | } |
38 | |
39 | === modified file 'state/assign_test.go' |
40 | --- state/assign_test.go 2012-09-21 14:54:59 +0000 |
41 | +++ state/assign_test.go 2012-09-24 03:51:21 +0000 |
42 | @@ -362,7 +362,7 @@ |
43 | c.Assert(err, IsNil) |
44 | |
45 | _, err = unit.AssignToUnusedMachine() |
46 | - c.Assert(err, ErrorMatches, `cannot assign unit "wordpress/0" to unused machine.*: cannot get unit "wordpress/0": not found`) |
47 | + c.Assert(err, ErrorMatches, `cannot assign unit "wordpress/0" to unused machine.*: unit "wordpress/0" not found`) |
48 | } |
49 | |
50 | func (s *AssignSuite) TestAssignUnitToUnusedMachineWithRemovedUnit(c *C) { |
51 | @@ -381,7 +381,7 @@ |
52 | c.Assert(err, IsNil) |
53 | |
54 | _, err = unit.AssignToUnusedMachine() |
55 | - c.Assert(err, ErrorMatches, `cannot assign unit "wordpress/0" to unused machine.*: cannot get unit "wordpress/0": not found`) |
56 | + c.Assert(err, ErrorMatches, `cannot assign unit "wordpress/0" to unused machine.*: unit "wordpress/0" not found`) |
57 | } |
58 | |
59 | func (s *AssignSuite) TestAssignUnitToUnusedMachineOnlyZero(c *C) { |
60 | |
61 | === modified file 'state/charm_test.go' |
62 | --- state/charm_test.go 2012-09-19 13:40:41 +0000 |
63 | +++ state/charm_test.go 2012-09-24 03:51:21 +0000 |
64 | @@ -3,6 +3,7 @@ |
65 | import ( |
66 | . "launchpad.net/gocheck" |
67 | "launchpad.net/juju-core/charm" |
68 | + "launchpad.net/juju-core/state" |
69 | "net/url" |
70 | ) |
71 | |
72 | @@ -40,10 +41,9 @@ |
73 | ) |
74 | } |
75 | |
76 | -func (s *CharmSuite) TestGetNonExistentCharm(c *C) { |
77 | - // Check that getting a non-existent charm fails nicely. |
78 | - |
79 | +func (s *CharmSuite) TestCharmNotFound(c *C) { |
80 | curl := charm.MustParseURL("local:anotherseries/dummy-1") |
81 | _, err := s.State.Charm(curl) |
82 | - c.Assert(err, ErrorMatches, `cannot get charm "local:anotherseries/dummy-1": .*`) |
83 | + c.Assert(err, ErrorMatches, `charm "local:anotherseries/dummy-1" not found`) |
84 | + c.Assert(err, FitsTypeOf, &state.NotFoundError{}) |
85 | } |
86 | |
87 | === modified file 'state/confignode.go' |
88 | --- state/confignode.go 2012-09-21 13:01:54 +0000 |
89 | +++ state/confignode.go 2012-09-24 03:51:21 +0000 |
90 | @@ -61,15 +61,6 @@ |
91 | txnRevno int64 |
92 | } |
93 | |
94 | -// NotFoundError represents the error that something is not found. |
95 | -type NotFoundError struct { |
96 | - what string |
97 | -} |
98 | - |
99 | -func (e *NotFoundError) Error() string { |
100 | - return fmt.Sprintf("%s not found", e.what) |
101 | -} |
102 | - |
103 | // Keys returns the current keys in alphabetical order. |
104 | func (c *ConfigNode) Keys() []string { |
105 | keys := []string{} |
106 | |
107 | === modified file 'state/machine.go' |
108 | --- state/machine.go 2012-09-20 09:15:49 +0000 |
109 | +++ state/machine.go 2012-09-24 03:51:21 +0000 |
110 | @@ -149,8 +149,7 @@ |
111 | // InstanceId returns the provider specific machine id for this machine. |
112 | func (m *Machine) InstanceId() (string, error) { |
113 | if m.doc.InstanceId == "" { |
114 | - msg := fmt.Sprintf("instance id for machine %d is not set", m.Id()) |
115 | - return "", &NotFoundError{msg} |
116 | + return "", notFound("instance id for machine %v", m) |
117 | } |
118 | return m.doc.InstanceId, nil |
119 | } |
120 | |
121 | === modified file 'state/machine_test.go' |
122 | --- state/machine_test.go 2012-09-21 17:26:00 +0000 |
123 | +++ state/machine_test.go 2012-09-24 03:51:21 +0000 |
124 | @@ -96,13 +96,14 @@ |
125 | err = machine.Refresh() |
126 | c.Assert(err, IsNil) |
127 | iid, err := machine.InstanceId() |
128 | - c.Assert(err, FitsTypeOf, &state.NotFoundError{}) |
129 | + c.Assert(state.IsNotFound(err), Equals, true) |
130 | c.Assert(iid, Equals, "") |
131 | } |
132 | |
133 | func (s *MachineSuite) TestMachineInstanceIdMissing(c *C) { |
134 | iid, err := s.machine.InstanceId() |
135 | - c.Assert(err, FitsTypeOf, &state.NotFoundError{}) |
136 | + c.Assert(state.IsNotFound(err), Equals, true) |
137 | + c.Assert(err, ErrorMatches, "instance id for machine 0 not found") |
138 | c.Assert(iid, Equals, "") |
139 | } |
140 | |
141 | @@ -118,7 +119,7 @@ |
142 | err = machine.Refresh() |
143 | c.Assert(err, IsNil) |
144 | iid, err := machine.InstanceId() |
145 | - c.Assert(err, FitsTypeOf, &state.NotFoundError{}) |
146 | + c.Assert(state.IsNotFound(err), Equals, true) |
147 | c.Assert(iid, Equals, "") |
148 | } |
149 | |
150 | @@ -322,7 +323,7 @@ |
151 | //info.tools, err = m.AgentTools() |
152 | //c.Assert(err, IsNil) |
153 | info.instanceId, err = m.InstanceId() |
154 | - if _, ok := err.(*state.NotFoundError); !ok { |
155 | + if !state.IsNotFound(err) { |
156 | c.Assert(err, IsNil) |
157 | } |
158 | c.Assert(info, DeepEquals, test.want) |
159 | |
160 | === modified file 'state/relation_test.go' |
161 | --- state/relation_test.go 2012-09-20 15:34:42 +0000 |
162 | +++ state/relation_test.go 2012-09-24 03:51:21 +0000 |
163 | @@ -63,9 +63,14 @@ |
164 | c.Assert(err, ErrorMatches, `cannot add relation "": cannot relate 0 endpoints`) |
165 | _, err = s.State.AddRelation(proep, reqep, peerep) |
166 | c.Assert(err, ErrorMatches, `cannot add relation "peer:baz pro:foo req:bar": cannot relate 3 endpoints`) |
167 | +} |
168 | |
169 | - _, err = s.State.Relation(peerep) |
170 | - c.Assert(err, ErrorMatches, `cannot get relation "peer:baz": .*`) |
171 | +func (s *RelationSuite) TestRelationNotFound(c *C) { |
172 | + subway := state.RelationEndpoint{"subway", "mongodb", "db", state.RoleRequirer, charm.ScopeGlobal} |
173 | + mongo := state.RelationEndpoint{"mongo", "mongodb", "server", state.RoleProvider, charm.ScopeGlobal} |
174 | + _, err := s.State.Relation(subway, mongo) |
175 | + c.Assert(err, ErrorMatches, `relation "mongo:server subway:db" not found`) |
176 | + c.Assert(state.IsNotFound(err), Equals, true) |
177 | } |
178 | |
179 | func (s *RelationSuite) TestProviderRequirerRelation(c *C) { |
180 | @@ -147,9 +152,9 @@ |
181 | err = s.State.RemoveService(peer) |
182 | c.Assert(err, IsNil) |
183 | _, err = s.State.Service("peer") |
184 | - c.Assert(err, ErrorMatches, `cannot get service "peer": not found`) |
185 | + c.Assert(err, ErrorMatches, `service "peer" not found`) |
186 | _, err = s.State.Relation(peerep) |
187 | - c.Assert(err, ErrorMatches, `cannot get relation "peer:baz": not found`) |
188 | + c.Assert(err, ErrorMatches, `relation "peer:baz" not found`) |
189 | } |
190 | |
191 | func assertNoRelations(c *C, srv *state.Service) { |
192 | |
193 | === modified file 'state/service_test.go' |
194 | --- state/service_test.go 2012-09-21 18:26:46 +0000 |
195 | +++ state/service_test.go 2012-09-24 03:51:21 +0000 |
196 | @@ -210,7 +210,7 @@ |
197 | unit, err = s.State.Unit("mysql/0/0") |
198 | c.Assert(err, ErrorMatches, `"mysql/0/0" is not a valid unit name`) |
199 | unit, err = s.State.Unit("pressword/0") |
200 | - c.Assert(err, ErrorMatches, `cannot get unit "pressword/0": not found`) |
201 | + c.Assert(err, ErrorMatches, `unit "pressword/0" not found`) |
202 | |
203 | // Add another service to check units are not misattributed. |
204 | mysql, err := s.State.AddService("wordpress", s.charm) |
205 | @@ -284,7 +284,7 @@ |
206 | err = s.State.RemoveService(s.service) |
207 | c.Assert(err, IsNil) |
208 | _, err = s.State.Unit("mysql/0") |
209 | - c.Assert(err, ErrorMatches, `cannot get unit "mysql/0": not found`) |
210 | + c.Assert(err, ErrorMatches, `unit "mysql/0" not found`) |
211 | } |
212 | |
213 | func (s *ServiceSuite) TestServiceConfig(c *C) { |
214 | |
215 | === modified file 'state/state.go' |
216 | --- state/state.go 2012-09-21 17:26:00 +0000 |
217 | +++ state/state.go 2012-09-24 03:51:21 +0000 |
218 | @@ -41,6 +41,25 @@ |
219 | return validUnit.MatchString(name) |
220 | } |
221 | |
222 | +// NotFoundError represents the error that something is not found. |
223 | +type NotFoundError struct { |
224 | + format string |
225 | + args []interface{} |
226 | +} |
227 | + |
228 | +func (e *NotFoundError) Error() string { |
229 | + return fmt.Sprintf(e.format+" not found", e.args...) |
230 | +} |
231 | + |
232 | +func notFound(format string, args ...interface{}) error { |
233 | + return &NotFoundError{format, args} |
234 | +} |
235 | + |
236 | +func IsNotFound(err error) bool { |
237 | + _, ok := err.(*NotFoundError) |
238 | + return ok |
239 | +} |
240 | + |
241 | // State represents the state of an environment |
242 | // managed by juju. |
243 | type State struct { |
244 | @@ -155,6 +174,9 @@ |
245 | mdoc := &machineDoc{} |
246 | sel := D{{"_id", id}} |
247 | err := s.machines.Find(sel).One(mdoc) |
248 | + if err == mgo.ErrNotFound { |
249 | + return nil, notFound("machine %d", id) |
250 | + } |
251 | if err != nil { |
252 | return nil, fmt.Errorf("cannot get machine %d: %v", id, err) |
253 | } |
254 | @@ -183,10 +205,12 @@ |
255 | func (s *State) Charm(curl *charm.URL) (*Charm, error) { |
256 | cdoc := &charmDoc{} |
257 | err := s.charms.Find(D{{"_id", curl}}).One(cdoc) |
258 | + if err == mgo.ErrNotFound { |
259 | + return nil, notFound("charm %q", curl) |
260 | + } |
261 | if err != nil { |
262 | return nil, fmt.Errorf("cannot get charm %q: %v", curl, err) |
263 | } |
264 | - |
265 | return newCharm(s, cdoc) |
266 | } |
267 | |
268 | @@ -277,6 +301,9 @@ |
269 | sdoc := &serviceDoc{} |
270 | sel := D{{"_id", name}} |
271 | err = s.services.Find(sel).One(sdoc) |
272 | + if err == mgo.ErrNotFound { |
273 | + return nil, notFound("service %q", name) |
274 | + } |
275 | if err != nil { |
276 | return nil, fmt.Errorf("cannot get service %q: %v", name, err) |
277 | } |
278 | @@ -355,12 +382,14 @@ |
279 | |
280 | // Relation returns the existing relation with the given endpoints. |
281 | func (s *State) Relation(endpoints ...RelationEndpoint) (r *Relation, err error) { |
282 | - defer trivial.ErrorContextf(&err, "cannot get relation %q", relationKey(endpoints)) |
283 | - |
284 | doc := relationDoc{} |
285 | - err = s.relations.Find(D{{"_id", relationKey(endpoints)}}).One(&doc) |
286 | + key := relationKey(endpoints) |
287 | + err = s.relations.Find(D{{"_id", key}}).One(&doc) |
288 | + if err == mgo.ErrNotFound { |
289 | + return nil, notFound("relation %q", key) |
290 | + } |
291 | if err != nil { |
292 | - return nil, err |
293 | + return nil, fmt.Errorf("cannot get relation %q: %v", key, err) |
294 | } |
295 | return newRelation(s, &doc), nil |
296 | } |
297 | @@ -391,6 +420,9 @@ |
298 | } |
299 | doc := unitDoc{} |
300 | err := s.units.FindId(name).One(&doc) |
301 | + if err == mgo.ErrNotFound { |
302 | + return nil, notFound("unit %q", name) |
303 | + } |
304 | if err != nil { |
305 | return nil, fmt.Errorf("cannot get unit %q: %v", name, err) |
306 | } |
307 | |
308 | === modified file 'state/state_test.go' |
309 | --- state/state_test.go 2012-09-21 18:26:46 +0000 |
310 | +++ state/state_test.go 2012-09-24 03:51:21 +0000 |
311 | @@ -30,6 +30,13 @@ |
312 | } |
313 | } |
314 | |
315 | +func (s *StateSuite) TestIsNotFound(c *C) { |
316 | + err1 := fmt.Errorf("unrelated error") |
317 | + err2 := &state.NotFoundError{} |
318 | + c.Assert(state.IsNotFound(err1), Equals, false) |
319 | + c.Assert(state.IsNotFound(err2), Equals, true) |
320 | +} |
321 | + |
322 | func (s *StateSuite) TestAddCharm(c *C) { |
323 | // Check that adding charms from scratch works correctly. |
324 | ch := testing.Charms.Dir("series", "dummy") |
325 | @@ -97,6 +104,12 @@ |
326 | c.Assert(machine.Id(), Equals, expectedId) |
327 | } |
328 | |
329 | +func (s *StateSuite) TestMachineNotFound(c *C) { |
330 | + _, err := s.State.Machine(0) |
331 | + c.Assert(err, ErrorMatches, "machine 0 not found") |
332 | + c.Assert(state.IsNotFound(err), Equals, true) |
333 | +} |
334 | + |
335 | func (s *StateSuite) TestAllMachines(c *C) { |
336 | c.Skip("Marshalling of agent tools is currently broken") |
337 | numInserts := 42 |
338 | @@ -153,6 +166,12 @@ |
339 | c.Assert(ch.URL(), DeepEquals, charm.URL()) |
340 | } |
341 | |
342 | +func (s *StateSuite) TestServiceNotFound(c *C) { |
343 | + _, err := s.State.Service("bummer") |
344 | + c.Assert(err, ErrorMatches, `service "bummer" not found`) |
345 | + c.Assert(state.IsNotFound(err), Equals, true) |
346 | +} |
347 | + |
348 | func (s *StateSuite) TestRemoveService(c *C) { |
349 | charm := s.AddTestingCharm(c, "dummy") |
350 | service, err := s.State.AddService("wordpress", charm) |
351 | @@ -166,18 +185,12 @@ |
352 | err = s.State.RemoveService(service) |
353 | c.Assert(err, IsNil) |
354 | _, err = s.State.Service("wordpress") |
355 | - c.Assert(err, ErrorMatches, `cannot get service "wordpress": .*`) |
356 | + c.Assert(err, ErrorMatches, `service "wordpress" not found`) |
357 | |
358 | err = s.State.RemoveService(service) |
359 | c.Assert(err, IsNil) |
360 | } |
361 | |
362 | -func (s *StateSuite) TestReadNonExistentService(c *C) { |
363 | - // BUG(aram): use error strings from state. |
364 | - _, err := s.State.Service("pressword") |
365 | - c.Assert(err, ErrorMatches, `cannot get service "pressword": .*`) |
366 | -} |
367 | - |
368 | func (s *StateSuite) TestAllServices(c *C) { |
369 | charm := s.AddTestingCharm(c, "dummy") |
370 | services, err := s.State.AllServices() |
371 | |
372 | === modified file 'state/unit.go' |
373 | --- state/unit.go 2012-09-21 18:26:46 +0000 |
374 | +++ state/unit.go 2012-09-24 03:51:21 +0000 |
375 | @@ -526,7 +526,7 @@ |
376 | } |
377 | err = u.st.runner.Run(ops, "", nil) |
378 | if err != nil { |
379 | - return fmt.Errorf("cannot unassign unit %q from machine: %v", u, onAbort(err, &NotFoundError{"machine"})) |
380 | + return fmt.Errorf("cannot unassign unit %q from machine: %v", u, onAbort(err, notFound("machine"))) |
381 | } |
382 | u.doc.MachineId = nil |
383 | return nil |
384 | @@ -541,7 +541,7 @@ |
385 | Update: D{{"$set", D{{"publicaddress", address}}}}, |
386 | }} |
387 | if err := u.st.runner.Run(ops, "", nil); err != nil { |
388 | - return fmt.Errorf("cannot set public address of unit %q: %v", u, onAbort(err, &NotFoundError{"machine"})) |
389 | + return fmt.Errorf("cannot set public address of unit %q: %v", u, onAbort(err, notFound("machine"))) |
390 | } |
391 | u.doc.PublicAddress = address |
392 | return nil |
393 | @@ -557,7 +557,7 @@ |
394 | }} |
395 | err := u.st.runner.Run(ops, "", nil) |
396 | if err != nil { |
397 | - return fmt.Errorf("cannot set private address of unit %q: %v", u, &NotFoundError{"unit"}) |
398 | + return fmt.Errorf("cannot set private address of unit %q: %v", u, notFound("unit")) |
399 | } |
400 | u.doc.PrivateAddress = address |
401 | return nil |
402 | @@ -609,7 +609,7 @@ |
403 | }} |
404 | err := u.st.runner.Run(ops, "", nil) |
405 | if err != nil { |
406 | - return fmt.Errorf("cannot clear resolved mode for unit %q: %v", u, &NotFoundError{"unit"}) |
407 | + return fmt.Errorf("cannot clear resolved mode for unit %q: %v", u, notFound("unit")) |
408 | } |
409 | u.doc.Resolved = ResolvedNone |
410 | return nil |
411 | |
412 | === modified file 'state/unit_test.go' |
413 | --- state/unit_test.go 2012-09-21 18:26:46 +0000 |
414 | +++ state/unit_test.go 2012-09-24 03:51:21 +0000 |
415 | @@ -23,6 +23,12 @@ |
416 | c.Assert(err, IsNil) |
417 | } |
418 | |
419 | +func (s *UnitSuite) TestUnitNotFound(c *C) { |
420 | + _, err := s.State.Unit("subway/0") |
421 | + c.Assert(err, ErrorMatches, `unit "subway/0" not found`) |
422 | + c.Assert(state.IsNotFound(err), Equals, true) |
423 | +} |
424 | + |
425 | func (s *UnitSuite) TestGetSetPublicAddress(c *C) { |
426 | address, err := s.unit.PublicAddress() |
427 | c.Assert(err, ErrorMatches, `public address of unit "wordpress/0" not found`) |
Reviewers: mp+125917_ code.launchpad. net,
Message:
Please take a look.
Description:
state: getter methods return NotFoundError
Due to the in-progress lifecycle changes, client code
must be able to distinguish not found errors from other
kinds of errors in client code.
https:/ /code.launchpad .net/~niemeyer/ juju-core/ resource- not-found/ +merge/ 125917
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/6549056/
Affected files: deploy_ test.go expose_ test.go unexpose_ test.go test.go test.go test.go test.go
A [revision details]
M cmd/juju/
M cmd/juju/
M cmd/juju/
M state/assign_
M state/charm_test.go
M state/confignode.go
M state/machine.go
M state/machine_
M state/relation_
M state/service_
M state/state.go
M state/state_test.go
M state/unit.go
M state/unit_test.go