Merge lp:~thumper/juju-core/common-api-env-watcher into lp:~go-bot/juju-core/trunk

Proposed by Tim Penhey
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 2243
Proposed branch: lp:~thumper/juju-core/common-api-env-watcher
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 522 lines (+111/-75)
14 files modified
state/api/agent/state.go (+3/-3)
state/api/base/caller.go (+1/-1)
state/api/charmrevisionupdater/updater.go (+3/-3)
state/api/common/environwatcher.go (+56/-0)
state/api/common/life.go (+2/-1)
state/api/deployer/deployer.go (+3/-2)
state/api/firewaller/firewaller.go (+3/-2)
state/api/keyupdater/authorisedkeys.go (+3/-3)
state/api/logger/logger.go (+3/-3)
state/api/machiner/machiner.go (+3/-2)
state/api/provisioner/provisioner.go (+18/-43)
state/api/uniter/uniter.go (+3/-2)
state/api/upgrader/upgrader.go (+3/-3)
state/api/watcher/watcher.go (+7/-7)
To merge this branch: bzr merge lp:~thumper/juju-core/common-api-env-watcher
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+202766@code.launchpad.net

Commit message

Refactor client side api to have common behaviour

The apiserver components have a common packge that
enables other end points to share the implementation
of some common facilities.

The api client side should also have this common
behaviour.

This branch starts this with the environ watcher
and getter for the provisioner. This will be used
by the Uniter in the next branch.

In order to reduce import cycles the common.Caller
interface had to be moved. It was either that or to
have the common code in a different package. I
decided that it was better to have the same package
name for the common code on both the client and
server side for the api, so common.Caller becomes
base.Caller.

https://codereview.appspot.com/52610045/

Description of the change

Refactor client side api to have common behaviour

The apiserver components have a common packge that
enables other end points to share the implementation
of some common facilities.

The api client side should also have this common
behaviour.

This branch starts this with the environ watcher
and getter for the provisioner. This will be used
by the Uniter in the next branch.

In order to reduce import cycles the common.Caller
interface had to be moved. It was either that or to
have the common code in a different package. I
decided that it was better to have the same package
name for the common code on both the client and
server side for the api, so common.Caller becomes
base.Caller.

https://codereview.appspot.com/52610045/

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Reviewers: mp+202766_code.launchpad.net,

Message:
Please take a look.

Description:
Refactor client side api to have common behaviour

The apiserver components have a common packge that
enables other end points to share the implementation
of some common facilities.

The api client side should also have this common
behaviour.

This branch starts this with the environ watcher
and getter for the provisioner. This will be used
by the Uniter in the next branch.

In order to reduce import cycles the common.Caller
interface had to be moved. It was either that or to
have the common code in a different package. I
decided that it was better to have the same package
name for the common code on both the client and
server side for the api, so common.Caller becomes
base.Caller.

https://code.launchpad.net/~thumper/juju-core/common-api-env-watcher/+merge/202766

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/52610045/

Affected files (+104, -75 lines):
   A [revision details]
   M state/api/agent/state.go
   M state/api/base/caller.go
   M state/api/charmrevisionupdater/updater.go
   A state/api/common/environwatcher.go
   M state/api/deployer/deployer.go
   M state/api/keyupdater/authorisedkeys.go
   M state/api/logger/logger.go
   M state/api/machiner/machiner.go
   M state/api/provisioner/provisioner.go
   M state/api/uniter/uniter.go
   M state/api/upgrader/upgrader.go
   M state/api/watcher/watcher.go

Revision history for this message
Ian Booth (wallyworld) wrote :

LGTM with tweaks

https://codereview.appspot.com/52610045/diff/1/state/api/common/environwatcher.go
File state/api/common/environwatcher.go (right):

