github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/metricsdebug/client_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package metricsdebug_test
     5  
     6  import (
     7  	"errors"
     8  	"time"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	basetesting "github.com/juju/juju/api/base/testing"
    14  	"github.com/juju/juju/api/metricsdebug"
    15  	"github.com/juju/juju/apiserver/common"
    16  	"github.com/juju/juju/apiserver/params"
    17  	jujutesting "github.com/juju/juju/juju/testing"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/testing"
    20  	"github.com/juju/juju/testing/factory"
    21  )
    22  
    23  type metricsdebugSuiteMock struct {
    24  	testing.BaseSuite
    25  	manager *metricsdebug.Client
    26  }
    27  
    28  var _ = gc.Suite(&metricsdebugSuiteMock{})
    29  
    30  func (s *metricsdebugSuiteMock) TestGetMetrics(c *gc.C) {
    31  	var called bool
    32  	now := time.Now()
    33  	apiCaller := basetesting.APICallerFunc(
    34  		func(objType string,
    35  			version int,
    36  			id, request string,
    37  			a, response interface{},
    38  		) error {
    39  			c.Assert(request, gc.Equals, "GetMetrics")
    40  			result := response.(*params.MetricResults)
    41  			result.Results = []params.EntityMetrics{{
    42  				Metrics: []params.MetricResult{{
    43  					Key:   "pings",
    44  					Value: "5",
    45  					Time:  now,
    46  				}},
    47  				Error: nil,
    48  			}}
    49  			called = true
    50  			return nil
    51  		})
    52  	client := metricsdebug.NewClient(apiCaller)
    53  	metrics, err := client.GetMetrics("unit-wordpress/0")
    54  	c.Assert(err, jc.ErrorIsNil)
    55  	c.Assert(called, jc.IsTrue)
    56  	c.Assert(metrics, gc.HasLen, 1)
    57  	c.Assert(metrics[0].Key, gc.Equals, "pings")
    58  	c.Assert(metrics[0].Value, gc.Equals, "5")
    59  	c.Assert(metrics[0].Time, gc.Equals, now)
    60  }
    61  
    62  func (s *metricsdebugSuiteMock) TestGetMetricsFails(c *gc.C) {
    63  	var called bool
    64  	apiCaller := basetesting.APICallerFunc(
    65  		func(objType string,
    66  			version int,
    67  			id, request string,
    68  			a, response interface{},
    69  		) error {
    70  			c.Assert(request, gc.Equals, "GetMetrics")
    71  			result := response.(*params.MetricResults)
    72  			result.Results = []params.EntityMetrics{{
    73  				Error: common.ServerError(errors.New("an error")),
    74  			}}
    75  			called = true
    76  			return nil
    77  		})
    78  	client := metricsdebug.NewClient(apiCaller)
    79  	metrics, err := client.GetMetrics("unit-wordpress/0")
    80  	c.Assert(err, gc.ErrorMatches, "an error")
    81  	c.Assert(metrics, gc.IsNil)
    82  	c.Assert(called, jc.IsTrue)
    83  }
    84  
    85  func (s *metricsdebugSuiteMock) TestGetMetricsFacadeCallError(c *gc.C) {
    86  	var called bool
    87  	apiCaller := basetesting.APICallerFunc(
    88  		func(objType string,
    89  			version int,
    90  			id, request string,
    91  			a, result interface{},
    92  		) error {
    93  			called = true
    94  			return errors.New("an error")
    95  		})
    96  	client := metricsdebug.NewClient(apiCaller)
    97  	metrics, err := client.GetMetrics("unit-wordpress/0")
    98  	c.Assert(err, gc.ErrorMatches, "an error")
    99  	c.Assert(metrics, gc.IsNil)
   100  	c.Assert(called, jc.IsTrue)
   101  }
   102  
   103  func (s *metricsdebugSuiteMock) TestGetMetricsForModel(c *gc.C) {
   104  	var called bool
   105  	now := time.Now()
   106  	apiCaller := basetesting.APICallerFunc(
   107  		func(objType string,
   108  			version int,
   109  			id, request string,
   110  			requestParam, response interface{},
   111  		) error {
   112  			c.Assert(request, gc.Equals, "GetMetrics")
   113  			entities := requestParam.(params.Entities)
   114  			c.Assert(entities, gc.DeepEquals, params.Entities{Entities: []params.Entity{}})
   115  			result := response.(*params.MetricResults)
   116  			result.Results = []params.EntityMetrics{{
   117  				Metrics: []params.MetricResult{{
   118  					Key:   "pings",
   119  					Value: "5",
   120  					Time:  now,
   121  				}},
   122  				Error: nil,
   123  			}}
   124  			called = true
   125  			return nil
   126  		})
   127  	client := metricsdebug.NewClient(apiCaller)
   128  	metrics, err := client.GetMetrics()
   129  	c.Assert(err, jc.ErrorIsNil)
   130  	c.Assert(called, jc.IsTrue)
   131  	c.Assert(metrics, gc.HasLen, 1)
   132  	c.Assert(metrics[0].Key, gc.Equals, "pings")
   133  	c.Assert(metrics[0].Value, gc.Equals, "5")
   134  	c.Assert(metrics[0].Time, gc.Equals, now)
   135  }
   136  
   137  func (s *metricsdebugSuiteMock) TestGetMetricsForModelFails(c *gc.C) {
   138  	var called bool
   139  	apiCaller := basetesting.APICallerFunc(
   140  		func(objType string,
   141  			version int,
   142  			id, request string,
   143  			requestParam, response interface{},
   144  		) error {
   145  			called = true
   146  			return errors.New("an error")
   147  		})
   148  	client := metricsdebug.NewClient(apiCaller)
   149  	metrics, err := client.GetMetrics()
   150  	c.Assert(called, jc.IsTrue)
   151  	c.Assert(metrics, gc.IsNil)
   152  	c.Assert(err, gc.ErrorMatches, "an error")
   153  }
   154  
   155  func (s *metricsdebugSuiteMock) TestSetMeterStatus(c *gc.C) {
   156  	var called bool
   157  	apiCaller := basetesting.APICallerFunc(
   158  		func(objType string,
   159  			version int,
   160  			id, request string,
   161  			a, response interface{},
   162  		) error {
   163  			c.Assert(request, gc.Equals, "SetMeterStatus")
   164  			c.Assert(a, gc.DeepEquals, params.MeterStatusParams{
   165  				Statuses: []params.MeterStatusParam{{
   166  					Tag:  "unit-metered/0",
   167  					Code: "RED",
   168  					Info: "test"},
   169  				},
   170  			})
   171  			result := response.(*params.ErrorResults)
   172  			result.Results = []params.ErrorResult{{
   173  				Error: nil,
   174  			}}
   175  			called = true
   176  			return nil
   177  		})
   178  	client := metricsdebug.NewClient(apiCaller)
   179  	err := client.SetMeterStatus("unit-metered/0", "RED", "test")
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	c.Assert(called, jc.IsTrue)
   182  }
   183  
   184  func (s *metricsdebugSuiteMock) TestSetMeterStatusAPIServerError(c *gc.C) {
   185  	var called bool
   186  	apiCaller := basetesting.APICallerFunc(
   187  		func(objType string,
   188  			version int,
   189  			id, request string,
   190  			a, response interface{},
   191  		) error {
   192  			c.Assert(request, gc.Equals, "SetMeterStatus")
   193  			c.Assert(a, gc.DeepEquals, params.MeterStatusParams{
   194  				Statuses: []params.MeterStatusParam{{
   195  					Tag:  "unit-metered/0",
   196  					Code: "RED",
   197  					Info: "test"},
   198  				},
   199  			})
   200  			result := response.(*params.ErrorResults)
   201  			result.Results = []params.ErrorResult{{
   202  				Error: common.ServerError(errors.New("an error")),
   203  			}}
   204  			called = true
   205  			return nil
   206  		})
   207  	client := metricsdebug.NewClient(apiCaller)
   208  	err := client.SetMeterStatus("unit-metered/0", "RED", "test")
   209  	c.Assert(err, gc.ErrorMatches, "an error")
   210  	c.Assert(called, jc.IsTrue)
   211  }
   212  
   213  func (s *metricsdebugSuiteMock) TestSetMeterStatusFacadeCallError(c *gc.C) {
   214  	var called bool
   215  	apiCaller := basetesting.APICallerFunc(
   216  		func(objType string,
   217  			version int,
   218  			id, request string,
   219  			a, response interface{},
   220  		) error {
   221  			called = true
   222  			return errors.New("an error")
   223  		})
   224  	client := metricsdebug.NewClient(apiCaller)
   225  	err := client.SetMeterStatus("unit-metered/0", "RED", "test")
   226  	c.Assert(err, gc.ErrorMatches, "an error")
   227  	c.Assert(called, jc.IsTrue)
   228  }
   229  
   230  type metricsdebugSuite struct {
   231  	jujutesting.JujuConnSuite
   232  	manager *metricsdebug.Client
   233  }
   234  
   235  var _ = gc.Suite(&metricsdebugSuite{})
   236  
   237  func (s *metricsdebugSuite) SetUpTest(c *gc.C) {
   238  	s.JujuConnSuite.SetUpTest(c)
   239  	s.manager = metricsdebug.NewClient(s.APIState)
   240  	c.Assert(s.manager, gc.NotNil)
   241  }
   242  
   243  func assertSameMetric(c *gc.C, a params.MetricResult, b *state.MetricBatch) {
   244  	c.Assert(a.Key, gc.Equals, b.Metrics()[0].Key)
   245  	c.Assert(a.Value, gc.Equals, b.Metrics()[0].Value)
   246  	c.Assert(a.Time, jc.TimeBetween(b.Metrics()[0].Time, b.Metrics()[0].Time))
   247  }
   248  
   249  func (s *metricsdebugSuite) TestFeatureGetMetrics(c *gc.C) {
   250  	meteredCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "local:quantal/metered"})
   251  	meteredService := s.Factory.MakeApplication(c, &factory.ApplicationParams{Charm: meteredCharm})
   252  	unit := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   253  	metric := s.Factory.MakeMetric(c, &factory.MetricParams{Unit: unit})
   254  	metrics, err := s.manager.GetMetrics("unit-metered/0")
   255  	c.Assert(err, jc.ErrorIsNil)
   256  	c.Assert(metrics, gc.HasLen, 1)
   257  	assertSameMetric(c, metrics[0], metric)
   258  }
   259  
   260  func (s *metricsdebugSuite) TestFeatureGetMultipleMetrics(c *gc.C) {
   261  	meteredCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "local:quantal/metered"})
   262  	meteredService := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   263  		Charm: meteredCharm,
   264  	})
   265  	unit0 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   266  	unit1 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   267  
   268  	metricUnit0 := s.Factory.MakeMetric(c, &factory.MetricParams{
   269  		Unit: unit0,
   270  	})
   271  	metricUnit1 := s.Factory.MakeMetric(c, &factory.MetricParams{
   272  		Unit: unit1,
   273  	})
   274  
   275  	metrics0, err := s.manager.GetMetrics("unit-metered/0")
   276  	c.Assert(err, jc.ErrorIsNil)
   277  	c.Assert(metrics0, gc.HasLen, 1)
   278  	assertSameMetric(c, metrics0[0], metricUnit0)
   279  
   280  	metrics1, err := s.manager.GetMetrics("unit-metered/1")
   281  	c.Assert(err, jc.ErrorIsNil)
   282  	c.Assert(metrics1, gc.HasLen, 1)
   283  	assertSameMetric(c, metrics1[0], metricUnit1)
   284  
   285  	metrics2, err := s.manager.GetMetrics("unit-metered/0", "unit-metered/1")
   286  	c.Assert(err, jc.ErrorIsNil)
   287  	c.Assert(metrics2, gc.HasLen, 2)
   288  }
   289  
   290  func (s *metricsdebugSuite) TestFeatureGetMetricsForModel(c *gc.C) {
   291  	meteredCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "local:quantal/metered"})
   292  	meteredService := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   293  		Charm: meteredCharm,
   294  	})
   295  	unit0 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   296  	unit1 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   297  
   298  	metricUnit0 := s.Factory.MakeMetric(c, &factory.MetricParams{
   299  		Unit: unit0,
   300  	})
   301  	metricUnit1 := s.Factory.MakeMetric(c, &factory.MetricParams{
   302  		Unit: unit1,
   303  	})
   304  
   305  	metrics, err := s.manager.GetMetrics()
   306  	c.Assert(err, jc.ErrorIsNil)
   307  	c.Assert(metrics, gc.HasLen, 2)
   308  	assertSameMetric(c, metrics[0], metricUnit0)
   309  	assertSameMetric(c, metrics[1], metricUnit1)
   310  }
   311  
   312  func (s *metricsdebugSuite) TestFeatureGetMultipleMetricsWithService(c *gc.C) {
   313  	meteredCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "local:quantal/metered"})
   314  	meteredService := s.Factory.MakeApplication(c, &factory.ApplicationParams{
   315  		Charm: meteredCharm,
   316  	})
   317  	unit0 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   318  	unit1 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: meteredService, SetCharmURL: true})
   319  
   320  	metricUnit0 := s.Factory.MakeMetric(c, &factory.MetricParams{
   321  		Unit: unit0,
   322  	})
   323  	metricUnit1 := s.Factory.MakeMetric(c, &factory.MetricParams{
   324  		Unit: unit1,
   325  	})
   326  
   327  	metrics, err := s.manager.GetMetrics("application-metered")
   328  	c.Assert(err, jc.ErrorIsNil)
   329  	c.Assert(metrics, gc.HasLen, 2)
   330  	assertSameMetric(c, metrics[0], metricUnit0)
   331  	assertSameMetric(c, metrics[1], metricUnit1)
   332  }
   333  
   334  func (s *metricsdebugSuite) TestSetMeterStatus(c *gc.C) {
   335  	testCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "local:quantal/metered"})
   336  	testService := s.Factory.MakeApplication(c, &factory.ApplicationParams{Charm: testCharm})
   337  	testUnit1 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: testService, SetCharmURL: true})
   338  	testUnit2 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: testService, SetCharmURL: true})
   339  
   340  	csCharm := s.Factory.MakeCharm(c, &factory.CharmParams{Name: "metered", URL: "cs:quantal/metered"})
   341  	csService := s.Factory.MakeApplication(c, &factory.ApplicationParams{Name: "cs-service", Charm: csCharm})
   342  	csUnit1 := s.Factory.MakeUnit(c, &factory.UnitParams{Application: csService, SetCharmURL: true})
   343  
   344  	tests := []struct {
   345  		about  string
   346  		tag    string
   347  		code   string
   348  		info   string
   349  		err    string
   350  		assert func(*gc.C)
   351  	}{{
   352  		about: "set service meter status",
   353  		tag:   testService.Tag().String(),
   354  		code:  "RED",
   355  		info:  "test",
   356  		assert: func(c *gc.C) {
   357  			ms1, err := testUnit1.GetMeterStatus()
   358  			c.Assert(err, jc.ErrorIsNil)
   359  			c.Assert(ms1, gc.DeepEquals, state.MeterStatus{
   360  				Code: state.MeterRed,
   361  				Info: "test",
   362  			})
   363  			ms2, err := testUnit2.GetMeterStatus()
   364  			c.Assert(err, jc.ErrorIsNil)
   365  			c.Assert(ms2, gc.DeepEquals, state.MeterStatus{
   366  				Code: state.MeterRed,
   367  				Info: "test",
   368  			})
   369  		},
   370  	}, {
   371  		about: "set unit meter status",
   372  		tag:   testUnit1.Tag().String(),
   373  		code:  "AMBER",
   374  		info:  "test",
   375  		assert: func(c *gc.C) {
   376  			ms1, err := testUnit1.GetMeterStatus()
   377  			c.Assert(err, jc.ErrorIsNil)
   378  			c.Assert(ms1, gc.DeepEquals, state.MeterStatus{
   379  				Code: state.MeterAmber,
   380  				Info: "test",
   381  			})
   382  		},
   383  	}, {
   384  		about: "not a local charm - service",
   385  		tag:   csService.Tag().String(),
   386  		code:  "AMBER",
   387  		info:  "test",
   388  		err:   "not a local charm",
   389  	}, {
   390  		about: "not a local charm - unit",
   391  		tag:   csUnit1.Tag().String(),
   392  		code:  "AMBER",
   393  		info:  "test",
   394  		err:   "not a local charm",
   395  	}, {
   396  		about: "invalid meter status",
   397  		tag:   testUnit1.Tag().String(),
   398  		code:  "WRONG",
   399  		info:  "test",
   400  		err:   "invalid meter status \"NOT AVAILABLE\"",
   401  	}, {
   402  		about: "not such service",
   403  		tag:   "application-missing",
   404  		code:  "AMBER",
   405  		info:  "test",
   406  		err:   "application \"missing\" not found",
   407  	},
   408  	}
   409  
   410  	for i, test := range tests {
   411  		c.Logf("running test %d: %v", i, test.about)
   412  		err := s.manager.SetMeterStatus(test.tag, test.code, test.info)
   413  		if test.err == "" {
   414  			c.Assert(err, jc.ErrorIsNil)
   415  			test.assert(c)
   416  		} else {
   417  			c.Assert(err, gc.ErrorMatches, test.err)
   418  		}
   419  	}
   420  }