github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/metricsmanager/metricsmanager.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Package metricsmanager contains the implementation of an api endpoint 5 // for calling metrics functions in state. 6 package metricsmanager 7 8 import ( 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 "github.com/juju/names" 12 13 "github.com/juju/juju/apiserver/common" 14 "github.com/juju/juju/apiserver/metricsender" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/state" 17 ) 18 19 var ( 20 logger = loggo.GetLogger("juju.apiserver.metricsmanager") 21 maxBatchesPerSend = 1000 22 23 sender metricsender.MetricSender = &metricsender.NopSender{} 24 ) 25 26 func init() { 27 common.RegisterStandardFacade("MetricsManager", 0, NewMetricsManagerAPI) 28 } 29 30 // MetricsManager defines the methods on the metricsmanager API end point. 31 type MetricsManager interface { 32 CleanupOldMetrics(arg params.Entities) (params.ErrorResults, error) 33 SendMetrics(args params.Entities) (params.ErrorResults, error) 34 } 35 36 // MetricsManagerAPI implements the metrics manager interface and is the concrete 37 // implementation of the api end point. 38 type MetricsManagerAPI struct { 39 state *state.State 40 41 accessEnviron common.GetAuthFunc 42 } 43 44 var _ MetricsManager = (*MetricsManagerAPI)(nil) 45 46 // NewMetricsManagerAPI creates a new API endpoint for calling metrics manager functions. 47 func NewMetricsManagerAPI( 48 st *state.State, 49 resources *common.Resources, 50 authorizer common.Authorizer, 51 ) (*MetricsManagerAPI, error) { 52 if !(authorizer.AuthMachineAgent() && authorizer.AuthEnvironManager()) { 53 return nil, common.ErrPerm 54 } 55 56 // Allow access only to the current environment. 57 accessEnviron := func() (common.AuthFunc, error) { 58 return func(tag names.Tag) bool { 59 if tag == nil { 60 return false 61 } 62 return tag == st.EnvironTag() 63 }, nil 64 } 65 66 return &MetricsManagerAPI{ 67 state: st, 68 accessEnviron: accessEnviron, 69 }, nil 70 } 71 72 // CleanupOldMetrics removes old metrics from the collection. 73 // TODO (mattyw) Returns result with all the delete metrics 74 // The single arg params is expected to contain and environment uuid. 75 // Even though the call will delete all metrics across environments 76 // it serves to validate that the connection has access to at least one environment. 77 func (api *MetricsManagerAPI) CleanupOldMetrics(args params.Entities) (params.ErrorResults, error) { 78 result := params.ErrorResults{ 79 Results: make([]params.ErrorResult, len(args.Entities)), 80 } 81 if len(args.Entities) == 0 { 82 return result, nil 83 } 84 canAccess, err := api.accessEnviron() 85 if err != nil { 86 return result, err 87 } 88 for i, arg := range args.Entities { 89 tag, err := names.ParseEnvironTag(arg.Tag) 90 if err != nil { 91 result.Results[i].Error = common.ServerError(common.ErrPerm) 92 continue 93 } 94 if !canAccess(tag) { 95 result.Results[i].Error = common.ServerError(common.ErrPerm) 96 continue 97 } 98 err = api.state.CleanupOldMetrics() 99 if err != nil { 100 err = errors.Annotate(err, "failed to cleanup old metrics") 101 result.Results[i].Error = common.ServerError(err) 102 } 103 } 104 return result, nil 105 } 106 107 // SendMetrics will send any unsent metrics onto the metric collection service. 108 func (api *MetricsManagerAPI) SendMetrics(args params.Entities) (params.ErrorResults, error) { 109 result := params.ErrorResults{ 110 Results: make([]params.ErrorResult, len(args.Entities)), 111 } 112 if len(args.Entities) == 0 { 113 return result, nil 114 } 115 canAccess, err := api.accessEnviron() 116 if err != nil { 117 return result, err 118 } 119 for i, arg := range args.Entities { 120 tag, err := names.ParseEnvironTag(arg.Tag) 121 if err != nil { 122 result.Results[i].Error = common.ServerError(common.ErrPerm) 123 continue 124 } 125 if !canAccess(tag) { 126 result.Results[i].Error = common.ServerError(common.ErrPerm) 127 continue 128 } 129 err = metricsender.SendMetrics(api.state, sender, maxBatchesPerSend) 130 if err != nil { 131 err = errors.Annotate(err, "failed to send metrics") 132 result.Results[i].Error = common.ServerError(err) 133 } 134 } 135 return result, nil 136 }