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  }