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 }