github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/modelmanager/modelmanager_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelmanager_test 5 6 import ( 7 "regexp" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/apiserver/modelmanager" 16 "github.com/juju/juju/apiserver/params" 17 apiservertesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/environs" 19 "github.com/juju/juju/environs/config" 20 jujutesting "github.com/juju/juju/juju/testing" 21 jujuversion "github.com/juju/juju/version" 22 // Register the providers for the field check test 23 _ "github.com/juju/juju/provider/azure" 24 _ "github.com/juju/juju/provider/ec2" 25 _ "github.com/juju/juju/provider/joyent" 26 _ "github.com/juju/juju/provider/maas" 27 _ "github.com/juju/juju/provider/openstack" 28 "github.com/juju/juju/state" 29 coretesting "github.com/juju/juju/testing" 30 "github.com/juju/juju/testing/factory" 31 ) 32 33 type modelManagerBaseSuite struct { 34 jujutesting.JujuConnSuite 35 36 modelmanager *modelmanager.ModelManagerAPI 37 authoriser apiservertesting.FakeAuthorizer 38 } 39 40 func (s *modelManagerBaseSuite) SetUpTest(c *gc.C) { 41 s.JujuConnSuite.SetUpTest(c) 42 s.authoriser = apiservertesting.FakeAuthorizer{ 43 Tag: s.AdminUserTag(c), 44 } 45 loggo.GetLogger("juju.apiserver.modelmanager").SetLogLevel(loggo.TRACE) 46 } 47 48 func (s *modelManagerBaseSuite) setAPIUser(c *gc.C, user names.UserTag) { 49 s.authoriser.Tag = user 50 modelmanager, err := modelmanager.NewModelManagerAPI( 51 modelmanager.NewStateBackend(s.State), s.authoriser, 52 ) 53 c.Assert(err, jc.ErrorIsNil) 54 s.modelmanager = modelmanager 55 } 56 57 type modelManagerSuite struct { 58 modelManagerBaseSuite 59 } 60 61 var _ = gc.Suite(&modelManagerSuite{}) 62 63 func (s *modelManagerSuite) TestNewAPIAcceptsClient(c *gc.C) { 64 anAuthoriser := s.authoriser 65 anAuthoriser.Tag = names.NewUserTag("external@remote") 66 endPoint, err := modelmanager.NewModelManagerAPI( 67 modelmanager.NewStateBackend(s.State), anAuthoriser, 68 ) 69 c.Assert(err, jc.ErrorIsNil) 70 c.Assert(endPoint, gc.NotNil) 71 } 72 73 func (s *modelManagerSuite) TestNewAPIRefusesNonClient(c *gc.C) { 74 anAuthoriser := s.authoriser 75 anAuthoriser.Tag = names.NewUnitTag("mysql/0") 76 endPoint, err := modelmanager.NewModelManagerAPI( 77 modelmanager.NewStateBackend(s.State), anAuthoriser, 78 ) 79 c.Assert(endPoint, gc.IsNil) 80 c.Assert(err, gc.ErrorMatches, "permission denied") 81 } 82 83 func (s *modelManagerSuite) createArgs(c *gc.C, owner names.UserTag) params.ModelCreateArgs { 84 return params.ModelCreateArgs{ 85 OwnerTag: owner.String(), 86 Account: make(map[string]interface{}), 87 Config: map[string]interface{}{ 88 "name": "test-model", 89 "authorized-keys": "ssh-key", 90 // And to make it a valid dummy config 91 "controller": false, 92 }, 93 } 94 } 95 96 func (s *modelManagerSuite) createArgsForVersion(c *gc.C, owner names.UserTag, ver interface{}) params.ModelCreateArgs { 97 params := s.createArgs(c, owner) 98 params.Config["agent-version"] = ver 99 return params 100 } 101 102 func (s *modelManagerSuite) TestUserCanCreateModel(c *gc.C) { 103 owner := names.NewUserTag("external@remote") 104 s.setAPIUser(c, owner) 105 model, err := s.modelmanager.CreateModel(s.createArgs(c, owner)) 106 c.Assert(err, jc.ErrorIsNil) 107 c.Assert(model.OwnerTag, gc.Equals, owner.String()) 108 c.Assert(model.Name, gc.Equals, "test-model") 109 } 110 111 func (s *modelManagerSuite) TestAdminCanCreateModelForSomeoneElse(c *gc.C) { 112 s.setAPIUser(c, s.AdminUserTag(c)) 113 owner := names.NewUserTag("external@remote") 114 model, err := s.modelmanager.CreateModel(s.createArgs(c, owner)) 115 c.Assert(err, jc.ErrorIsNil) 116 c.Assert(model.OwnerTag, gc.Equals, owner.String()) 117 c.Assert(model.Name, gc.Equals, "test-model") 118 // Make sure that the environment created does actually have the correct 119 // owner, and that owner is actually allowed to use the environment. 120 newState, err := s.State.ForModel(names.NewModelTag(model.UUID)) 121 c.Assert(err, jc.ErrorIsNil) 122 defer newState.Close() 123 124 newModel, err := newState.Model() 125 c.Assert(err, jc.ErrorIsNil) 126 c.Assert(newModel.Owner(), gc.Equals, owner) 127 _, err = newState.ModelUser(owner) 128 c.Assert(err, jc.ErrorIsNil) 129 } 130 131 func (s *modelManagerSuite) TestNonAdminCannotCreateModelForSomeoneElse(c *gc.C) { 132 s.setAPIUser(c, names.NewUserTag("non-admin@remote")) 133 owner := names.NewUserTag("external@remote") 134 _, err := s.modelmanager.CreateModel(s.createArgs(c, owner)) 135 c.Assert(err, gc.ErrorMatches, "permission denied") 136 } 137 138 func (s *modelManagerSuite) TestConfigSkeleton(c *gc.C) { 139 s.setAPIUser(c, names.NewUserTag("non-admin@remote")) 140 141 _, err := s.modelmanager.ConfigSkeleton( 142 params.ModelSkeletonConfigArgs{Provider: "ec2"}) 143 c.Check(err, gc.ErrorMatches, `cannot create new model with credentials for provider type "ec2" on controller with provider type "dummy"`) 144 _, err = s.modelmanager.ConfigSkeleton( 145 params.ModelSkeletonConfigArgs{Region: "the sun"}) 146 c.Check(err, gc.ErrorMatches, `region value "the sun" not valid`) 147 148 skeleton, err := s.modelmanager.ConfigSkeleton(params.ModelSkeletonConfigArgs{}) 149 c.Assert(err, jc.ErrorIsNil) 150 151 // The apiPort changes every test run as the dummy provider 152 // looks for a random open port. 153 apiPort := s.Environ.Config().APIPort() 154 155 c.Assert(skeleton.Config, jc.DeepEquals, params.ModelConfig{ 156 "type": "dummy", 157 "controller-uuid": coretesting.ModelTag.Id(), 158 "ca-cert": coretesting.CACert, 159 "state-port": 1234, 160 "api-port": apiPort, 161 }) 162 } 163 164 func (s *modelManagerSuite) TestCreateModelValidatesConfig(c *gc.C) { 165 admin := s.AdminUserTag(c) 166 s.setAPIUser(c, admin) 167 args := s.createArgs(c, admin) 168 args.Config["controller"] = "maybe" 169 _, err := s.modelmanager.CreateModel(args) 170 c.Assert(err, gc.ErrorMatches, 171 "failed to create config: provider validation failed: controller: expected bool, got string\\(\"maybe\"\\)", 172 ) 173 } 174 175 func (s *modelManagerSuite) TestCreateModelBadConfig(c *gc.C) { 176 owner := names.NewUserTag("external@remote") 177 s.setAPIUser(c, owner) 178 for i, test := range []struct { 179 key string 180 value interface{} 181 errMatch string 182 }{ 183 { 184 key: "uuid", 185 value: "anything", 186 errMatch: `failed to create config: uuid is generated, you cannot specify one`, 187 }, { 188 key: "type", 189 value: "fake", 190 errMatch: `failed to create config: specified type "fake" does not match controller "dummy"`, 191 }, { 192 key: "ca-cert", 193 value: coretesting.OtherCACert, 194 errMatch: `failed to create config: (?s)specified ca-cert ".*" does not match controller ".*"`, 195 }, { 196 key: "state-port", 197 value: 9876, 198 errMatch: `failed to create config: specified state-port "9876" does not match controller "1234"`, 199 }, { 200 // The api-port is dynamic, but always in user-space, so > 1024. 201 key: "api-port", 202 value: 123, 203 errMatch: `failed to create config: specified api-port "123" does not match controller ".*"`, 204 }, 205 } { 206 c.Logf("%d: %s", i, test.key) 207 args := s.createArgs(c, owner) 208 args.Config[test.key] = test.value 209 _, err := s.modelmanager.CreateModel(args) 210 c.Assert(err, gc.ErrorMatches, test.errMatch) 211 212 } 213 } 214 215 func (s *modelManagerSuite) TestCreateModelSameAgentVersion(c *gc.C) { 216 admin := s.AdminUserTag(c) 217 s.setAPIUser(c, admin) 218 args := s.createArgsForVersion(c, admin, jujuversion.Current.String()) 219 _, err := s.modelmanager.CreateModel(args) 220 c.Assert(err, jc.ErrorIsNil) 221 } 222 223 func (s *modelManagerSuite) TestCreateModelBadAgentVersion(c *gc.C) { 224 err := s.BackingState.SetModelAgentVersion(coretesting.FakeVersionNumber) 225 c.Assert(err, jc.ErrorIsNil) 226 227 admin := s.AdminUserTag(c) 228 s.setAPIUser(c, admin) 229 230 bigger := coretesting.FakeVersionNumber 231 bigger.Minor += 1 232 233 smaller := coretesting.FakeVersionNumber 234 smaller.Minor -= 1 235 236 for i, test := range []struct { 237 value interface{} 238 errMatch string 239 }{ 240 { 241 value: 42, 242 errMatch: `failed to create config: agent-version must be a string but has type 'int'`, 243 }, { 244 value: "not a number", 245 errMatch: `failed to create config: invalid version \"not a number\"`, 246 }, { 247 value: bigger.String(), 248 errMatch: "failed to create config: agent-version .* cannot be greater than the controller .*", 249 }, { 250 value: smaller.String(), 251 errMatch: "failed to create config: no tools found for version .*", 252 }, 253 } { 254 c.Logf("test %d", i) 255 args := s.createArgsForVersion(c, admin, test.value) 256 _, err := s.modelmanager.CreateModel(args) 257 c.Check(err, gc.ErrorMatches, test.errMatch) 258 } 259 } 260 261 func (s *modelManagerSuite) TestListModelsForSelf(c *gc.C) { 262 user := names.NewUserTag("external@remote") 263 s.setAPIUser(c, user) 264 result, err := s.modelmanager.ListModels(params.Entity{Tag: user.String()}) 265 c.Assert(err, jc.ErrorIsNil) 266 c.Assert(result.UserModels, gc.HasLen, 0) 267 } 268 269 func (s *modelManagerSuite) TestListModelsForSelfLocalUser(c *gc.C) { 270 // When the user's credentials cache stores the simple name, but the 271 // api server converts it to a fully qualified name. 272 user := names.NewUserTag("local-user") 273 s.setAPIUser(c, names.NewUserTag("local-user@local")) 274 result, err := s.modelmanager.ListModels(params.Entity{Tag: user.String()}) 275 c.Assert(err, jc.ErrorIsNil) 276 c.Assert(result.UserModels, gc.HasLen, 0) 277 } 278 279 func (s *modelManagerSuite) checkModelMatches(c *gc.C, env params.Model, expected *state.Model) { 280 c.Check(env.Name, gc.Equals, expected.Name()) 281 c.Check(env.UUID, gc.Equals, expected.UUID()) 282 c.Check(env.OwnerTag, gc.Equals, expected.Owner().String()) 283 } 284 285 func (s *modelManagerSuite) TestListModelsAdminSelf(c *gc.C) { 286 user := s.AdminUserTag(c) 287 s.setAPIUser(c, user) 288 result, err := s.modelmanager.ListModels(params.Entity{Tag: user.String()}) 289 c.Assert(err, jc.ErrorIsNil) 290 c.Assert(result.UserModels, gc.HasLen, 1) 291 expected, err := s.State.Model() 292 c.Assert(err, jc.ErrorIsNil) 293 s.checkModelMatches(c, result.UserModels[0].Model, expected) 294 } 295 296 func (s *modelManagerSuite) TestListModelsAdminListsOther(c *gc.C) { 297 user := s.AdminUserTag(c) 298 s.setAPIUser(c, user) 299 other := names.NewUserTag("external@remote") 300 result, err := s.modelmanager.ListModels(params.Entity{Tag: other.String()}) 301 c.Assert(err, jc.ErrorIsNil) 302 c.Assert(result.UserModels, gc.HasLen, 0) 303 } 304 305 func (s *modelManagerSuite) TestListModelsDenied(c *gc.C) { 306 user := names.NewUserTag("external@remote") 307 s.setAPIUser(c, user) 308 other := names.NewUserTag("other@remote") 309 _, err := s.modelmanager.ListModels(params.Entity{Tag: other.String()}) 310 c.Assert(err, gc.ErrorMatches, "permission denied") 311 } 312 313 func (s *modelManagerSuite) TestAdminModelManager(c *gc.C) { 314 user := s.AdminUserTag(c) 315 s.setAPIUser(c, user) 316 c.Assert(modelmanager.AuthCheck(c, s.modelmanager, user), jc.IsTrue) 317 } 318 319 func (s *modelManagerSuite) TestNonAdminModelManager(c *gc.C) { 320 user := names.NewUserTag("external@remote") 321 s.setAPIUser(c, user) 322 c.Assert(modelmanager.AuthCheck(c, s.modelmanager, user), jc.IsFalse) 323 } 324 325 func (s *modelManagerSuite) modifyAccess(c *gc.C, user names.UserTag, action params.ModelAction, access params.ModelAccessPermission, model names.ModelTag) error { 326 args := params.ModifyModelAccessRequest{ 327 Changes: []params.ModifyModelAccess{{ 328 UserTag: user.String(), 329 Action: action, 330 Access: access, 331 ModelTag: model.String(), 332 }}} 333 result, err := s.modelmanager.ModifyModelAccess(args) 334 c.Assert(err, jc.ErrorIsNil) 335 return result.OneError() 336 } 337 338 func (s *modelManagerSuite) grant(c *gc.C, user names.UserTag, access params.ModelAccessPermission, model names.ModelTag) error { 339 return s.modifyAccess(c, user, params.GrantModelAccess, access, model) 340 } 341 342 func (s *modelManagerSuite) revoke(c *gc.C, user names.UserTag, access params.ModelAccessPermission, model names.ModelTag) error { 343 return s.modifyAccess(c, user, params.RevokeModelAccess, access, model) 344 } 345 346 func (s *modelManagerSuite) TestGrantMissingUserFails(c *gc.C) { 347 s.setAPIUser(c, s.AdminUserTag(c)) 348 st := s.Factory.MakeModel(c, nil) 349 defer st.Close() 350 351 user := names.NewLocalUserTag("foobar") 352 err := s.grant(c, user, params.ModelReadAccess, st.ModelTag()) 353 expectedErr := `could not grant model access: user "foobar" does not exist locally: user "foobar" not found` 354 c.Assert(err, gc.ErrorMatches, expectedErr) 355 } 356 357 func (s *modelManagerSuite) TestGrantMissingModelFails(c *gc.C) { 358 s.setAPIUser(c, s.AdminUserTag(c)) 359 user := s.Factory.MakeModelUser(c, nil) 360 model := names.NewModelTag("17e4bd2d-3e08-4f3d-b945-087be7ebdce4") 361 err := s.grant(c, user.UserTag(), params.ModelReadAccess, model) 362 expectedErr := `model not found` 363 c.Assert(err, gc.ErrorMatches, expectedErr) 364 } 365 366 func (s *modelManagerSuite) TestRevokeAdminLeavesReadAccess(c *gc.C) { 367 s.setAPIUser(c, s.AdminUserTag(c)) 368 user := s.Factory.MakeModelUser(c, &factory.ModelUserParams{Access: state.ModelAdminAccess}) 369 370 err := s.revoke(c, user.UserTag(), params.ModelWriteAccess, user.ModelTag()) 371 c.Assert(err, gc.IsNil) 372 373 modelUser, err := s.State.ModelUser(user.UserTag()) 374 c.Assert(err, jc.ErrorIsNil) 375 c.Assert(modelUser.ReadOnly(), jc.IsTrue) 376 } 377 378 func (s *modelManagerSuite) TestRevokeReadRemovesModelUser(c *gc.C) { 379 s.setAPIUser(c, s.AdminUserTag(c)) 380 user := s.Factory.MakeModelUser(c, nil) 381 382 err := s.revoke(c, user.UserTag(), params.ModelReadAccess, user.ModelTag()) 383 c.Assert(err, gc.IsNil) 384 385 _, err = s.State.ModelUser(user.UserTag()) 386 c.Assert(errors.IsNotFound(err), jc.IsTrue) 387 } 388 389 func (s *modelManagerSuite) TestRevokeModelMissingUser(c *gc.C) { 390 s.setAPIUser(c, s.AdminUserTag(c)) 391 st := s.Factory.MakeModel(c, nil) 392 defer st.Close() 393 394 user := names.NewUserTag("bob") 395 err := s.revoke(c, user, params.ModelReadAccess, st.ModelTag()) 396 c.Assert(err, gc.ErrorMatches, `could not revoke model access: model user "bob@local" does not exist`) 397 398 _, err = st.ModelUser(user) 399 c.Assert(errors.IsNotFound(err), jc.IsTrue) 400 } 401 402 func (s *modelManagerSuite) TestGrantOnlyGreaterAccess(c *gc.C) { 403 user := s.Factory.MakeUser(c, &factory.UserParams{Name: "foobar", NoModelUser: true}) 404 s.setAPIUser(c, s.AdminUserTag(c)) 405 st := s.Factory.MakeModel(c, nil) 406 defer st.Close() 407 408 err := s.grant(c, user.UserTag(), params.ModelReadAccess, st.ModelTag()) 409 c.Assert(err, jc.ErrorIsNil) 410 411 err = s.grant(c, user.UserTag(), params.ModelReadAccess, st.ModelTag()) 412 c.Assert(err, gc.ErrorMatches, `user already has "read" access`) 413 } 414 415 func (s *modelManagerSuite) assertNewUser(c *gc.C, modelUser *state.ModelUser, userTag, creatorTag names.UserTag) { 416 c.Assert(modelUser.UserTag(), gc.Equals, userTag) 417 c.Assert(modelUser.CreatedBy(), gc.Equals, creatorTag.Canonical()) 418 _, err := modelUser.LastConnection() 419 c.Assert(err, jc.Satisfies, state.IsNeverConnectedError) 420 } 421 422 func (s *modelManagerSuite) TestGrantModelAddLocalUser(c *gc.C) { 423 user := s.Factory.MakeUser(c, &factory.UserParams{Name: "foobar", NoModelUser: true}) 424 apiUser := s.AdminUserTag(c) 425 s.setAPIUser(c, apiUser) 426 st := s.Factory.MakeModel(c, nil) 427 defer st.Close() 428 429 err := s.grant(c, user.UserTag(), params.ModelReadAccess, st.ModelTag()) 430 c.Assert(err, jc.ErrorIsNil) 431 432 modelUser, err := st.ModelUser(user.UserTag()) 433 c.Assert(err, jc.ErrorIsNil) 434 s.assertNewUser(c, modelUser, user.UserTag(), apiUser) 435 c.Assert(modelUser.ReadOnly(), jc.IsTrue) 436 } 437 438 func (s *modelManagerSuite) TestGrantModelAddRemoteUser(c *gc.C) { 439 userTag := names.NewUserTag("foobar@ubuntuone") 440 apiUser := s.AdminUserTag(c) 441 s.setAPIUser(c, apiUser) 442 st := s.Factory.MakeModel(c, nil) 443 defer st.Close() 444 445 err := s.grant(c, userTag, params.ModelReadAccess, st.ModelTag()) 446 c.Assert(err, jc.ErrorIsNil) 447 448 modelUser, err := st.ModelUser(userTag) 449 c.Assert(err, jc.ErrorIsNil) 450 451 s.assertNewUser(c, modelUser, userTag, apiUser) 452 c.Assert(modelUser.ReadOnly(), jc.IsTrue) 453 } 454 455 func (s *modelManagerSuite) TestGrantModelAddAdminUser(c *gc.C) { 456 user := s.Factory.MakeUser(c, &factory.UserParams{Name: "foobar", NoModelUser: true}) 457 apiUser := s.AdminUserTag(c) 458 s.setAPIUser(c, apiUser) 459 st := s.Factory.MakeModel(c, nil) 460 defer st.Close() 461 462 err := s.grant(c, user.UserTag(), params.ModelWriteAccess, st.ModelTag()) 463 464 modelUser, err := st.ModelUser(user.UserTag()) 465 c.Assert(err, jc.ErrorIsNil) 466 s.assertNewUser(c, modelUser, user.UserTag(), apiUser) 467 c.Assert(modelUser.ReadOnly(), jc.IsFalse) 468 } 469 470 func (s *modelManagerSuite) TestGrantModelIncreaseAccess(c *gc.C) { 471 s.setAPIUser(c, s.AdminUserTag(c)) 472 st := s.Factory.MakeModel(c, nil) 473 defer st.Close() 474 stFactory := factory.NewFactory(st) 475 user := stFactory.MakeModelUser(c, &factory.ModelUserParams{Access: state.ModelReadAccess}) 476 477 err := s.grant(c, user.UserTag(), params.ModelWriteAccess, st.ModelTag()) 478 c.Assert(err, jc.ErrorIsNil) 479 480 modelUser, err := st.ModelUser(user.UserTag()) 481 c.Assert(err, jc.ErrorIsNil) 482 c.Assert(modelUser.Access(), gc.Equals, state.ModelAdminAccess) 483 } 484 485 func (s *modelManagerSuite) TestGrantToModelNoAccess(c *gc.C) { 486 apiUser := names.NewUserTag("bob@remote") 487 s.setAPIUser(c, apiUser) 488 489 st := s.Factory.MakeModel(c, nil) 490 defer st.Close() 491 492 other := names.NewUserTag("other@remote") 493 err := s.grant(c, other, params.ModelReadAccess, st.ModelTag()) 494 c.Assert(err, gc.ErrorMatches, "permission denied") 495 } 496 497 func (s *modelManagerSuite) TestGrantToModelReadAccess(c *gc.C) { 498 apiUser := names.NewUserTag("bob@remote") 499 s.setAPIUser(c, apiUser) 500 501 st := s.Factory.MakeModel(c, nil) 502 defer st.Close() 503 stFactory := factory.NewFactory(st) 504 stFactory.MakeModelUser(c, &factory.ModelUserParams{ 505 User: apiUser.Canonical(), Access: state.ModelReadAccess}) 506 507 other := names.NewUserTag("other@remote") 508 err := s.grant(c, other, params.ModelReadAccess, st.ModelTag()) 509 c.Assert(err, gc.ErrorMatches, "permission denied") 510 } 511 512 func (s *modelManagerSuite) TestGrantToModelWriteAccess(c *gc.C) { 513 apiUser := names.NewUserTag("bob@remote") 514 s.setAPIUser(c, apiUser) 515 516 st := s.Factory.MakeModel(c, nil) 517 defer st.Close() 518 stFactory := factory.NewFactory(st) 519 stFactory.MakeModelUser(c, &factory.ModelUserParams{ 520 User: apiUser.Canonical(), Access: state.ModelAdminAccess}) 521 522 other := names.NewUserTag("other@remote") 523 err := s.grant(c, other, params.ModelReadAccess, st.ModelTag()) 524 c.Assert(err, jc.ErrorIsNil) 525 526 modelUser, err := st.ModelUser(other) 527 c.Assert(err, jc.ErrorIsNil) 528 s.assertNewUser(c, modelUser, other, apiUser) 529 c.Assert(modelUser.ReadOnly(), jc.IsTrue) 530 } 531 532 func (s *modelManagerSuite) TestGrantModelInvalidUserTag(c *gc.C) { 533 s.setAPIUser(c, s.AdminUserTag(c)) 534 for _, testParam := range []struct { 535 tag string 536 validTag bool 537 }{{ 538 tag: "unit-foo/0", 539 validTag: true, 540 }, { 541 tag: "service-foo", 542 validTag: true, 543 }, { 544 tag: "relation-wordpress:db mysql:db", 545 validTag: true, 546 }, { 547 tag: "machine-0", 548 validTag: true, 549 }, { 550 tag: "user@local", 551 validTag: false, 552 }, { 553 tag: "user-Mua^h^h^h^arh", 554 validTag: true, 555 }, { 556 tag: "user@", 557 validTag: false, 558 }, { 559 tag: "user@ubuntuone", 560 validTag: false, 561 }, { 562 tag: "user@ubuntuone", 563 validTag: false, 564 }, { 565 tag: "@ubuntuone", 566 validTag: false, 567 }, { 568 tag: "in^valid.", 569 validTag: false, 570 }, { 571 tag: "", 572 validTag: false, 573 }, 574 } { 575 var expectedErr string 576 errPart := `could not modify model access: "` + regexp.QuoteMeta(testParam.tag) + `" is not a valid ` 577 578 if testParam.validTag { 579 // The string is a valid tag, but not a user tag. 580 expectedErr = errPart + `user tag` 581 } else { 582 // The string is not a valid tag of any kind. 583 expectedErr = errPart + `tag` 584 } 585 586 args := params.ModifyModelAccessRequest{ 587 Changes: []params.ModifyModelAccess{{ 588 UserTag: testParam.tag, 589 Action: params.GrantModelAccess, 590 Access: params.ModelReadAccess, 591 }}} 592 593 result, err := s.modelmanager.ModifyModelAccess(args) 594 c.Assert(err, jc.ErrorIsNil) 595 c.Assert(result.OneError(), gc.ErrorMatches, expectedErr) 596 } 597 } 598 599 func (s *modelManagerSuite) TestModifyModelAccessEmptyArgs(c *gc.C) { 600 s.setAPIUser(c, s.AdminUserTag(c)) 601 args := params.ModifyModelAccessRequest{Changes: []params.ModifyModelAccess{{}}} 602 603 result, err := s.modelmanager.ModifyModelAccess(args) 604 c.Assert(err, jc.ErrorIsNil) 605 expectedErr := `could not modify model access: invalid model access permission ""` 606 c.Assert(result.OneError(), gc.ErrorMatches, expectedErr) 607 } 608 609 func (s *modelManagerSuite) TestModifyModelAccessInvalidAction(c *gc.C) { 610 s.setAPIUser(c, s.AdminUserTag(c)) 611 var dance params.ModelAction = "dance" 612 args := params.ModifyModelAccessRequest{ 613 Changes: []params.ModifyModelAccess{{ 614 UserTag: "user-user@local", 615 Action: dance, 616 Access: params.ModelReadAccess, 617 ModelTag: s.State.ModelTag().String(), 618 }}} 619 620 result, err := s.modelmanager.ModifyModelAccess(args) 621 c.Assert(err, jc.ErrorIsNil) 622 expectedErr := `unknown action "dance"` 623 c.Assert(result.OneError(), gc.ErrorMatches, expectedErr) 624 } 625 626 type fakeProvider struct { 627 environs.EnvironProvider 628 } 629 630 func (*fakeProvider) Validate(cfg, old *config.Config) (*config.Config, error) { 631 return cfg, nil 632 } 633 634 func (*fakeProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) { 635 return cfg, nil 636 } 637 638 func init() { 639 environs.RegisterProvider("fake", &fakeProvider{}) 640 }