github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/sla/sla_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package sla_test 5 6 import ( 7 stdtesting "testing" 8 9 "github.com/juju/cmd" 10 "github.com/juju/cmd/cmdtesting" 11 "github.com/juju/errors" 12 slawire "github.com/juju/romulus/wireformat/sla" 13 "github.com/juju/testing" 14 jujutesting "github.com/juju/testing" 15 jc "github.com/juju/testing/checkers" 16 "github.com/juju/utils" 17 gc "gopkg.in/check.v1" 18 "gopkg.in/juju/names.v2" 19 "gopkg.in/macaroon-bakery.v2-unstable/bakery" 20 "gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers" 21 "gopkg.in/macaroon.v2-unstable" 22 23 "github.com/juju/juju/api" 24 rcmd "github.com/juju/juju/cmd/juju/romulus" 25 "github.com/juju/juju/cmd/juju/romulus/sla" 26 "github.com/juju/juju/cmd/modelcmd" 27 "github.com/juju/juju/jujuclient" 28 ) 29 30 func TestPackage(t *stdtesting.T) { 31 gc.TestingT(t) 32 } 33 34 var _ = gc.Suite(&supportCommandSuite{}) 35 36 type supportCommandSuite struct { 37 jujutesting.CleanupSuite 38 mockAPI *mockapi 39 mockSLAClient *mockSlaClient 40 fakeAPIRoot *fakeAPIConnection 41 charmURL string 42 modelUUID string 43 } 44 45 func (s *supportCommandSuite) SetUpTest(c *gc.C) { 46 s.CleanupSuite.SetUpTest(c) 47 mockAPI, err := newMockAPI() 48 c.Assert(err, jc.ErrorIsNil) 49 s.mockAPI = mockAPI 50 s.mockSLAClient = &mockSlaClient{} 51 s.modelUUID = utils.MustNewUUID().String() 52 s.fakeAPIRoot = &fakeAPIConnection{model: s.modelUUID} 53 s.PatchValue(sla.NewJujuClientStore, s.newMockClientStore) 54 s.PatchValue(&rcmd.GetMeteringURLForModelCmd, func(c *modelcmd.ModelCommandBase) (string, error) { 55 return "http://example.com", nil 56 }) 57 } 58 59 func (s *supportCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, error) { 60 command := sla.NewSLACommandForTest(s.fakeAPIRoot, s.mockSLAClient, s.mockAPI) 61 command.SetClientStore(newMockStore()) 62 return cmdtesting.RunCommand(c, command, args...) 63 } 64 65 func newMockStore() *jujuclient.MemStore { 66 store := jujuclient.NewMemStore() 67 store.CurrentControllerName = "foo" 68 store.Controllers["foo"] = jujuclient.ControllerDetails{ 69 APIEndpoints: []string{"0.1.2.3:1234"}, 70 } 71 store.Models["foo"] = &jujuclient.ControllerModels{ 72 CurrentModel: "admin/bar", 73 Models: map[string]jujuclient.ModelDetails{"admin/bar": {}}, 74 } 75 return store 76 } 77 78 func (s supportCommandSuite) TestSupportCommand(c *gc.C) { 79 tests := []struct { 80 about string 81 level string 82 budget string 83 err string 84 apiErr error 85 apiCalls []testing.StubCall 86 }{{ 87 about: "all is well", 88 level: "essential", 89 apiCalls: []testing.StubCall{{ 90 FuncName: "Authorize", 91 Args: []interface{}{ 92 s.modelUUID, 93 "essential", 94 "", 95 }, 96 }}, 97 }, { 98 about: "all is well with budget", 99 level: "essential", 100 budget: "personal:10", 101 apiCalls: []testing.StubCall{{ 102 FuncName: "Authorize", 103 Args: []interface{}{ 104 s.modelUUID, 105 "essential", 106 "personal:10", 107 }, 108 }}, 109 }, 110 } 111 for i, test := range tests { 112 c.Logf("running test %d: %v", i, test.about) 113 s.mockAPI.ResetCalls() 114 if test.apiErr != nil { 115 s.mockAPI.SetErrors(test.apiErr) 116 } 117 ctx, err := s.run(c, test.level, "--budget", test.budget) 118 if test.err == "" { 119 c.Assert(err, jc.ErrorIsNil) 120 c.Assert(s.mockAPI.Calls(), gc.HasLen, 1) 121 s.mockAPI.CheckCalls(c, test.apiCalls) 122 c.Assert(cmdtesting.Stdout(ctx), gc.Equals, `Model SLA Message 123 c:m1 essential a test message 124 `) 125 } else { 126 c.Assert(err, gc.ErrorMatches, test.err) 127 } 128 } 129 } 130 131 func (s *supportCommandSuite) TestDiplayCurrentLevel(c *gc.C) { 132 tests := []struct { 133 format string 134 expectedOutput string 135 }{{ 136 expectedOutput: `Model SLA Message 137 c:m1 mock-level 138 `, 139 }, { 140 format: "tabular", 141 expectedOutput: `Model SLA Message 142 c:m1 mock-level 143 `, 144 }, { 145 format: "json", 146 expectedOutput: `{"model":"c:m1","sla":"mock-level"} 147 `, 148 }, { 149 format: "yaml", 150 expectedOutput: `model: c:m1 151 sla: mock-level 152 `, 153 }, 154 } 155 156 for i, test := range tests { 157 c.Logf("running test %d", i) 158 args := []string{} 159 if test.format != "" { 160 args = append(args, "--format", test.format) 161 } 162 ctx, err := s.run(c, args...) 163 c.Assert(err, jc.ErrorIsNil, gc.Commentf("%s", errors.Details(err))) 164 c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, test.expectedOutput) 165 } 166 } 167 168 func newMockAPI() (*mockapi, error) { 169 kp, err := bakery.GenerateKey() 170 if err != nil { 171 return nil, errors.Trace(err) 172 } 173 svc, err := bakery.NewService(bakery.NewServiceParams{ 174 Location: "omnibus", 175 Key: kp, 176 }) 177 if err != nil { 178 return nil, errors.Trace(err) 179 } 180 return &mockapi{ 181 service: svc, 182 }, nil 183 } 184 185 type mockapi struct { 186 testing.Stub 187 188 service *bakery.Service 189 macaroon *macaroon.Macaroon 190 } 191 192 func (m *mockapi) Authorize(modelUUID, supportLevel, budget string) (*slawire.SLAResponse, error) { 193 err := m.NextErr() 194 if err != nil { 195 return nil, errors.Trace(err) 196 } 197 m.AddCall("Authorize", modelUUID, supportLevel, budget) 198 macaroon, err := m.service.NewMacaroon([]checkers.Caveat{}) 199 if err != nil { 200 return nil, errors.Trace(err) 201 } 202 m.macaroon = macaroon 203 return &slawire.SLAResponse{ 204 Credentials: m.macaroon, 205 Owner: "bob", 206 Message: "a test message", 207 }, nil 208 } 209 210 type mockSlaClient struct { 211 testing.Stub 212 } 213 214 func (m *mockSlaClient) SetSLALevel(level, owner string, creds []byte) error { 215 m.AddCall("SetSLALevel", level, owner, creds) 216 return nil 217 } 218 func (m *mockSlaClient) SLALevel() (string, error) { 219 m.AddCall("SLALevel") 220 return "mock-level", nil 221 } 222 223 type fakeAPIConnection struct { 224 api.Connection 225 model string 226 } 227 228 func (f *fakeAPIConnection) BestFacadeVersion(facade string) int { 229 return 2 230 } 231 232 func (f *fakeAPIConnection) ModelTag() (names.ModelTag, bool) { 233 return names.NewModelTag(f.model), false 234 } 235 236 type mockClientStore struct { 237 jujuclient.ClientStore 238 modelUUID string 239 } 240 241 func (s *supportCommandSuite) newMockClientStore() jujuclient.ClientStore { 242 return &mockClientStore{modelUUID: s.modelUUID} 243 } 244 245 func (s *mockClientStore) AllControllers() (map[string]jujuclient.ControllerDetails, error) { 246 return map[string]jujuclient.ControllerDetails{ 247 "c": {}, 248 }, nil 249 } 250 251 func (s *mockClientStore) AllModels(controllerName string) (map[string]jujuclient.ModelDetails, error) { 252 return map[string]jujuclient.ModelDetails{ 253 "m1": {ModelUUID: s.modelUUID}, 254 "m2": {ModelUUID: "uuid2"}, 255 "m3": {ModelUUID: "uuid3"}, 256 }, nil 257 }