github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/modelmanager/modelinfo_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelmanager_test 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/names" 11 gitjujutesting "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/apiserver/common" 16 "github.com/juju/juju/apiserver/modelmanager" 17 "github.com/juju/juju/apiserver/params" 18 apiservertesting "github.com/juju/juju/apiserver/testing" 19 "github.com/juju/juju/environs/config" 20 "github.com/juju/juju/state" 21 "github.com/juju/juju/status" 22 coretesting "github.com/juju/juju/testing" 23 ) 24 25 type modelInfoSuite struct { 26 coretesting.BaseSuite 27 authorizer apiservertesting.FakeAuthorizer 28 st *mockState 29 modelmanager *modelmanager.ModelManagerAPI 30 } 31 32 var _ = gc.Suite(&modelInfoSuite{}) 33 34 func (s *modelInfoSuite) SetUpTest(c *gc.C) { 35 s.BaseSuite.SetUpTest(c) 36 s.authorizer = apiservertesting.FakeAuthorizer{ 37 Tag: names.NewUserTag("admin@local"), 38 } 39 s.st = &mockState{ 40 uuid: coretesting.ModelTag.Id(), 41 } 42 s.st.model = &mockModel{ 43 owner: names.NewUserTag("bob@local"), 44 cfg: coretesting.ModelConfig(c), 45 life: state.Dying, 46 status: status.StatusInfo{ 47 Status: status.StatusDestroying, 48 Since: &time.Time{}, 49 }, 50 users: []*mockModelUser{{ 51 userName: "admin", 52 access: state.ModelAdminAccess, 53 }, { 54 userName: "bob@local", 55 displayName: "Bob", 56 access: state.ModelReadAccess, 57 }, { 58 userName: "charlotte@local", 59 displayName: "Charlotte", 60 access: state.ModelReadAccess, 61 }}, 62 } 63 var err error 64 s.modelmanager, err = modelmanager.NewModelManagerAPI(s.st, &s.authorizer) 65 c.Assert(err, jc.ErrorIsNil) 66 } 67 68 func (s *modelInfoSuite) setAPIUser(c *gc.C, user names.UserTag) { 69 s.authorizer.Tag = user 70 modelmanager, err := modelmanager.NewModelManagerAPI(s.st, s.authorizer) 71 c.Assert(err, jc.ErrorIsNil) 72 s.modelmanager = modelmanager 73 } 74 75 func (s *modelInfoSuite) TestModelInfo(c *gc.C) { 76 s.st.model.users[1].SetErrors( 77 nil, state.NeverConnectedError("never connected"), 78 ) 79 info := s.getModelInfo(c) 80 c.Assert(info, jc.DeepEquals, params.ModelInfo{ 81 Name: "testenv", 82 UUID: s.st.model.cfg.UUID(), 83 ControllerUUID: coretesting.ModelTag.Id(), 84 OwnerTag: "user-bob@local", 85 ProviderType: "someprovider", 86 DefaultSeries: coretesting.FakeDefaultSeries, 87 Life: params.Dying, 88 Status: params.EntityStatus{ 89 Status: status.StatusDestroying, 90 Since: &time.Time{}, 91 }, 92 Users: []params.ModelUserInfo{{ 93 UserName: "admin", 94 LastConnection: &time.Time{}, 95 Access: params.ModelWriteAccess, 96 }, { 97 UserName: "bob@local", 98 DisplayName: "Bob", 99 LastConnection: nil, // never connected 100 Access: params.ModelReadAccess, 101 }, { 102 UserName: "charlotte@local", 103 DisplayName: "Charlotte", 104 LastConnection: &time.Time{}, 105 Access: params.ModelReadAccess, 106 }}, 107 }) 108 s.st.CheckCalls(c, []gitjujutesting.StubCall{ 109 {"IsControllerAdministrator", []interface{}{names.NewUserTag("admin@local")}}, 110 {"ModelUUID", nil}, 111 {"ForModel", []interface{}{names.NewModelTag(s.st.model.cfg.UUID())}}, 112 {"Model", nil}, 113 {"Close", nil}, 114 }) 115 s.st.model.CheckCalls(c, []gitjujutesting.StubCall{ 116 {"Config", nil}, 117 {"Users", nil}, 118 {"Status", nil}, 119 {"Owner", nil}, 120 {"Life", nil}, 121 }) 122 } 123 124 func (s *modelInfoSuite) TestModelInfoOwner(c *gc.C) { 125 s.setAPIUser(c, names.NewUserTag("bob@local")) 126 info := s.getModelInfo(c) 127 c.Assert(info.Users, gc.HasLen, 3) 128 } 129 130 func (s *modelInfoSuite) TestModelInfoNonOwner(c *gc.C) { 131 s.setAPIUser(c, names.NewUserTag("charlotte@local")) 132 info := s.getModelInfo(c) 133 c.Assert(info.Users, gc.HasLen, 1) 134 c.Assert(info.Users[0].UserName, gc.Equals, "charlotte@local") 135 } 136 137 func (s *modelInfoSuite) getModelInfo(c *gc.C) params.ModelInfo { 138 results, err := s.modelmanager.ModelInfo(params.Entities{ 139 Entities: []params.Entity{{ 140 names.NewModelTag(s.st.model.cfg.UUID()).String(), 141 }}, 142 }) 143 c.Assert(err, jc.ErrorIsNil) 144 c.Assert(results.Results, gc.HasLen, 1) 145 c.Assert(results.Results[0].Result, gc.NotNil) 146 c.Assert(results.Results[0].Error, gc.IsNil) 147 return *results.Results[0].Result 148 } 149 150 func (s *modelInfoSuite) TestModelInfoErrorInvalidTag(c *gc.C) { 151 s.testModelInfoError(c, "user-bob", `"user-bob" is not a valid model tag`) 152 } 153 154 func (s *modelInfoSuite) TestModelInfoErrorGetModelNotFound(c *gc.C) { 155 s.st.SetErrors(errors.NotFoundf("model")) 156 s.testModelInfoError(c, coretesting.ModelTag.String(), `permission denied`) 157 } 158 159 func (s *modelInfoSuite) TestModelInfoErrorModelConfig(c *gc.C) { 160 s.st.model.SetErrors(errors.Errorf("no config for you")) 161 s.testModelInfoError(c, coretesting.ModelTag.String(), `no config for you`) 162 } 163 164 func (s *modelInfoSuite) TestModelInfoErrorModelUsers(c *gc.C) { 165 s.st.model.SetErrors(errors.Errorf("no users for you")) 166 s.testModelInfoError(c, coretesting.ModelTag.String(), `no users for you`) 167 } 168 169 func (s *modelInfoSuite) TestModelInfoErrorNoModelUsers(c *gc.C) { 170 s.st.model.users = nil 171 s.testModelInfoError(c, coretesting.ModelTag.String(), `permission denied`) 172 } 173 174 func (s *modelInfoSuite) TestModelInfoErrorNoAccess(c *gc.C) { 175 s.setAPIUser(c, names.NewUserTag("nemo@local")) 176 s.testModelInfoError(c, coretesting.ModelTag.String(), `permission denied`) 177 } 178 179 func (s *modelInfoSuite) testModelInfoError(c *gc.C, modelTag, expectedErr string) { 180 results, err := s.modelmanager.ModelInfo(params.Entities{ 181 Entities: []params.Entity{{modelTag}}, 182 }) 183 c.Assert(err, jc.ErrorIsNil) 184 c.Assert(results.Results, gc.HasLen, 1) 185 c.Assert(results.Results[0].Result, gc.IsNil) 186 c.Assert(results.Results[0].Error, gc.ErrorMatches, expectedErr) 187 } 188 189 type mockState struct { 190 gitjujutesting.Stub 191 192 common.APIHostPortsGetter 193 common.ModelConfigGetter 194 common.ToolsStorageGetter 195 196 uuid string 197 model *mockModel 198 owner names.UserTag 199 users []*state.ModelUser 200 } 201 202 func (st *mockState) ModelUUID() string { 203 st.MethodCall(st, "ModelUUID") 204 return st.uuid 205 } 206 207 func (st *mockState) ModelsForUser(user names.UserTag) ([]*state.UserModel, error) { 208 st.MethodCall(st, "ModelsForUser", user) 209 return nil, st.NextErr() 210 } 211 212 func (st *mockState) IsControllerAdministrator(user names.UserTag) (bool, error) { 213 st.MethodCall(st, "IsControllerAdministrator", user) 214 return user.Canonical() == "admin@local", st.NextErr() 215 } 216 217 func (st *mockState) NewModel(args state.ModelArgs) (*state.Model, *state.State, error) { 218 st.MethodCall(st, "NewModel", args) 219 return nil, nil, st.NextErr() 220 } 221 222 func (st *mockState) ControllerModel() (*state.Model, error) { 223 st.MethodCall(st, "ControllerModel") 224 return nil, st.NextErr() 225 } 226 227 func (st *mockState) ForModel(tag names.ModelTag) (modelmanager.Backend, error) { 228 st.MethodCall(st, "ForModel", tag) 229 return st, st.NextErr() 230 } 231 232 func (st *mockState) Model() (modelmanager.Model, error) { 233 st.MethodCall(st, "Model") 234 return st.model, st.NextErr() 235 } 236 237 func (st *mockState) Close() error { 238 st.MethodCall(st, "Close") 239 return st.NextErr() 240 } 241 242 func (st *mockState) AddModelUser(spec state.ModelUserSpec) (*state.ModelUser, error) { 243 st.MethodCall(st, "AddModelUser", spec) 244 return nil, st.NextErr() 245 } 246 247 func (st *mockState) RemoveModelUser(tag names.UserTag) error { 248 st.MethodCall(st, "RemoveModelUser", tag) 249 return st.NextErr() 250 } 251 252 func (st *mockState) ModelUser(tag names.UserTag) (*state.ModelUser, error) { 253 st.MethodCall(st, "ModelUser", tag) 254 return nil, st.NextErr() 255 } 256 257 type mockModel struct { 258 gitjujutesting.Stub 259 owner names.UserTag 260 life state.Life 261 status status.StatusInfo 262 cfg *config.Config 263 users []*mockModelUser 264 } 265 266 func (m *mockModel) Config() (*config.Config, error) { 267 m.MethodCall(m, "Config") 268 return m.cfg, m.NextErr() 269 } 270 271 func (m *mockModel) Owner() names.UserTag { 272 m.MethodCall(m, "Owner") 273 m.PopNoErr() 274 return m.owner 275 } 276 277 func (m *mockModel) Life() state.Life { 278 m.MethodCall(m, "Life") 279 m.PopNoErr() 280 return m.life 281 } 282 283 func (m *mockModel) Status() (status.StatusInfo, error) { 284 m.MethodCall(m, "Status") 285 return m.status, m.NextErr() 286 } 287 288 func (m *mockModel) Users() ([]common.ModelUser, error) { 289 m.MethodCall(m, "Users") 290 if err := m.NextErr(); err != nil { 291 return nil, err 292 } 293 users := make([]common.ModelUser, len(m.users)) 294 for i, user := range m.users { 295 users[i] = user 296 } 297 return users, nil 298 } 299 300 type mockModelUser struct { 301 gitjujutesting.Stub 302 userName string 303 displayName string 304 access state.ModelAccess 305 lastConnection time.Time 306 } 307 308 func (u *mockModelUser) Access() state.ModelAccess { 309 u.MethodCall(u, "Access") 310 u.PopNoErr() 311 return u.access 312 } 313 314 func (u *mockModelUser) DisplayName() string { 315 u.MethodCall(u, "DisplayName") 316 u.PopNoErr() 317 return u.displayName 318 } 319 320 func (u *mockModelUser) LastConnection() (time.Time, error) { 321 u.MethodCall(u, "LastConnection") 322 return u.lastConnection, u.NextErr() 323 } 324 325 func (u *mockModelUser) UserName() string { 326 u.MethodCall(u, "UserName") 327 u.PopNoErr() 328 return u.userName 329 } 330 331 func (u *mockModelUser) UserTag() names.UserTag { 332 u.MethodCall(u, "UserTag") 333 u.PopNoErr() 334 return names.NewUserTag(u.userName) 335 }