github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/budget/budget_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package budget_test
     5  
     6  import (
     7  	"github.com/juju/cmd"
     8  	"github.com/juju/cmd/cmdtesting"
     9  	"github.com/juju/errors"
    10  	"github.com/juju/persistent-cookiejar"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	rcmd "github.com/juju/juju/cmd/juju/romulus"
    17  	"github.com/juju/juju/cmd/juju/romulus/budget"
    18  	"github.com/juju/juju/cmd/modelcmd"
    19  	"github.com/juju/juju/core/model"
    20  	"github.com/juju/juju/jujuclient"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  var _ = gc.Suite(&budgetSuite{})
    25  
    26  type budgetSuite struct {
    27  	coretesting.FakeJujuXDGDataHomeSuite
    28  	stub    *testing.Stub
    29  	mockAPI *mockapi
    30  	store   jujuclient.ClientStore
    31  }
    32  
    33  func (s *budgetSuite) SetUpTest(c *gc.C) {
    34  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    35  	s.store = &jujuclient.MemStore{
    36  		CurrentControllerName: "controller",
    37  		Controllers: map[string]jujuclient.ControllerDetails{
    38  			"controller":        {},
    39  			"anothercontroller": {},
    40  		},
    41  		Models: map[string]*jujuclient.ControllerModels{
    42  			"controller": {
    43  				Models: map[string]jujuclient.ModelDetails{
    44  					"admin/model": {ModelUUID: "model-uuid", ModelType: model.IAAS},
    45  				},
    46  				CurrentModel: "admin/model",
    47  			},
    48  			"anothercontroller": {
    49  				Models: map[string]jujuclient.ModelDetails{
    50  					"admin/somemodel": {ModelUUID: "another-model-uuid", ModelType: model.IAAS},
    51  				},
    52  				CurrentModel: "admin/somemodel",
    53  			},
    54  		},
    55  		Accounts: map[string]jujuclient.AccountDetails{
    56  			"controller": {
    57  				User: "admin",
    58  			},
    59  			"anothercontroller": {
    60  				User: "admin",
    61  			},
    62  		},
    63  		CookieJars: make(map[string]*cookiejar.Jar),
    64  	}
    65  	s.stub = &testing.Stub{}
    66  	s.mockAPI = newMockAPI(s.stub)
    67  	s.PatchValue(&rcmd.GetMeteringURLForModelCmd, func(c *modelcmd.ModelCommandBase) (string, error) {
    68  		return "http://example.com", nil
    69  	})
    70  }
    71  
    72  func (s *budgetSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
    73  	updateBudget := budget.NewBudgetCommandForTest(s.mockAPI, s.store)
    74  	return cmdtesting.RunCommand(c, updateBudget, args...)
    75  }
    76  
    77  func (s *budgetSuite) TestUpdateBudget(c *gc.C) {
    78  	s.mockAPI.resp = "budget set to 5"
    79  	ctx, err := s.run(c, "5")
    80  	c.Assert(err, jc.ErrorIsNil)
    81  	c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, "budget set to 5\n")
    82  	s.mockAPI.CheckCall(c, 0, "UpdateBudget", "model-uuid", "", "5")
    83  }
    84  
    85  func (s *budgetSuite) TestUpdateBudgetMoveToWallet(c *gc.C) {
    86  	s.mockAPI.resp = "budget moved to wallet 'work', budget set to 5"
    87  	ctx, err := s.run(c, "work:5")
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, "budget moved to wallet 'work', budget set to 5\n")
    90  	s.mockAPI.CheckCall(c, 0, "UpdateBudget", "model-uuid", "work", "5")
    91  }
    92  
    93  func (s *budgetSuite) TestUpdateBudgetByModelUUID(c *gc.C) {
    94  	modelUUID := utils.MustNewUUID().String()
    95  	s.mockAPI.resp = "budget set to 5"
    96  	ctx, err := s.run(c, "--model-uuid", modelUUID, "5")
    97  	c.Assert(err, jc.ErrorIsNil)
    98  	c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, "budget set to 5\n")
    99  	s.mockAPI.CheckCall(c, 0, "UpdateBudget", modelUUID, "", "5")
   100  }
   101  
   102  func (s *budgetSuite) TestUpdateBudgetByModelName(c *gc.C) {
   103  	s.mockAPI.resp = "budget set to 5"
   104  	ctx, err := s.run(c, "--model", "anothercontroller:somemodel", "5")
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, "budget set to 5\n")
   107  	s.mockAPI.CheckCall(c, 0, "UpdateBudget", "another-model-uuid", "", "5")
   108  }
   109  
   110  func (s *budgetSuite) TestUpdateBudgetInvalidModelUUID(c *gc.C) {
   111  	ctx, err := s.run(c, "--model-uuid", "not-a-uuid", "5")
   112  	c.Assert(err, gc.ErrorMatches, `provided model UUID "not-a-uuid" not valid`)
   113  	c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, "")
   114  	s.mockAPI.CheckNoCalls(c)
   115  }
   116  
   117  func (s *budgetSuite) TestUpdateBudgetAPIError(c *gc.C) {
   118  	s.stub.SetErrors(errors.New("something failed"))
   119  	_, err := s.run(c, "5")
   120  	c.Assert(err, gc.ErrorMatches, "failed to update the budget: something failed")
   121  	s.mockAPI.CheckCall(c, 0, "UpdateBudget", "model-uuid", "", "5")
   122  }
   123  
   124  func (s *budgetSuite) TestUpdateBudgetErrors(c *gc.C) {
   125  	tests := []struct {
   126  		about         string
   127  		args          []string
   128  		expectedError string
   129  	}{
   130  		{
   131  			about:         "budget limit needs to be a number",
   132  			args:          []string{"badvalue"},
   133  			expectedError: "budget limit needs to be a whole number",
   134  		}, {
   135  			about:         "budget limit needs to be a number",
   136  			args:          []string{"wallet:"},
   137  			expectedError: "budget limit needs to be a whole number",
   138  		}, {
   139  			about:         "no args",
   140  			args:          []string{},
   141  			expectedError: "value required",
   142  		},
   143  	}
   144  	for i, test := range tests {
   145  		s.mockAPI.ResetCalls()
   146  		c.Logf("test %d: %s", i, test.about)
   147  		_, err := s.run(c, test.args...)
   148  		c.Check(err, gc.ErrorMatches, test.expectedError)
   149  		s.mockAPI.CheckNoCalls(c)
   150  	}
   151  }
   152  
   153  func newMockAPI(s *testing.Stub) *mockapi {
   154  	return &mockapi{Stub: s}
   155  }
   156  
   157  type mockapi struct {
   158  	*testing.Stub
   159  	resp string
   160  }
   161  
   162  func (api *mockapi) UpdateBudget(modelUUID, wallet, value string) (string, error) {
   163  	api.MethodCall(api, "UpdateBudget", modelUUID, wallet, value)
   164  	return api.resp, api.NextErr()
   165  }