github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/metricsdebug/collectmetrics_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 "github.com/juju/errors" 8 "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/charm.v6-unstable" 12 "gopkg.in/juju/names.v2" 13 14 "github.com/juju/juju/api" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/cmd/juju/action" 17 "github.com/juju/juju/cmd/juju/metricsdebug" 18 "github.com/juju/juju/cmd/modelcmd" 19 coretesting "github.com/juju/juju/testing" 20 ) 21 22 type collectMetricsSuite struct { 23 coretesting.FakeJujuXDGDataHomeSuite 24 } 25 26 var _ = gc.Suite(&collectMetricsSuite{}) 27 28 func (s *collectMetricsSuite) TestCollectMetrics(c *gc.C) { 29 runClient := &testRunClient{} 30 serviceClient := &testServiceClient{} 31 serviceClient.charmURL = "local:quantal/charm" 32 s.PatchValue(metricsdebug.NewAPIConn, noConn) 33 s.PatchValue(metricsdebug.NewRunClient, metricsdebug.NewRunClientFnc(runClient)) 34 s.PatchValue(metricsdebug.NewServiceClient, metricsdebug.NewServiceClientFnc(serviceClient)) 35 36 actionTag1 := names.NewActionTag("01234567-89ab-cdef-0123-456789abcdef") 37 actionTag2 := names.NewActionTag("11234567-89ab-cdef-0123-456789abcdef") 38 39 tests := []struct { 40 about string 41 args []string 42 stdout string 43 results [][]params.ActionResult 44 actionMap map[string]params.ActionResult 45 err string 46 }{{ 47 about: "missing args", 48 err: "you need to specify a unit or application.", 49 }, { 50 about: "invalid application name", 51 args: []string{"application_1-0"}, 52 err: `"application_1-0" is not a valid unit or application`, 53 }, { 54 about: "all is well", 55 args: []string{"uptime"}, 56 results: [][]params.ActionResult{ 57 []params.ActionResult{{ 58 Action: ¶ms.Action{ 59 Tag: actionTag1.String(), 60 }, 61 }}, 62 []params.ActionResult{{ 63 Action: ¶ms.Action{ 64 Tag: actionTag2.String(), 65 }, 66 }}, 67 }, 68 actionMap: map[string]params.ActionResult{ 69 actionTag1.Id(): params.ActionResult{ 70 Action: ¶ms.Action{ 71 Tag: actionTag1.String(), 72 Receiver: "unit-uptime-0", 73 }, 74 Output: map[string]interface{}{ 75 "Stdout": "ok", 76 "Stderr": "", 77 }, 78 }, 79 actionTag2.Id(): params.ActionResult{ 80 Action: ¶ms.Action{ 81 Tag: actionTag2.String(), 82 }, 83 Output: map[string]interface{}{ 84 "Stdout": "ok", 85 "Stderr": "", 86 }, 87 }, 88 }, 89 }, { 90 about: "invalid tag returned", 91 args: []string{"uptime"}, 92 results: [][]params.ActionResult{ 93 []params.ActionResult{{ 94 Action: ¶ms.Action{ 95 Tag: "invalid", 96 }, 97 }}, 98 }, 99 stdout: `failed to collect metrics: "invalid" is not a valid tag\n`, 100 }, { 101 about: "no action found", 102 args: []string{"uptime"}, 103 results: [][]params.ActionResult{ 104 []params.ActionResult{{ 105 Action: ¶ms.Action{ 106 Tag: actionTag1.String(), 107 }, 108 }}, 109 }, 110 stdout: "failed to collect metrics: plm\n", 111 }, { 112 about: "fail to parse result", 113 args: []string{"uptime"}, 114 results: [][]params.ActionResult{ 115 []params.ActionResult{{ 116 Action: ¶ms.Action{ 117 Tag: actionTag1.String(), 118 }, 119 }}, 120 }, 121 actionMap: map[string]params.ActionResult{ 122 actionTag1.Id(): params.ActionResult{}, 123 }, 124 stdout: "failed to collect metrics: could not read stdout\n", 125 }, { 126 about: "no results on sendResults", 127 args: []string{"uptime"}, 128 results: [][]params.ActionResult{ 129 []params.ActionResult{{ 130 Action: ¶ms.Action{ 131 Tag: actionTag1.String(), 132 }, 133 }}, 134 }, 135 actionMap: map[string]params.ActionResult{ 136 actionTag1.Id(): params.ActionResult{ 137 Action: ¶ms.Action{ 138 Tag: actionTag2.String(), 139 Receiver: "unit-uptime-0", 140 }, 141 Output: map[string]interface{}{ 142 "Stdout": "ok", 143 "Stderr": "", 144 }, 145 }, 146 }, 147 stdout: "failed to send metrics for unit uptime/0: no results\n", 148 }, { 149 about: "too many sendResults", 150 args: []string{"uptime"}, 151 results: [][]params.ActionResult{ 152 []params.ActionResult{{ 153 Action: ¶ms.Action{ 154 Tag: actionTag1.String(), 155 }, 156 }}, 157 []params.ActionResult{{ 158 Action: ¶ms.Action{ 159 Tag: actionTag1.String(), 160 }, 161 }, { 162 Action: ¶ms.Action{ 163 Tag: actionTag2.String(), 164 }, 165 }}, 166 }, 167 actionMap: map[string]params.ActionResult{ 168 actionTag1.Id(): params.ActionResult{ 169 Action: ¶ms.Action{ 170 Tag: actionTag2.String(), 171 Receiver: "unit-uptime-0", 172 }, 173 Output: map[string]interface{}{ 174 "Stdout": "ok", 175 "Stderr": "", 176 }, 177 }, 178 }, 179 stdout: "failed to send metrics for unit uptime/0\n", 180 }, { 181 about: "sendResults error", 182 args: []string{"uptime"}, 183 results: [][]params.ActionResult{ 184 []params.ActionResult{{ 185 Action: ¶ms.Action{ 186 Tag: actionTag1.String(), 187 }, 188 }}, 189 []params.ActionResult{{ 190 Error: ¶ms.Error{ 191 Message: "permission denied", 192 }, 193 }}, 194 }, 195 actionMap: map[string]params.ActionResult{ 196 actionTag1.Id(): params.ActionResult{ 197 Action: ¶ms.Action{ 198 Tag: actionTag2.String(), 199 Receiver: "unit-uptime-0", 200 }, 201 Output: map[string]interface{}{ 202 "Stdout": "ok", 203 "Stderr": "", 204 }, 205 }, 206 }, 207 stdout: "failed to send metrics for unit uptime/0: permission denied\n", 208 }, { 209 about: "couldn't get sendResults action", 210 args: []string{"uptime"}, 211 results: [][]params.ActionResult{ 212 []params.ActionResult{{ 213 Action: ¶ms.Action{ 214 Tag: actionTag1.String(), 215 }, 216 }}, 217 []params.ActionResult{{ 218 Action: ¶ms.Action{ 219 Tag: actionTag2.String(), 220 }, 221 }}, 222 }, 223 actionMap: map[string]params.ActionResult{ 224 actionTag1.Id(): params.ActionResult{ 225 Action: ¶ms.Action{ 226 Tag: actionTag2.String(), 227 Receiver: "unit-uptime-0", 228 }, 229 Output: map[string]interface{}{ 230 "Stdout": "ok", 231 "Stderr": "", 232 }, 233 }, 234 }, 235 stdout: "failed to send metrics for unit uptime/0: plm\n", 236 }, { 237 about: "couldn't parse sendResults action", 238 args: []string{"uptime"}, 239 results: [][]params.ActionResult{ 240 []params.ActionResult{{ 241 Action: ¶ms.Action{ 242 Tag: actionTag1.String(), 243 }, 244 }}, 245 []params.ActionResult{{ 246 Action: ¶ms.Action{ 247 Tag: actionTag2.String(), 248 }, 249 }}, 250 }, 251 actionMap: map[string]params.ActionResult{ 252 actionTag1.Id(): params.ActionResult{ 253 Action: ¶ms.Action{ 254 Tag: actionTag2.String(), 255 Receiver: "unit-uptime-0", 256 }, 257 Output: map[string]interface{}{ 258 "Stdout": "ok", 259 "Stderr": "", 260 }, 261 }, 262 actionTag2.Id(): params.ActionResult{}, 263 }, 264 stdout: "failed to send metrics for unit uptime/0: could not read stdout\n", 265 }, { 266 about: "sendResults action stderr", 267 args: []string{"uptime"}, 268 results: [][]params.ActionResult{ 269 []params.ActionResult{{ 270 Action: ¶ms.Action{ 271 Tag: actionTag1.String(), 272 }, 273 }}, 274 []params.ActionResult{{ 275 Action: ¶ms.Action{ 276 Tag: actionTag2.String(), 277 }, 278 }}, 279 }, 280 actionMap: map[string]params.ActionResult{ 281 actionTag1.Id(): params.ActionResult{ 282 Action: ¶ms.Action{ 283 Tag: actionTag2.String(), 284 Receiver: "unit-uptime-0", 285 }, 286 Output: map[string]interface{}{ 287 "Stdout": "ok", 288 "Stderr": "", 289 }, 290 }, 291 actionTag2.Id(): params.ActionResult{ 292 Action: ¶ms.Action{ 293 Tag: actionTag2.String(), 294 Receiver: "unit-uptime-0", 295 }, 296 Output: map[string]interface{}{ 297 "Stdout": "garbage", 298 "Stderr": "kek", 299 }, 300 }, 301 }, 302 stdout: "failed to send metrics for unit uptime/0: kek\n", 303 }} 304 305 for i, test := range tests { 306 c.Logf("running test %d: %v", i, test.about) 307 runClient.reset() 308 if test.results != nil { 309 runClient.results = test.results 310 } 311 metricsdebug.PatchGetActionResult(s.PatchValue, test.actionMap) 312 ctx, err := coretesting.RunCommand(c, metricsdebug.NewCollectMetricsCommand(), test.args...) 313 if test.err != "" { 314 c.Assert(err, gc.ErrorMatches, test.err) 315 } else { 316 c.Assert(err, jc.ErrorIsNil) 317 c.Assert(coretesting.Stdout(ctx), gc.Matches, test.stdout) 318 } 319 } 320 } 321 322 func (s *collectMetricsSuite) TestCollectMetricsFailsOnNonLocalCharm(c *gc.C) { 323 runClient := &testRunClient{} 324 serviceClient := &testServiceClient{} 325 serviceClient.charmURL = "cs:quantal/charm" 326 s.PatchValue(metricsdebug.NewAPIConn, noConn) 327 s.PatchValue(metricsdebug.NewRunClient, metricsdebug.NewRunClientFnc(runClient)) 328 s.PatchValue(metricsdebug.NewServiceClient, metricsdebug.NewServiceClientFnc(serviceClient)) 329 _, err := coretesting.RunCommand(c, metricsdebug.NewCollectMetricsCommand(), "foobar") 330 c.Assert(err, gc.ErrorMatches, `"foobar" is not a local charm`) 331 runClient.CheckCallNames(c, "Close") 332 } 333 334 type testRunClient struct { 335 action.APIClient 336 testing.Stub 337 338 results [][]params.ActionResult 339 err string 340 } 341 342 // Run implements the runClient interface. 343 func (t *testRunClient) Run(run params.RunParams) ([]params.ActionResult, error) { 344 t.AddCall("Run", run) 345 if t.err != "" { 346 return nil, errors.New(t.err) 347 } 348 if len(t.results) == 0 { 349 return nil, errors.New("no results") 350 } 351 r := t.results[0] 352 t.results = t.results[1:] 353 return r, nil 354 } 355 356 // Close implements the runClient interface. 357 func (t *testRunClient) Close() error { 358 t.AddCall("Close") 359 return nil 360 } 361 362 func (t *testRunClient) reset() { 363 t.ResetCalls() 364 t.results = nil 365 t.err = "" 366 } 367 368 type testServiceClient struct { 369 testing.Stub 370 charmURL string 371 } 372 373 func (t *testServiceClient) GetCharmURL(service string) (*charm.URL, error) { 374 url := charm.MustParseURL(t.charmURL) 375 return url, t.NextErr() 376 } 377 378 func (t *testServiceClient) Close() error { 379 return t.NextErr() 380 } 381 382 func noConn(_ modelcmd.ModelCommandBase) (api.Connection, error) { 383 return nil, nil 384 }