https://codereview.appspot.com/52610045/diff/1/state/api/common/environwatcher.go#newcode13
state/api/common/environwatcher.go:13: type EnvironWatcher struct {
doc comment

https://codereview.appspot.com/52610045/diff/1/state/api/common/environwatcher.go#newcode14
state/api/common/environwatcher.go:14: name string
perhaps facadeName?

https://codereview.appspot.com/52610045/diff/1/state/api/common/environwatcher.go#newcode18
state/api/common/environwatcher.go:18: func NewEnvironWatcher(name
string, caller base.Caller) *EnvironWatcher {
ditto

https://codereview.appspot.com/52610045/diff/1/state/api/provisioner/provisioner.go
File state/api/provisioner/provisioner.go (right):

https://codereview.appspot.com/52610045/diff/1/state/api/provisioner/provisioner.go#newcode16
state/api/provisioner/provisioner.go:16: const Provisioner =
"Provisioner"
lower case please, no need to export

https://codereview.appspot.com/52610045/

Revision history for this message
Go Bot (go-bot) wrote :

Attempt to merge into lp:juju-core failed due to conflicts:

text conflict in state/api/deployer/deployer.go
text conflict in state/api/machiner/machiner.go
text conflict in state/api/provisioner/provisioner.go

Revision history for this message
Go Bot (go-bot) wrote :

The attempt to merge lp:~thumper/juju-core/common-api-env-watcher into lp:juju-core failed. Below is the output from the failed tests.

# launchpad.net/juju-core/state/api/deployer
state/api/deployer/deployer.go:24: undefined: common
state/api/deployer/deployer.go:24: not enough arguments to return
# launchpad.net/juju-core/state/api/common
state/api/common/life.go:14: undefined: Caller
# launchpad.net/juju-core/state/api/machiner
state/api/machiner/machiner.go:23: undefined: common
state/api/machiner/machiner.go:23: not enough arguments to return
# launchpad.net/juju-core/state/api/uniter
state/api/uniter/uniter.go:29: undefined: common
state/api/uniter/uniter.go:29: not enough arguments to return

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'state/api/agent/state.go'
2--- state/api/agent/state.go 2013-10-01 10:00:26 +0000
3+++ state/api/agent/state.go 2014-01-23 00:09:43 +0000
4@@ -7,18 +7,18 @@
5 "fmt"
6
7 "launchpad.net/juju-core/instance"
8- "launchpad.net/juju-core/state/api/common"
9+ "launchpad.net/juju-core/state/api/base"
10 "launchpad.net/juju-core/state/api/params"
11 )
12
13 // State provides access to an agent's view of the state.
14 type State struct {
15- caller common.Caller
16+ caller base.Caller
17 }
18
19 // NewState returns a version of the state that provides functionality
20 // required by agent code.
21-func NewState(caller common.Caller) *State {
22+func NewState(caller base.Caller) *State {
23 return &State{caller}
24 }
25
26
27=== added directory 'state/api/base'
28=== renamed file 'state/api/common/interfaces.go' => 'state/api/base/caller.go'
29--- state/api/common/interfaces.go 2013-06-06 09:56:00 +0000
30+++ state/api/base/caller.go 2014-01-23 00:09:43 +0000
31@@ -1,7 +1,7 @@
32 // Copyright 2012, 2013 Canonical Ltd.
33 // Licensed under the AGPLv3, see LICENCE file for details.
34
35-package common
36+package base
37
38 // Caller is implemented by the client-facing State object.
39 type Caller interface {
40
41=== modified file 'state/api/charmrevisionupdater/updater.go'
42--- state/api/charmrevisionupdater/updater.go 2014-01-15 07:23:28 +0000
43+++ state/api/charmrevisionupdater/updater.go 2014-01-23 00:09:43 +0000
44@@ -4,17 +4,17 @@
45 package charmrevisionupdater
46
47 import (
48- "launchpad.net/juju-core/state/api/common"
49+ "launchpad.net/juju-core/state/api/base"
50 "launchpad.net/juju-core/state/api/params"
51 )
52
53 // State provides access to a worker's view of the state.
54 type State struct {
55- caller common.Caller
56+ caller base.Caller
57 }
58
59 // NewState returns a version of the state that provides functionality required by the worker.
60-func NewState(caller common.Caller) *State {
61+func NewState(caller base.Caller) *State {
62 return &State{caller}
63 }
64
65
66=== added file 'state/api/common/environwatcher.go'
67--- state/api/common/environwatcher.go 1970-01-01 00:00:00 +0000
68+++ state/api/common/environwatcher.go 2014-01-23 00:09:43 +0000
69@@ -0,0 +1,56 @@
70+// Copyright 2014 Canonical Ltd.
71+// Licensed under the AGPLv3, see LICENCE file for details.
72+
73+package common
74+
75+import (
76+ "launchpad.net/juju-core/environs/config"
77+ "launchpad.net/juju-core/state/api/base"
78+ "launchpad.net/juju-core/state/api/params"
79+ "launchpad.net/juju-core/state/api/watcher"
80+)
81+
82+// EnvironWatcher provides common client side api functions
83+// to call into the apiserver.common.EnvironWatcher.
84+type EnvironWatcher struct {
85+ façadeName string
86+ caller base.Caller
87+}
88+
89+// NewEnvironWatcher creates a EnvironWatcher on the specified façade,
90+// and uses this name when calling through the caller.
91+func NewEnvironWatcher(façadeName string, caller base.Caller) *EnvironWatcher {
92+ return &EnvironWatcher{façadeName, caller}
93+}
94+
95+// WatchForEnvironConfigChanges return a NotifyWatcher waiting for the
96+// environment configuration to change.
97+func (e *EnvironWatcher) WatchForEnvironConfigChanges() (watcher.NotifyWatcher, error) {
98+ var result params.NotifyWatchResult
99+ err := e.caller.Call(e.façadeName, "", "WatchForEnvironConfigChanges", nil, &result)
100+ if err != nil {
101+ return nil, err
102+ }
103+ if err := result.Error; err != nil {
104+ return nil, result.Error
105+ }
106+ w := watcher.NewNotifyWatcher(e.caller, result)
107+ return w, nil
108+}
109+
110+// EnvironConfig returns the current environment configuration.
111+func (e *EnvironWatcher) EnvironConfig() (*config.Config, error) {
112+ var result params.EnvironConfigResult
113+ err := e.caller.Call(e.façadeName, "", "EnvironConfig", nil, &result)
114+ if err != nil {
115+ return nil, err
116+ }
117+ if err := result.Error; err != nil {
118+ return nil, err
119+ }
120+ conf, err := config.New(config.NoDefaults, result.Config)
121+ if err != nil {
122+ return nil, err
123+ }
124+ return conf, nil
125+}
126
127=== modified file 'state/api/common/life.go'
128--- state/api/common/life.go 2014-01-22 22:36:32 +0000
129+++ state/api/common/life.go 2014-01-23 00:09:43 +0000
130@@ -6,12 +6,13 @@
131 import (
132 "fmt"
133
134+ "launchpad.net/juju-core/state/api/base"
135 "launchpad.net/juju-core/state/api/params"
136 )
137
138 // Life requests the life cycle of the given entity from the given
139 // server-side API facade via the given caller.
140-func Life(caller Caller, facadeName, tag string) (params.Life, error) {
141+func Life(caller base.Caller, facadeName, tag string) (params.Life, error) {
142 var result params.LifeResults
143 args := params.Entities{
144 Entities: []params.Entity{{Tag: tag}},
145
146=== modified file 'state/api/deployer/deployer.go'
147--- state/api/deployer/deployer.go 2014-01-22 22:36:32 +0000
148+++ state/api/deployer/deployer.go 2014-01-23 00:09:43 +0000
149@@ -4,18 +4,19 @@
150 package deployer
151
152 import (
153+ "launchpad.net/juju-core/state/api/base"
154 "launchpad.net/juju-core/state/api/common"
155 "launchpad.net/juju-core/state/api/params"
156 )
157
158 // State provides access to the deployer worker's idea of the state.
159 type State struct {
160- caller common.Caller
161+ caller base.Caller
162 }
163
164 // NewState creates a new State instance that makes API calls
165 // through the given caller.
166-func NewState(caller common.Caller) *State {
167+func NewState(caller base.Caller) *State {
168 return &State{caller}
169 }
170
171
172=== modified file 'state/api/firewaller/firewaller.go'
173--- state/api/firewaller/firewaller.go 2014-01-22 22:36:32 +0000
174+++ state/api/firewaller/firewaller.go 2014-01-23 00:09:43 +0000
175@@ -5,6 +5,7 @@
176
177 import (
178 "launchpad.net/juju-core/environs/config"
179+ "launchpad.net/juju-core/state/api/base"
180 "launchpad.net/juju-core/state/api/common"
181 "launchpad.net/juju-core/state/api/params"
182 "launchpad.net/juju-core/state/api/watcher"
183@@ -12,11 +13,11 @@
184
185 // State provides access to the Firewaller API facade.
186 type State struct {
187- caller common.Caller
188+ caller base.Caller
189 }
190
191 // NewState creates a new client-side Firewaller facade.
192-func NewState(caller common.Caller) *State {
193+func NewState(caller base.Caller) *State {
194 return &State{caller}
195 }
196
197
198=== modified file 'state/api/keyupdater/authorisedkeys.go'
199--- state/api/keyupdater/authorisedkeys.go 2013-12-09 11:40:27 +0000
200+++ state/api/keyupdater/authorisedkeys.go 2014-01-23 00:09:43 +0000
201@@ -6,18 +6,18 @@
202 import (
203 "fmt"
204
205- "launchpad.net/juju-core/state/api/common"
206+ "launchpad.net/juju-core/state/api/base"
207 "launchpad.net/juju-core/state/api/params"
208 "launchpad.net/juju-core/state/api/watcher"
209 )
210
211 // State provides access to a worker's view of the state.
212 type State struct {
213- caller common.Caller
214+ caller base.Caller
215 }
216
217 // NewState returns a version of the state that provides functionality required by the worker.
218-func NewState(caller common.Caller) *State {
219+func NewState(caller base.Caller) *State {
220 return &State{caller}
221 }
222
223
224=== modified file 'state/api/logger/logger.go'
225--- state/api/logger/logger.go 2013-09-13 04:27:17 +0000
226+++ state/api/logger/logger.go 2014-01-23 00:09:43 +0000
227@@ -6,19 +6,19 @@
228 import (
229 "fmt"
230
231- "launchpad.net/juju-core/state/api/common"
232+ "launchpad.net/juju-core/state/api/base"
233 "launchpad.net/juju-core/state/api/params"
234 "launchpad.net/juju-core/state/api/watcher"
235 )
236
237 // State provides access to an logger worker's view of the state.
238 type State struct {
239- caller common.Caller
240+ caller base.Caller
241 }
242
243 // NewState returns a version of the state that provides functionality
244 // required by the logger worker.
245-func NewState(caller common.Caller) *State {
246+func NewState(caller base.Caller) *State {
247 return &State{caller}
248 }
249
250
251=== modified file 'state/api/machiner/machiner.go'
252--- state/api/machiner/machiner.go 2014-01-22 22:36:32 +0000
253+++ state/api/machiner/machiner.go 2014-01-23 00:09:43 +0000
254@@ -4,17 +4,18 @@
255 package machiner
256
257 import (
258+ "launchpad.net/juju-core/state/api/base"
259 "launchpad.net/juju-core/state/api/common"
260 "launchpad.net/juju-core/state/api/params"
261 )
262
263 // State provides access to the Machiner API facade.
264 type State struct {
265- caller common.Caller
266+ caller base.Caller
267 }
268
269 // NewState creates a new client-side Machiner facade.
270-func NewState(caller common.Caller) *State {
271+func NewState(caller base.Caller) *State {
272 return &State{caller}
273 }
274
275
276=== modified file 'state/api/provisioner/provisioner.go'
277--- state/api/provisioner/provisioner.go 2014-01-22 22:36:32 +0000
278+++ state/api/provisioner/provisioner.go 2014-01-23 00:09:43 +0000
279@@ -6,26 +6,33 @@
280 import (
281 "fmt"
282
283- "launchpad.net/juju-core/environs/config"
284+ "launchpad.net/juju-core/state/api/base"
285 "launchpad.net/juju-core/state/api/common"
286 "launchpad.net/juju-core/state/api/params"
287 "launchpad.net/juju-core/state/api/watcher"
288 "launchpad.net/juju-core/tools"
289 )
290
291+const provisioner = "Provisioner"
292+
293 // State provides access to the Machiner API facade.
294 type State struct {
295- caller common.Caller
296+ *common.EnvironWatcher
297+
298+ caller base.Caller
299 }
300
301 // NewState creates a new client-side Machiner facade.
302-func NewState(caller common.Caller) *State {
303- return &State{caller}
304+func NewState(caller base.Caller) *State {
305+ return &State{
306+ EnvironWatcher: common.NewEnvironWatcher(provisioner, caller),
307+
308+ caller: caller}
309 }
310
311 // machineLife requests the lifecycle of the given machine from the server.
312 func (st *State) machineLife(tag string) (params.Life, error) {
313- return common.Life(st.caller, "Provisioner", tag)
314+ return common.Life(st.caller, provisioner, tag)
315 }
316
317 // Machine provides access to methods of a state.Machine through the facade.
318@@ -41,44 +48,12 @@
319 }, nil
320 }
321
322-// WatchForEnvironConfigChanges return a NotifyWatcher waiting for the
323-// environment configuration to change.
324-func (st *State) WatchForEnvironConfigChanges() (watcher.NotifyWatcher, error) {
325- var result params.NotifyWatchResult
326- err := st.caller.Call("Provisioner", "", "WatchForEnvironConfigChanges", nil, &result)
327- if err != nil {
328- return nil, err
329- }
330- if err := result.Error; err != nil {
331- return nil, result.Error
332- }
333- w := watcher.NewNotifyWatcher(st.caller, result)
334- return w, nil
335-}
336-
337-// EnvironConfig returns the current environment configuration.
338-func (st *State) EnvironConfig() (*config.Config, error) {
339- var result params.EnvironConfigResult
340- err := st.caller.Call("Provisioner", "", "EnvironConfig", nil, &result)
341- if err != nil {
342- return nil, err
343- }
344- if err := result.Error; err != nil {
345- return nil, err
346- }
347- conf, err := config.New(config.NoDefaults, result.Config)
348- if err != nil {
349- return nil, err
350- }
351- return conf, nil
352-}
353-
354 // WatchEnvironMachines returns a StringsWatcher that notifies of
355 // changes to the lifecycles of the machines (but not containers) in
356 // the current environment.
357 func (st *State) WatchEnvironMachines() (watcher.StringsWatcher, error) {
358 var result params.StringsWatchResult
359- err := st.caller.Call("Provisioner", "", "WatchEnvironMachines", nil, &result)
360+ err := st.caller.Call(provisioner, "", "WatchEnvironMachines", nil, &result)
361 if err != nil {
362 return nil, err
363 }
364@@ -92,7 +67,7 @@
365 // StateAddresses returns the list of addresses used to connect to the state.
366 func (st *State) StateAddresses() ([]string, error) {
367 var result params.StringsResult
368- err := st.caller.Call("Provisioner", "", "StateAddresses", nil, &result)
369+ err := st.caller.Call(provisioner, "", "StateAddresses", nil, &result)
370 if err != nil {
371 return nil, err
372 }
373@@ -102,7 +77,7 @@
374 // APIAddresses returns the list of addresses used to connect to the API.
375 func (st *State) APIAddresses() ([]string, error) {
376 var result params.StringsResult
377- err := st.caller.Call("Provisioner", "", "APIAddresses", nil, &result)
378+ err := st.caller.Call(provisioner, "", "APIAddresses", nil, &result)
379 if err != nil {
380 return nil, err
381 }
382@@ -112,7 +87,7 @@
383 // CACert returns the certificate used to validate the state connection.
384 func (st *State) CACert() ([]byte, error) {
385 var result params.BytesResult
386- err := st.caller.Call("Provisioner", "", "CACert", nil, &result)
387+ err := st.caller.Call(provisioner, "", "CACert", nil, &result)
388 if err != nil {
389 return nil, err
390 }
391@@ -125,7 +100,7 @@
392 args := params.Entities{
393 Entities: []params.Entity{{Tag: tag}},
394 }
395- err := st.caller.Call("Provisioner", "", "Tools", args, &results)
396+ err := st.caller.Call(provisioner, "", "Tools", args, &results)
397 if err != nil {
398 // TODO: Not directly tested
399 return nil, err
400@@ -144,6 +119,6 @@
401 // ContainerConfig returns information from the environment config that are
402 // needed for container cloud-init.
403 func (st *State) ContainerConfig() (result params.ContainerConfig, err error) {
404- err = st.caller.Call("Provisioner", "", "ContainerConfig", nil, &result)
405+ err = st.caller.Call(provisioner, "", "ContainerConfig", nil, &result)
406 return result, err
407 }
408
409=== modified file 'state/api/uniter/uniter.go'
410--- state/api/uniter/uniter.go 2014-01-22 22:36:32 +0000
411+++ state/api/uniter/uniter.go 2014-01-23 00:09:43 +0000
412@@ -8,19 +8,20 @@
413
414 "launchpad.net/juju-core/charm"
415 "launchpad.net/juju-core/names"
416+ "launchpad.net/juju-core/state/api/base"
417 "launchpad.net/juju-core/state/api/common"
418 "launchpad.net/juju-core/state/api/params"
419 )
420
421 // State provides access to the Uniter API facade.
422 type State struct {
423- caller common.Caller
424+ caller base.Caller
425 // unitTag contains the authenticated unit's tag.
426 unitTag string
427 }
428
429 // NewState creates a new client-side Uniter facade.
430-func NewState(caller common.Caller, authTag string) *State {
431+func NewState(caller base.Caller, authTag string) *State {
432 return &State{caller, authTag}
433 }
434
435
436=== modified file 'state/api/upgrader/upgrader.go'
437--- state/api/upgrader/upgrader.go 2013-10-03 12:18:41 +0000
438+++ state/api/upgrader/upgrader.go 2014-01-23 00:09:43 +0000
439@@ -6,7 +6,7 @@
440 import (
441 "fmt"
442
443- "launchpad.net/juju-core/state/api/common"
444+ "launchpad.net/juju-core/state/api/base"
445 "launchpad.net/juju-core/state/api/params"
446 "launchpad.net/juju-core/state/api/watcher"
447 "launchpad.net/juju-core/tools"
448@@ -15,12 +15,12 @@
449
450 // State provides access to an upgrader worker's view of the state.
451 type State struct {
452- caller common.Caller
453+ caller base.Caller
454 }
455
456 // NewState returns a version of the state that provides functionality
457 // required by the upgrader worker.
458-func NewState(caller common.Caller) *State {
459+func NewState(caller base.Caller) *State {
460 return &State{caller}
461 }
462
463
464=== modified file 'state/api/watcher/watcher.go'
465--- state/api/watcher/watcher.go 2013-12-05 03:42:25 +0000
466+++ state/api/watcher/watcher.go 2014-01-23 00:09:43 +0000
467@@ -9,7 +9,7 @@
468 "launchpad.net/tomb"
469
470 "launchpad.net/juju-core/log"
471- "launchpad.net/juju-core/state/api/common"
472+ "launchpad.net/juju-core/state/api/base"
473 "launchpad.net/juju-core/state/api/params"
474 )
475
476@@ -114,14 +114,14 @@
477 // It does not send content for those changes.
478 type notifyWatcher struct {
479 commonWatcher
480- caller common.Caller
481+ caller base.Caller
482 notifyWatcherId string
483 out chan struct{}
484 }
485
486 // If an API call returns a NotifyWatchResult, you can use this to turn it into
487 // a local Watcher.
488-func NewNotifyWatcher(caller common.Caller, result params.NotifyWatchResult) NotifyWatcher {
489+func NewNotifyWatcher(caller base.Caller, result params.NotifyWatchResult) NotifyWatcher {
490 w := &notifyWatcher{
491 caller: caller,
492 notifyWatcherId: result.NotifyWatcherId,
493@@ -172,12 +172,12 @@
494 // The content of the changes is a list of strings.
495 type stringsWatcher struct {
496 commonWatcher
497- caller common.Caller
498+ caller base.Caller
499 stringsWatcherId string
500 out chan []string
501 }
502
503-func NewStringsWatcher(caller common.Caller, result params.StringsWatchResult) StringsWatcher {
504+func NewStringsWatcher(caller base.Caller, result params.StringsWatchResult) StringsWatcher {
505 w := &stringsWatcher{
506 caller: caller,
507 stringsWatcherId: result.StringsWatcherId,
508@@ -230,12 +230,12 @@
509 // those units known to have entered.
510 type relationUnitsWatcher struct {
511 commonWatcher
512- caller common.Caller
513+ caller base.Caller
514 relationUnitsWatcherId string
515 out chan params.RelationUnitsChange
516 }
517
518-func NewRelationUnitsWatcher(caller common.Caller, result params.RelationUnitsWatchResult) RelationUnitsWatcher {
519+func NewRelationUnitsWatcher(caller base.Caller, result params.RelationUnitsWatchResult) RelationUnitsWatcher {
520 w := &relationUnitsWatcher{
521 caller: caller,
522 relationUnitsWatcherId: result.RelationUnitsWatcherId,

Subscribers

People subscribed via source and target branches

to status/vote changes: