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 }