github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/common/unitswatcher.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 "github.com/juju/errors" 8 "github.com/juju/juju/apiserver/params" 9 "github.com/juju/juju/state" 10 "github.com/juju/juju/state/watcher" 11 "github.com/juju/names" 12 ) 13 14 // UnitsWatcher implements a common WatchUnits method for use by 15 // various facades. 16 type UnitsWatcher struct { 17 st state.EntityFinder 18 resources *Resources 19 getCanWatch GetAuthFunc 20 } 21 22 // NewUnitsWatcher returns a new UnitsWatcher. The GetAuthFunc will be 23 // used on each invocation of WatchUnits to determine current 24 // permissions. 25 func NewUnitsWatcher(st state.EntityFinder, resources *Resources, getCanWatch GetAuthFunc) *UnitsWatcher { 26 return &UnitsWatcher{ 27 st: st, 28 resources: resources, 29 getCanWatch: getCanWatch, 30 } 31 } 32 33 func (u *UnitsWatcher) watchOneEntityUnits(canWatch AuthFunc, tag names.Tag) (params.StringsWatchResult, error) { 34 nothing := params.StringsWatchResult{} 35 if !canWatch(tag) { 36 return nothing, ErrPerm 37 } 38 entity0, err := u.st.FindEntity(tag) 39 if err != nil { 40 return nothing, err 41 } 42 entity, ok := entity0.(state.UnitsWatcher) 43 if !ok { 44 return nothing, NotSupportedError(tag, "watching units") 45 } 46 watch := entity.WatchUnits() 47 // Consume the initial event and forward it to the result. 48 if changes, ok := <-watch.Changes(); ok { 49 return params.StringsWatchResult{ 50 StringsWatcherId: u.resources.Register(watch), 51 Changes: changes, 52 }, nil 53 } 54 return nothing, watcher.EnsureErr(watch) 55 } 56 57 // WatchUnits starts a StringsWatcher to watch all units belonging to 58 // to any entity (machine or service) passed in args. 59 func (u *UnitsWatcher) WatchUnits(args params.Entities) (params.StringsWatchResults, error) { 60 result := params.StringsWatchResults{ 61 Results: make([]params.StringsWatchResult, len(args.Entities)), 62 } 63 if len(args.Entities) == 0 { 64 return result, nil 65 } 66 canWatch, err := u.getCanWatch() 67 if err != nil { 68 return params.StringsWatchResults{}, errors.Trace(err) 69 } 70 for i, entity := range args.Entities { 71 tag, err := names.ParseTag(entity.Tag) 72 if err != nil { 73 result.Results[i].Error = ServerError(ErrPerm) 74 continue 75 } 76 entityResult, err := u.watchOneEntityUnits(canWatch, tag) 77 result.Results[i] = entityResult 78 result.Results[i].Error = ServerError(err) 79 } 80 return result, nil 81 }