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 }