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 }