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