github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/meterstatus/meterstatus.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  // Package meterstatus provides the meter status API facade.
     5  package meterstatus
     6  
     7  import (
     8  	"github.com/juju/names"
     9  
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/apiserver/params"
    12  	"github.com/juju/juju/state"
    13  	"github.com/juju/juju/state/watcher"
    14  )
    15  
    16  func init() {
    17  	common.RegisterStandardFacade("MeterStatus", 1, NewMeterStatusAPI)
    18  }
    19  
    20  // MeterStatus defines the methods exported by the meter status API facade.
    21  type MeterStatus interface {
    22  	GetMeterStatus(args params.Entities) (params.MeterStatusResults, error)
    23  	WatchMeterStatus(args params.Entities) (params.NotifyWatchResults, error)
    24  }
    25  
    26  // MeterStatusAPI implements the MeterStatus interface and is the concrete implementation
    27  // of the API endpoint.
    28  type MeterStatusAPI struct {
    29  	state      *state.State
    30  	accessUnit common.GetAuthFunc
    31  	resources  *common.Resources
    32  }
    33  
    34  // NewMeterStatusAPI creates a new API endpoint for dealing with unit meter status.
    35  func NewMeterStatusAPI(
    36  	st *state.State,
    37  	resources *common.Resources,
    38  	authorizer common.Authorizer,
    39  ) (*MeterStatusAPI, error) {
    40  	if !authorizer.AuthUnitAgent() {
    41  		return nil, common.ErrPerm
    42  	}
    43  	return &MeterStatusAPI{
    44  		state: st,
    45  		accessUnit: func() (common.AuthFunc, error) {
    46  			return authorizer.AuthOwner, nil
    47  		},
    48  		resources: resources,
    49  	}, nil
    50  }
    51  
    52  // WatchMeterStatus returns a NotifyWatcher for observing changes
    53  // to each unit's meter status.
    54  func (m *MeterStatusAPI) WatchMeterStatus(args params.Entities) (params.NotifyWatchResults, error) {
    55  	result := params.NotifyWatchResults{
    56  		Results: make([]params.NotifyWatchResult, len(args.Entities)),
    57  	}
    58  	canAccess, err := m.accessUnit()
    59  	if err != nil {
    60  		return params.NotifyWatchResults{}, err
    61  	}
    62  	for i, entity := range args.Entities {
    63  		tag, err := names.ParseUnitTag(entity.Tag)
    64  		if err != nil {
    65  			result.Results[i].Error = common.ServerError(common.ErrPerm)
    66  			continue
    67  		}
    68  		err = common.ErrPerm
    69  		watcherId := ""
    70  		if canAccess(tag) {
    71  			watcherId, err = m.watchOneUnitMeterStatus(tag)
    72  		}
    73  		result.Results[i].NotifyWatcherId = watcherId
    74  		result.Results[i].Error = common.ServerError(err)
    75  	}
    76  	return result, nil
    77  }
    78  
    79  func (m *MeterStatusAPI) watchOneUnitMeterStatus(tag names.UnitTag) (string, error) {
    80  	unit, err := m.state.Unit(tag.Id())
    81  	if err != nil {
    82  		return "", err
    83  	}
    84  	watch := unit.WatchMeterStatus()
    85  	if _, ok := <-watch.Changes(); ok {
    86  		return m.resources.Register(watch), nil
    87  	}
    88  	return "", watcher.EnsureErr(watch)
    89  }
    90  
    91  // GetMeterStatus returns meter status information for each unit.
    92  func (m *MeterStatusAPI) GetMeterStatus(args params.Entities) (params.MeterStatusResults, error) {
    93  	result := params.MeterStatusResults{
    94  		Results: make([]params.MeterStatusResult, len(args.Entities)),
    95  	}
    96  	canAccess, err := m.accessUnit()
    97  	if err != nil {
    98  		return params.MeterStatusResults{}, common.ErrPerm
    99  	}
   100  	for i, entity := range args.Entities {
   101  		unitTag, err := names.ParseUnitTag(entity.Tag)
   102  		if err != nil {
   103  			result.Results[i].Error = common.ServerError(common.ErrPerm)
   104  			continue
   105  		}
   106  		err = common.ErrPerm
   107  		var status state.MeterStatus
   108  		if canAccess(unitTag) {
   109  			var unit *state.Unit
   110  			unit, err = m.state.Unit(unitTag.Id())
   111  			if err == nil {
   112  				status, err = MeterStatusWrapper(unit.GetMeterStatus)
   113  			}
   114  			result.Results[i].Code = status.Code.String()
   115  			result.Results[i].Info = status.Info
   116  		}
   117  		result.Results[i].Error = common.ServerError(err)
   118  	}
   119  	return result, nil
   120  }