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