Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(833)

Side by Side Diff: state/apiserver/apiserver.go

Issue 9714044: state/api: New client API watchers; api.State (Closed)
Patch Set: Created 11 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« state/apiserver/api_test.go ('K') | « state/apiserver/api_test.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 Canonical Ltd. 1 // Copyright 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package apiserver 4 package apiserver
5 5
6 import ( 6 import (
7 "fmt" 7 "fmt"
8 "launchpad.net/juju-core/charm" 8 "launchpad.net/juju-core/charm"
9 "launchpad.net/juju-core/juju" 9 "launchpad.net/juju-core/juju"
10 "launchpad.net/juju-core/log" 10 "launchpad.net/juju-core/log"
11 "launchpad.net/juju-core/state" 11 "launchpad.net/juju-core/state"
12 "launchpad.net/juju-core/state/api" 12 "launchpad.net/juju-core/state/api"
13 "launchpad.net/juju-core/state/api/params" 13 "launchpad.net/juju-core/state/api/params"
14 "launchpad.net/juju-core/state/multiwatcher" 14 "launchpad.net/juju-core/state/multiwatcher"
15 "launchpad.net/juju-core/state/presence" 15 "launchpad.net/juju-core/state/presence"
16 "launchpad.net/juju-core/state/statecmd" 16 "launchpad.net/juju-core/state/statecmd"
17 statewatcher "launchpad.net/juju-core/state/watcher" 17 statewatcher "launchpad.net/juju-core/state/watcher"
18 "strconv" 18 "strconv"
19 "sync" 19 "sync"
20 ) 20 )
21 21
22 // srvRoot represents a single client's connection to the state. 22 // srvRoot represents a single client's connection to the state.
23 type srvRoot struct { 23 type srvRoot struct {
24 admin *srvAdmin 24 admin *srvAdmin
25 client *srvClient 25 client *srvClient
26 state *srvState
26 srv *Server 27 srv *Server
27 resources *resources 28 resources *resources
28 29
29 user authUser 30 user authUser
30 } 31 }
31 32
32 // srvAdmin is the only object that unlogged-in 33 // srvAdmin is the only object that unlogged-in
33 // clients can access. It holds any methods 34 // clients can access. It holds any methods
34 // that are needed to log in. 35 // that are needed to log in.
35 type srvAdmin struct { 36 type srvAdmin struct {
(...skipping 16 matching lines...) Expand all
52 type srvUser struct { 53 type srvUser struct {
53 root *srvRoot 54 root *srvRoot
54 u *state.User 55 u *state.User
55 } 56 }
56 57
57 // srvClient serves client-specific API methods. 58 // srvClient serves client-specific API methods.
58 type srvClient struct { 59 type srvClient struct {
59 root *srvRoot 60 root *srvRoot
60 } 61 }
61 62
63 // srvState serves agent-specific top-level state API methods.
64 type srvState struct {
65 root *srvRoot
66 }
67
68 // WatchMachines registers a srvLifecycleWatcher that notifies of
69 // changes to the lifecycles of the machines in the environment. The
70 // result contains the id of the registered watcher and the initial
71 // list of machine ids.
72 func (s *srvState) WatchMachines() (params.LifecycleWatchResults, error) {
rog 2013/05/24 13:35:13 these two methods should be further down the file,
dimitern 2013/05/24 14:07:44 Done.
73 watcher := s.root.srv.state.WatchMachines()
74 // To save an extra round-trip to call Next after Watch, we check
75 // for initial changes.
76 initial, ok := <-watcher.Changes()
77 if !ok {
78 return params.LifecycleWatchResults{}, statewatcher.MustErr(watc her)
79 }
80 return params.LifecycleWatchResults{
81 LifecycleWatcherId: s.root.resources.register(watcher).id,
82 Ids: initial,
83 }, nil
84 }
85
86 // WatchEnvironConfig registers a srvEnvironConfigWatcher for
87 // observing changes to the environment configuration. The result
88 // contains the id of the registered watcher and the current
89 // environment configuration.
90 func (s *srvState) WatchEnvironConfig() (params.EnvironConfigWatchResults, error ) {
91 watcher := s.root.srv.state.WatchEnvironConfig()
rog 2013/05/24 13:35:13 // TODO restrict access to environment manager mac
dimitern 2013/05/24 14:07:44 No need, I added the authEnvironManager check anyw
92 // To save an extra round-trip to call Next after Watch, we check
rog 2013/05/24 13:35:13 // The watcher always sends an initial value on th
dimitern 2013/05/24 14:07:44 Done. Also updated the other places.
93 // for initial changes.
94 initial, ok := <-watcher.Changes()
95 if !ok {
96 return params.EnvironConfigWatchResults{}, statewatcher.MustErr( watcher)
97 }
98 return params.EnvironConfigWatchResults{
99 EnvironConfigWatcherId: s.root.resources.register(watcher).id,
100 Config: initial.AllAttrs(),
101 }, nil
102 }
103
62 func newStateServer(srv *Server) *srvRoot { 104 func newStateServer(srv *Server) *srvRoot {
63 r := &srvRoot{ 105 r := &srvRoot{
64 srv: srv, 106 srv: srv,
65 resources: newResources(), 107 resources: newResources(),
66 } 108 }
67 r.admin = &srvAdmin{ 109 r.admin = &srvAdmin{
68 root: r, 110 root: r,
69 } 111 }
70 r.client = &srvClient{ 112 r.client = &srvClient{
71 root: r, 113 root: r,
72 } 114 }
115 r.state = &srvState{
116 root: r,
117 }
73 return r 118 return r
74 } 119 }
75 120
76 // Kill implements rpc.Killer. It cleans up any resources that need 121 // Kill implements rpc.Killer. It cleans up any resources that need
77 // cleaning up to ensure that all outstanding requests return. 122 // cleaning up to ensure that all outstanding requests return.
78 func (r *srvRoot) Kill() { 123 func (r *srvRoot) Kill() {
79 r.resources.stopAll() 124 r.resources.stopAll()
80 } 125 }
81 126
82 // Admin returns an object that provides API access 127 // Admin returns an object that provides API access
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 watcher := r.resources.get(id) 249 watcher := r.resources.get(id)
205 if watcher == nil { 250 if watcher == nil {
206 return srvEntityWatcher{}, errUnknownWatcher 251 return srvEntityWatcher{}, errUnknownWatcher
207 } 252 }
208 if _, ok := watcher.resource.(*state.EntityWatcher); !ok { 253 if _, ok := watcher.resource.(*state.EntityWatcher); !ok {
209 return srvEntityWatcher{}, errUnknownWatcher 254 return srvEntityWatcher{}, errUnknownWatcher
210 } 255 }
211 return srvEntityWatcher{watcher}, nil 256 return srvEntityWatcher{watcher}, nil
212 } 257 }
213 258
259 // LifecycleWatcher returns an object that provides
260 // API access to methods on a state.LifecycleWatcher.
261 // Each client has its own current set of watchers, stored
262 // in r.resources.
263 func (r *srvRoot) LifecycleWatcher(id string) (srvLifecycleWatcher, error) {
264 if err := r.requireAgent(); err != nil {
265 return srvLifecycleWatcher{}, err
266 }
267 watcher := r.resources.get(id)
268 if watcher == nil {
269 return srvLifecycleWatcher{}, errUnknownWatcher
270 }
271 if _, ok := watcher.resource.(*state.LifecycleWatcher); !ok {
272 return srvLifecycleWatcher{}, errUnknownWatcher
273 }
274 return srvLifecycleWatcher{watcher}, nil
275 }
276
277 // EnvironConfigWatcher returns an object that provides
278 // API access to methods on a state.EnvironConfigWatcher.
279 // Each client has its own current set of watchers, stored
280 // in r.resources.
281 func (r *srvRoot) EnvironConfigWatcher(id string) (srvEnvironConfigWatcher, erro r) {
282 if err := r.requireAgent(); err != nil {
283 return srvEnvironConfigWatcher{}, err
284 }
285 watcher := r.resources.get(id)
286 if watcher == nil {
287 return srvEnvironConfigWatcher{}, errUnknownWatcher
288 }
289 if _, ok := watcher.resource.(*state.EnvironConfigWatcher); !ok {
290 return srvEnvironConfigWatcher{}, errUnknownWatcher
291 }
292 return srvEnvironConfigWatcher{watcher}, nil
293 }
294
214 // AllWatcher returns an object that provides API access to methods on 295 // AllWatcher returns an object that provides API access to methods on
215 // a state/multiwatcher.Watcher, which watches any changes to the 296 // a state/multiwatcher.Watcher, which watches any changes to the
216 // state. Each client has its own current set of watchers, stored in 297 // state. Each client has its own current set of watchers, stored in
217 // r.resources. 298 // r.resources.
218 func (r *srvRoot) AllWatcher(id string) (srvClientAllWatcher, error) { 299 func (r *srvRoot) AllWatcher(id string) (srvClientAllWatcher, error) {
219 if err := r.requireClient(); err != nil { 300 if err := r.requireClient(); err != nil {
220 return srvClientAllWatcher{}, err 301 return srvClientAllWatcher{}, err
221 } 302 }
222 watcher := r.resources.get(id) 303 watcher := r.resources.get(id)
223 if watcher == nil { 304 if watcher == nil {
224 return srvClientAllWatcher{}, errUnknownWatcher 305 return srvClientAllWatcher{}, errUnknownWatcher
225 } 306 }
226 if _, ok := watcher.resource.(*multiwatcher.Watcher); !ok { 307 if _, ok := watcher.resource.(*multiwatcher.Watcher); !ok {
227 return srvClientAllWatcher{}, errUnknownWatcher 308 return srvClientAllWatcher{}, errUnknownWatcher
228 } 309 }
229 return srvClientAllWatcher{watcher}, nil 310 return srvClientAllWatcher{watcher}, nil
230 311
231 } 312 }
232 313
314 // State returns an object that provides API access to top-level state methods.
315 func (r *srvRoot) State(id string) (*srvState, error) {
316 if err := r.requireAgent(); err != nil {
317 return nil, err
318 }
319 if id != "" {
320 // Safeguard id for possible future use.
321 return nil, errBadId
322 }
323 return r.state, nil
324 }
325
233 // Client returns an object that provides access 326 // Client returns an object that provides access
234 // to methods accessible to non-agent clients. 327 // to methods accessible to non-agent clients.
235 func (r *srvRoot) Client(id string) (*srvClient, error) { 328 func (r *srvRoot) Client(id string) (*srvClient, error) {
236 if err := r.requireClient(); err != nil { 329 if err := r.requireClient(); err != nil {
237 return nil, err 330 return nil, err
238 } 331 }
239 if id != "" { 332 if id != "" {
240 // Safeguard id for possible future use. 333 // Safeguard id for possible future use.
241 return nil, errBadId 334 return nil, errBadId
242 } 335 }
(...skipping 30 matching lines...) Expand all
273 if _, ok := <-watcher.Changes(); ok { 366 if _, ok := <-watcher.Changes(); ok {
274 return nil 367 return nil
275 } 368 }
276 err := watcher.Err() 369 err := watcher.Err()
277 if err == nil { 370 if err == nil {
278 err = errStoppedWatcher 371 err = errStoppedWatcher
279 } 372 }
280 return err 373 return err
281 } 374 }
282 375
376 // srvLifecycleWatcher notifies about lifecycle changes for all
377 // entities of a given kind. See state.LifecycleWatcher.
378 type srvLifecycleWatcher struct {
379 *srvResource
380 }
381
382 // Next returns when a change has occured to the lifecycle of an
383 // entity of the collection being watched since the most recent call
384 // to Next or the Watch call that created the srvLifecycleWatcher.
385 func (w srvLifecycleWatcher) Next() (params.LifecycleWatchResults, error) {
386 watcher := w.resource.(*state.LifecycleWatcher)
387 if changes, ok := <-watcher.Changes(); ok {
388 return params.LifecycleWatchResults{
389 Ids: changes,
390 }, nil
391 }
392 err := watcher.Err()
393 if err == nil {
394 err = errStoppedWatcher
395 }
396 return params.LifecycleWatchResults{}, err
397 }
398
399 // srvEnvironConfigWatcher notifies about changes to the environment
400 // configuration. See state.EnvironConfigWatcher.
401 type srvEnvironConfigWatcher struct {
402 *srvResource
403 }
404
405 // Next returns when a change has occured to the environment
406 // configuration since the most recent call to Next or the Watch call
407 // that created the srvEnvironConfigWatcher.
408 func (w srvEnvironConfigWatcher) Next() (params.EnvironConfigWatchResults, error ) {
409 watcher := w.resource.(*state.EnvironConfigWatcher)
410 if changes, ok := <-watcher.Changes(); ok {
411 return params.EnvironConfigWatchResults{
412 Config: changes.AllAttrs(),
413 }, nil
414 }
415 err := watcher.Err()
416 if err == nil {
417 err = errStoppedWatcher
418 }
419 return params.EnvironConfigWatchResults{}, err
420 }
421
283 func (c *srvClient) Status() (api.Status, error) { 422 func (c *srvClient) Status() (api.Status, error) {
284 ms, err := c.root.srv.state.AllMachines() 423 ms, err := c.root.srv.state.AllMachines()
285 if err != nil { 424 if err != nil {
286 return api.Status{}, err 425 return api.Status{}, err
287 } 426 }
288 status := api.Status{ 427 status := api.Status{
289 Machines: make(map[string]api.MachineInfo), 428 Machines: make(map[string]api.MachineInfo),
290 } 429 }
291 for _, m := range ms { 430 for _, m := range ms {
292 instId, _ := m.InstanceId() 431 instId, _ := m.InstanceId()
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 652
514 // Get retrieves all the details of a machine. 653 // Get retrieves all the details of a machine.
515 func (m *srvMachine) Get() (info params.Machine) { 654 func (m *srvMachine) Get() (info params.Machine) {
516 instId, _ := m.m.InstanceId() 655 instId, _ := m.m.InstanceId()
517 info.InstanceId = string(instId) 656 info.InstanceId = string(instId)
518 info.Life = params.Life(m.m.Life().String()) 657 info.Life = params.Life(m.m.Life().String())
519 return 658 return
520 } 659 }
521 660
522 func (m *srvMachine) Watch() (params.EntityWatcherId, error) { 661 func (m *srvMachine) Watch() (params.EntityWatcherId, error) {
523 » w := m.m.Watch() 662 » watcher := m.m.Watch()
524 » if _, ok := <-w.Changes(); !ok { 663 » // To save an extra round-trip to call Next after Watch, we check
525 » » return params.EntityWatcherId{}, statewatcher.MustErr(w) 664 » // for initial changes.
665 » if _, ok := <-watcher.Changes(); !ok {
666 » » return params.EntityWatcherId{}, statewatcher.MustErr(watcher)
526 } 667 }
527 return params.EntityWatcherId{ 668 return params.EntityWatcherId{
528 » » EntityWatcherId: m.root.resources.register(w).id, 669 » » EntityWatcherId: m.root.resources.register(watcher).id,
529 }, nil 670 }, nil
530 } 671 }
531 672
532 // SetAgentAlive signals that the agent for machine m is alive. 673 // SetAgentAlive signals that the agent for machine m is alive.
533 func (m *srvMachine) SetAgentAlive() (params.PingerId, error) { 674 func (m *srvMachine) SetAgentAlive() (params.PingerId, error) {
534 if !m.root.authOwner(m.m) { 675 if !m.root.authOwner(m.m) {
535 return params.PingerId{}, errPerm 676 return params.PingerId{}, errPerm
536 } 677 }
537 pinger, err := m.m.SetAgentAlive() 678 pinger, err := m.m.SetAgentAlive()
538 if err != nil { 679 if err != nil {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 func (rs *resources) stopAll() { 882 func (rs *resources) stopAll() {
742 rs.mu.Lock() 883 rs.mu.Lock()
743 defer rs.mu.Unlock() 884 defer rs.mu.Unlock()
744 for _, r := range rs.rs { 885 for _, r := range rs.rs {
745 if err := r.resource.Stop(); err != nil { 886 if err := r.resource.Stop(); err != nil {
746 log.Errorf("state/api: error stopping %T resource: %v", r, err) 887 log.Errorf("state/api: error stopping %T resource: %v", r, err)
747 } 888 }
748 } 889 }
749 rs.rs = make(map[string]*srvResource) 890 rs.rs = make(map[string]*srvResource)
750 } 891 }
OLDNEW
« state/apiserver/api_test.go ('K') | « state/apiserver/api_test.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b