github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/state/apiserver/common/watch.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "launchpad.net/juju-core/state" 8 "launchpad.net/juju-core/state/api/params" 9 "launchpad.net/juju-core/state/watcher" 10 ) 11 12 // AgentEntityWatcher implements a common Watch method for use by 13 // various facades. 14 type AgentEntityWatcher struct { 15 st state.EntityFinder 16 resources *Resources 17 getCanWatch GetAuthFunc 18 } 19 20 // NewAgentEntityWatcher returns a new AgentEntityWatcher. The 21 // GetAuthFunc will be used on each invocation of Watch to determine 22 // current permissions. 23 func NewAgentEntityWatcher(st state.EntityFinder, resources *Resources, getCanWatch GetAuthFunc) *AgentEntityWatcher { 24 return &AgentEntityWatcher{ 25 st: st, 26 resources: resources, 27 getCanWatch: getCanWatch, 28 } 29 } 30 31 func (a *AgentEntityWatcher) watchEntity(tag string) (string, error) { 32 entity0, err := a.st.FindEntity(tag) 33 if err != nil { 34 return "", err 35 } 36 entity, ok := entity0.(state.NotifyWatcherFactory) 37 if !ok { 38 return "", NotSupportedError(tag, "watching") 39 } 40 watch := entity.Watch() 41 // Consume the initial event. Technically, API 42 // calls to Watch 'transmit' the initial event 43 // in the Watch response. But NotifyWatchers 44 // have no state to transmit. 45 if _, ok := <-watch.Changes(); ok { 46 return a.resources.Register(watch), nil 47 } 48 return "", watcher.MustErr(watch) 49 } 50 51 // Watch starts an NotifyWatcher for each given entity. 52 func (a *AgentEntityWatcher) Watch(args params.Entities) (params.NotifyWatchResults, error) { 53 result := params.NotifyWatchResults{ 54 Results: make([]params.NotifyWatchResult, len(args.Entities)), 55 } 56 if len(args.Entities) == 0 { 57 return result, nil 58 } 59 canWatch, err := a.getCanWatch() 60 if err != nil { 61 return params.NotifyWatchResults{}, err 62 } 63 for i, entity := range args.Entities { 64 err := ErrPerm 65 watcherId := "" 66 if canWatch(entity.Tag) { 67 watcherId, err = a.watchEntity(entity.Tag) 68 } 69 result.Results[i].NotifyWatcherId = watcherId 70 result.Results[i].Error = ServerError(err) 71 } 72 return result, nil 73 }