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  }