github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/metricsmanager/metricsmanager_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package metricsmanager_test
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/clock/testclock"
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/names.v2"
    15  
    16  	"github.com/juju/juju/apiserver/common"
    17  	"github.com/juju/juju/apiserver/facades/agent/metricsender/testing"
    18  	"github.com/juju/juju/apiserver/facades/controller/metricsmanager"
    19  	"github.com/juju/juju/apiserver/params"
    20  	apiservertesting "github.com/juju/juju/apiserver/testing"
    21  	jujujutesting "github.com/juju/juju/juju/testing"
    22  	"github.com/juju/juju/state"
    23  	"github.com/juju/juju/testing/factory"
    24  )
    25  
    26  type metricsManagerSuite struct {
    27  	jujujutesting.JujuConnSuite
    28  
    29  	clock          *testclock.Clock
    30  	metricsmanager *metricsmanager.MetricsManagerAPI
    31  	authorizer     apiservertesting.FakeAuthorizer
    32  	unit           *state.Unit
    33  }
    34  
    35  var _ = gc.Suite(&metricsManagerSuite{})
    36  
    37  func (s *metricsManagerSuite) SetUpTest(c *gc.C) {
    38  	s.JujuConnSuite.SetUpTest(c)
    39  	s.authorizer = apiservertesting.FakeAuthorizer{
    40  		Tag:        names.NewMachineTag("0"),
    41  		Controller: true,
    42  	}
    43  	s.clock = testclock.NewClock(time.Now())
    44  	manager, err := metricsmanager.NewMetricsManagerAPI(s.State, nil, s.authorizer, s.StatePool, s.clock)
    45  	c.Assert(err, jc.ErrorIsNil)
    46  	s.metricsmanager = manager
    47  	meteredCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "cs:quantal/metered"})
    48  	meteredApplication := s.Factory.MakeApplication(c, &factory.ApplicationParams{Charm: meteredCharm})
    49  	s.unit = s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredApplication, SetCharmURL: true})
    50  }
    51  
    52  func (s *metricsManagerSuite) TestNewMetricsManagerAPIRefusesNonController(c *gc.C) {
    53  	tests := []struct {
    54  		tag           names.Tag
    55  		controller    bool
    56  		expectedError string
    57  	}{
    58  		{names.NewUnitTag("mysql/0"), false, "permission denied"},
    59  		{names.NewLocalUserTag("admin"), false, "permission denied"},
    60  		{names.NewMachineTag("0"), false, "permission denied"},
    61  		{names.NewMachineTag("0"), true, ""},
    62  	}
    63  	for i, test := range tests {
    64  		c.Logf("test %d", i)
    65  
    66  		anAuthoriser := s.authorizer
    67  		anAuthoriser.Controller = test.controller
    68  		anAuthoriser.Tag = test.tag
    69  		endPoint, err := metricsmanager.NewMetricsManagerAPI(s.State, nil,
    70  			anAuthoriser, s.StatePool, testclock.NewClock(time.Now()))
    71  		if test.expectedError == "" {
    72  			c.Assert(err, jc.ErrorIsNil)
    73  			c.Assert(endPoint, gc.NotNil)
    74  		} else {
    75  			c.Assert(err, gc.ErrorMatches, test.expectedError)
    76  			c.Assert(endPoint, gc.IsNil)
    77  		}
    78  	}
    79  }
    80  
    81  func (s *metricsManagerSuite) TestCleanupOldMetrics(c *gc.C) {
    82  	oldTime := time.Now().Add(-(time.Hour * 25))
    83  	newTime := time.Now()
    84  	metric := state.Metric{Key: "pings", Value: "5", Time: newTime}
    85  	oldMetric := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: true, DeleteTime: &oldTime, Metrics: []state.Metric{metric}})
    86  	newMetric := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: true, DeleteTime: &newTime, Metrics: []state.Metric{metric}})
    87  	args := params.Entities{Entities: []params.Entity{
    88  		{s.Model.ModelTag().String()},
    89  	}}
    90  	result, err := s.metricsmanager.CleanupOldMetrics(args)
    91  	c.Assert(err, jc.ErrorIsNil)
    92  	c.Assert(result.Results, gc.HasLen, 1)
    93  	c.Assert(result.Results[0], gc.DeepEquals, params.ErrorResult{Error: nil})
    94  	_, err = s.State.MetricBatch(oldMetric.UUID())
    95  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
    96  	_, err = s.State.MetricBatch(newMetric.UUID())
    97  	c.Assert(err, jc.ErrorIsNil)
    98  }
    99  
   100  func (s *metricsManagerSuite) TestCleanupOldMetricsInvalidArg(c *gc.C) {
   101  	args := params.Entities{Entities: []params.Entity{
   102  		{"invalid"},
   103  	}}
   104  	result, err := s.metricsmanager.CleanupOldMetrics(args)
   105  	c.Assert(result.Results, gc.HasLen, 1)
   106  	c.Assert(err, jc.ErrorIsNil)
   107  	expectedError := common.ServerError(common.ErrPerm)
   108  	c.Assert(result.Results[0], gc.DeepEquals, params.ErrorResult{Error: expectedError})
   109  }
   110  
   111  func (s *metricsManagerSuite) TestCleanupArgsIndependent(c *gc.C) {
   112  	args := params.Entities{Entities: []params.Entity{
   113  		{"invalid"},
   114  		{s.Model.ModelTag().String()},
   115  	}}
   116  	result, err := s.metricsmanager.CleanupOldMetrics(args)
   117  	c.Assert(result.Results, gc.HasLen, 2)
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	expectedError := common.ServerError(common.ErrPerm)
   120  	c.Assert(result.Results[0], gc.DeepEquals, params.ErrorResult{Error: expectedError})
   121  	c.Assert(result.Results[1], gc.DeepEquals, params.ErrorResult{Error: nil})
   122  }
   123  
   124  func (s *metricsManagerSuite) TestSendMetrics(c *gc.C) {
   125  	var sender testing.MockSender
   126  	cleanup := s.metricsmanager.PatchSender(&sender)
   127  	defer cleanup()
   128  	now := time.Now()
   129  	metric := state.Metric{Key: "pings", Value: "5", Time: now}
   130  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: true, Time: &now, Metrics: []state.Metric{metric}})
   131  	unsent := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: false, Time: &now, Metrics: []state.Metric{metric}})
   132  	args := params.Entities{Entities: []params.Entity{
   133  		{s.Model.ModelTag().String()},
   134  	}}
   135  	result, err := s.metricsmanager.SendMetrics(args)
   136  	c.Assert(err, jc.ErrorIsNil)
   137  	c.Assert(result.Results, gc.HasLen, 1)
   138  	c.Assert(result.Results[0], gc.DeepEquals, params.ErrorResult{Error: nil})
   139  	c.Assert(sender.Data, gc.HasLen, 1)
   140  	m, err := s.State.MetricBatch(unsent.UUID())
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	c.Assert(m.Sent(), jc.IsTrue)
   143  }
   144  
   145  func (s *metricsManagerSuite) TestSendOldMetricsInvalidArg(c *gc.C) {
   146  	args := params.Entities{Entities: []params.Entity{
   147  		{"invalid"},
   148  	}}
   149  	result, err := s.metricsmanager.SendMetrics(args)
   150  	c.Assert(result.Results, gc.HasLen, 1)
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	expectedError := `"invalid" is not a valid tag`
   153  	c.Assert(result.Results[0].Error, gc.ErrorMatches, expectedError)
   154  }
   155  
   156  func (s *metricsManagerSuite) TestSendArgsIndependent(c *gc.C) {
   157  	args := params.Entities{Entities: []params.Entity{
   158  		{"invalid"},
   159  		{s.Model.ModelTag().String()},
   160  	}}
   161  	result, err := s.metricsmanager.SendMetrics(args)
   162  	c.Assert(result.Results, gc.HasLen, 2)
   163  	c.Assert(err, jc.ErrorIsNil)
   164  	expectedError := `"invalid" is not a valid tag`
   165  	c.Assert(result.Results[0].Error, gc.ErrorMatches, expectedError)
   166  	c.Assert(result.Results[1].Error, gc.IsNil)
   167  }
   168  
   169  func (s *metricsManagerSuite) TestMeterStatusOnConsecutiveErrors(c *gc.C) {
   170  	var sender testing.ErrorSender
   171  	sender.Err = errors.New("an error")
   172  	now := time.Now()
   173  	metric := state.Metric{Key: "pings", Value: "5", Time: now}
   174  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: false, Time: &now, Metrics: []state.Metric{metric}})
   175  	cleanup := s.metricsmanager.PatchSender(&sender)
   176  	defer cleanup()
   177  	args := params.Entities{Entities: []params.Entity{
   178  		{s.Model.ModelTag().String()},
   179  	}}
   180  	result, err := s.metricsmanager.SendMetrics(args)
   181  	c.Assert(err, jc.ErrorIsNil)
   182  	expectedError := params.ErrorResult{Error: apiservertesting.PrefixedError(
   183  		fmt.Sprintf("failed to send metrics for %s: ", s.Model.ModelTag()),
   184  		"an error")}
   185  	c.Assert(result.Results[0], jc.DeepEquals, expectedError)
   186  	mm, err := s.State.MetricsManager()
   187  	c.Assert(err, jc.ErrorIsNil)
   188  	c.Assert(mm.ConsecutiveErrors(), gc.Equals, 1)
   189  }
   190  
   191  func (s *metricsManagerSuite) TestMeterStatusSuccessfulSend(c *gc.C) {
   192  	var sender testing.MockSender
   193  	pastTime := s.clock.Now().Add(-time.Second)
   194  	metric := state.Metric{Key: "pings", Value: "5", Time: pastTime}
   195  	s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: false, Time: &pastTime, Metrics: []state.Metric{metric}})
   196  	cleanup := s.metricsmanager.PatchSender(&sender)
   197  	defer cleanup()
   198  	args := params.Entities{Entities: []params.Entity{
   199  		{s.Model.ModelTag().String()},
   200  	}}
   201  	result, err := s.metricsmanager.SendMetrics(args)
   202  	c.Assert(err, jc.ErrorIsNil)
   203  	c.Assert(result.Results[0].Error, gc.IsNil)
   204  	mm, err := s.State.MetricsManager()
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	c.Assert(mm.LastSuccessfulSend().After(pastTime), jc.IsTrue)
   207  }
   208  
   209  func (s *metricsManagerSuite) TestLastSuccessfulNotChangedIfNothingToSend(c *gc.C) {
   210  	var sender testing.MockSender
   211  	cleanup := s.metricsmanager.PatchSender(&sender)
   212  	defer cleanup()
   213  	args := params.Entities{Entities: []params.Entity{
   214  		{s.Model.ModelTag().String()},
   215  	}}
   216  	result, err := s.metricsmanager.SendMetrics(args)
   217  	c.Assert(err, jc.ErrorIsNil)
   218  	c.Assert(result.Results[0].Error, gc.IsNil)
   219  	mm, err := s.State.MetricsManager()
   220  	c.Assert(err, jc.ErrorIsNil)
   221  	c.Assert(mm.LastSuccessfulSend().Equal(time.Time{}), jc.IsTrue)
   222  }
   223  
   224  func (s *metricsManagerSuite) TestAddJujuMachineMetrics(c *gc.C) {
   225  	err := s.State.SetSLA("essential", "bob", []byte("sla"))
   226  	c.Assert(err, jc.ErrorIsNil)
   227  	// Create two additional ubuntu machines, in addition to the one created in setup.
   228  	s.Factory.MakeMachine(c, &factory.MachineParams{Series: "trusty"})
   229  	s.Factory.MakeMachine(c, &factory.MachineParams{Series: "xenial"})
   230  	s.Factory.MakeMachine(c, &factory.MachineParams{Series: "win7"})
   231  	s.Factory.MakeMachine(c, &factory.MachineParams{Series: "win8"})
   232  	s.Factory.MakeMachine(c, &factory.MachineParams{Series: "centos7"})
   233  	s.Factory.MakeMachine(c, &factory.MachineParams{Series: "redox"})
   234  	err = s.metricsmanager.AddJujuMachineMetrics()
   235  	c.Assert(err, jc.ErrorIsNil)
   236  	metrics, err := s.State.MetricsToSend(10)
   237  	c.Assert(err, jc.ErrorIsNil)
   238  	c.Assert(metrics, gc.HasLen, 1)
   239  	c.Assert(metrics[0].Metrics(), gc.HasLen, 5)
   240  	c.Assert(metrics[0].SLACredentials(), gc.DeepEquals, []byte("sla"))
   241  	t := metrics[0].Metrics()[0].Time
   242  	c.Assert(metrics[0].UniqueMetrics(), jc.DeepEquals, []state.Metric{{
   243  		Key:   "juju-centos-machines",
   244  		Value: "1",
   245  		Time:  t,
   246  	}, {
   247  		Key:   "juju-machines",
   248  		Value: "7",
   249  		Time:  t,
   250  	}, {
   251  		Key:   "juju-ubuntu-machines",
   252  		Value: "3",
   253  		Time:  t,
   254  	}, {
   255  		Key:   "juju-unknown-machines",
   256  		Value: "1",
   257  		Time:  t,
   258  	}, {
   259  		Key:   "juju-windows-machines",
   260  		Value: "2",
   261  		Time:  t,
   262  	}})
   263  }
   264  
   265  func (s *metricsManagerSuite) TestAddJujuMachineMetricsAddsNoMetricsWhenNoSLASet(c *gc.C) {
   266  	s.Factory.MakeMachine(c, nil)
   267  	err := s.metricsmanager.AddJujuMachineMetrics()
   268  	c.Assert(err, jc.ErrorIsNil)
   269  	metrics, err := s.State.MetricsToSend(10)
   270  	c.Assert(err, jc.ErrorIsNil)
   271  	c.Assert(metrics, gc.HasLen, 0)
   272  }
   273  
   274  func (s *metricsManagerSuite) TestAddJujuMachineMetricsDontCountContainers(c *gc.C) {
   275  	err := s.State.SetSLA("essential", "bob", []byte("sla"))
   276  	c.Assert(err, jc.ErrorIsNil)
   277  	machine := s.Factory.MakeMachine(c, nil)
   278  	s.Factory.MakeMachineNested(c, machine.Id(), nil)
   279  	err = s.metricsmanager.AddJujuMachineMetrics()
   280  	c.Assert(err, jc.ErrorIsNil)
   281  	metrics, err := s.State.MetricsToSend(10)
   282  	c.Assert(err, jc.ErrorIsNil)
   283  	c.Assert(metrics, gc.HasLen, 1)
   284  	c.Assert(metrics[0].Metrics()[0].Key, gc.Equals, "juju-machines")
   285  	// Even though we add two machines - one nested (i.e. container) we only
   286  	// count non-container machine.
   287  	c.Assert(metrics[0].Metrics()[0].Value, gc.Equals, "2")
   288  	c.Assert(metrics[0].SLACredentials(), gc.DeepEquals, []byte("sla"))
   289  }
   290  
   291  func (s *metricsManagerSuite) TestSendMetricsMachineMetrics(c *gc.C) {
   292  	err := s.State.SetSLA("essential", "bob", []byte("sla"))
   293  	c.Assert(err, jc.ErrorIsNil)
   294  	s.Factory.MakeMachine(c, nil)
   295  	var sender testing.MockSender
   296  	cleanup := s.metricsmanager.PatchSender(&sender)
   297  	defer cleanup()
   298  	args := params.Entities{Entities: []params.Entity{
   299  		{s.Model.ModelTag().String()},
   300  	}}
   301  	result, err := s.metricsmanager.SendMetrics(args)
   302  	c.Assert(err, jc.ErrorIsNil)
   303  	c.Assert(result.Results, gc.HasLen, 1)
   304  	c.Assert(result.Results[0], gc.DeepEquals, params.ErrorResult{Error: nil})
   305  	c.Assert(sender.Data, gc.HasLen, 1)
   306  	c.Assert(sender.Data[0], gc.HasLen, 1)
   307  	c.Assert(sender.Data[0][0].Metrics[0].Key, gc.Equals, "juju-machines")
   308  	c.Assert(sender.Data[0][0].SLACredentials, gc.DeepEquals, []byte("sla"))
   309  	ms, err := s.State.AllMetricBatches()
   310  	c.Assert(err, jc.ErrorIsNil)
   311  	c.Assert(ms, gc.HasLen, 1)
   312  	c.Assert(ms[0].Sent(), jc.IsTrue)
   313  }