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