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