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