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: &params.Action{
    59  					Tag: actionTag1.String(),
    60  				},
    61  			}},
    62  			[]params.ActionResult{{
    63  				Action: &params.Action{
    64  					Tag: actionTag2.String(),
    65  				},
    66  			}},
    67  		},
    68  		actionMap: map[string]params.ActionResult{
    69  			actionTag1.Id(): params.ActionResult{
    70  				Action: &params.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: &params.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: &params.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: &params.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: &params.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: &params.Action{
   131  					Tag: actionTag1.String(),
   132  				},
   133  			}},
   134  		},
   135  		actionMap: map[string]params.ActionResult{
   136  			actionTag1.Id(): params.ActionResult{
   137  				Action: &params.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: &params.Action{
   154  					Tag: actionTag1.String(),
   155  				},
   156  			}},
   157  			[]params.ActionResult{{
   158  				Action: &params.Action{
   159  					Tag: actionTag1.String(),
   160  				},
   161  			}, {
   162  				Action: &params.Action{
   163  					Tag: actionTag2.String(),
   164  				},
   165  			}},
   166  		},
   167  		actionMap: map[string]params.ActionResult{
   168  			actionTag1.Id(): params.ActionResult{
   169  				Action: &params.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: &params.Action{
   186  					Tag: actionTag1.String(),
   187  				},
   188  			}},
   189  			[]params.ActionResult{{
   190  				Error: &params.Error{
   191  					Message: "permission denied",
   192  				},
   193  			}},
   194  		},
   195  		actionMap: map[string]params.ActionResult{
   196  			actionTag1.Id(): params.ActionResult{
   197  				Action: &params.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: &params.Action{
   214  					Tag: actionTag1.String(),
   215  				},
   216  			}},
   217  			[]params.ActionResult{{
   218  				Action: &params.Action{
   219  					Tag: actionTag2.String(),
   220  				},
   221  			}},
   222  		},
   223  		actionMap: map[string]params.ActionResult{
   224  			actionTag1.Id(): params.ActionResult{
   225  				Action: &params.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: &params.Action{
   242  					Tag: actionTag1.String(),
   243  				},
   244  			}},
   245  			[]params.ActionResult{{
   246  				Action: &params.Action{
   247  					Tag: actionTag2.String(),
   248  				},
   249  			}},
   250  		},
   251  		actionMap: map[string]params.ActionResult{
   252  			actionTag1.Id(): params.ActionResult{
   253  				Action: &params.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: &params.Action{
   271  					Tag: actionTag1.String(),
   272  				},
   273  			}},
   274  			[]params.ActionResult{{
   275  				Action: &params.Action{
   276  					Tag: actionTag2.String(),
   277  				},
   278  			}},
   279  		},
   280  		actionMap: map[string]params.ActionResult{
   281  			actionTag1.Id(): params.ActionResult{
   282  				Action: &params.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: &params.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  }