github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/cloud/cloud_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package cloud_test 5 6 import ( 7 "github.com/juju/errors" 8 gitjujutesting "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/names.v2" 12 13 basetesting "github.com/juju/juju/api/base/testing" 14 cloudapi "github.com/juju/juju/api/cloud" 15 "github.com/juju/juju/apiserver/common" 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/cloud" 18 coretesting "github.com/juju/juju/testing" 19 ) 20 21 type cloudSuite struct { 22 gitjujutesting.IsolationSuite 23 } 24 25 var _ = gc.Suite(&cloudSuite{}) 26 27 func (s *cloudSuite) TestCloud(c *gc.C) { 28 apiCaller := basetesting.APICallerFunc( 29 func(objType string, 30 version int, 31 id, request string, 32 a, result interface{}, 33 ) error { 34 c.Check(objType, gc.Equals, "Cloud") 35 c.Check(id, gc.Equals, "") 36 c.Check(request, gc.Equals, "Cloud") 37 c.Check(a, jc.DeepEquals, params.Entities{ 38 Entities: []params.Entity{{Tag: "cloud-foo"}}, 39 }) 40 c.Assert(result, gc.FitsTypeOf, ¶ms.CloudResults{}) 41 results := result.(*params.CloudResults) 42 results.Results = append(results.Results, params.CloudResult{ 43 Cloud: ¶ms.Cloud{ 44 Type: "dummy", 45 AuthTypes: []string{"empty", "userpass"}, 46 Regions: []params.CloudRegion{{Name: "nether", Endpoint: "endpoint"}}, 47 }, 48 }) 49 return nil 50 }, 51 ) 52 53 client := cloudapi.NewClient(apiCaller) 54 result, err := client.Cloud(names.NewCloudTag("foo")) 55 c.Assert(err, jc.ErrorIsNil) 56 c.Assert(result, jc.DeepEquals, cloud.Cloud{ 57 Name: "foo", 58 Type: "dummy", 59 AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType}, 60 Regions: []cloud.Region{{Name: "nether", Endpoint: "endpoint"}}, 61 }) 62 } 63 64 func (s *cloudSuite) TestClouds(c *gc.C) { 65 apiCaller := basetesting.APICallerFunc( 66 func(objType string, 67 version int, 68 id, request string, 69 a, result_ interface{}, 70 ) error { 71 c.Check(objType, gc.Equals, "Cloud") 72 c.Check(id, gc.Equals, "") 73 c.Check(request, gc.Equals, "Clouds") 74 c.Check(a, gc.IsNil) 75 c.Assert(result_, gc.FitsTypeOf, ¶ms.CloudsResult{}) 76 result := result_.(*params.CloudsResult) 77 result.Clouds = map[string]params.Cloud{ 78 "cloud-foo": { 79 Type: "bar", 80 }, 81 "cloud-baz": { 82 Type: "qux", 83 AuthTypes: []string{"empty", "userpass"}, 84 Regions: []params.CloudRegion{{Name: "nether", Endpoint: "endpoint"}}, 85 }, 86 } 87 return nil 88 }, 89 ) 90 91 client := cloudapi.NewClient(apiCaller) 92 clouds, err := client.Clouds() 93 c.Assert(err, jc.ErrorIsNil) 94 c.Assert(clouds, jc.DeepEquals, map[names.CloudTag]cloud.Cloud{ 95 names.NewCloudTag("foo"): { 96 Name: "foo", 97 Type: "bar", 98 }, 99 names.NewCloudTag("baz"): { 100 Name: "baz", 101 Type: "qux", 102 AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType}, 103 Regions: []cloud.Region{{Name: "nether", Endpoint: "endpoint"}}, 104 }, 105 }) 106 } 107 108 func (s *cloudSuite) TestDefaultCloud(c *gc.C) { 109 apiCaller := basetesting.APICallerFunc( 110 func(objType string, 111 version int, 112 id, request string, 113 a, result interface{}, 114 ) error { 115 c.Check(objType, gc.Equals, "Cloud") 116 c.Check(id, gc.Equals, "") 117 c.Check(request, gc.Equals, "DefaultCloud") 118 c.Assert(result, gc.FitsTypeOf, ¶ms.StringResult{}) 119 results := result.(*params.StringResult) 120 results.Result = "cloud-foo" 121 return nil 122 }, 123 ) 124 125 client := cloudapi.NewClient(apiCaller) 126 result, err := client.DefaultCloud() 127 c.Assert(err, jc.ErrorIsNil) 128 c.Assert(result, jc.DeepEquals, names.NewCloudTag("foo")) 129 } 130 131 func (s *cloudSuite) TestUserCredentials(c *gc.C) { 132 apiCaller := basetesting.APICallerFunc( 133 func(objType string, 134 version int, 135 id, request string, 136 a, result interface{}, 137 ) error { 138 c.Check(objType, gc.Equals, "Cloud") 139 c.Check(id, gc.Equals, "") 140 c.Check(request, gc.Equals, "UserCredentials") 141 c.Assert(result, gc.FitsTypeOf, ¶ms.StringsResults{}) 142 c.Assert(a, jc.DeepEquals, params.UserClouds{UserClouds: []params.UserCloud{{ 143 UserTag: "user-bob", 144 CloudTag: "cloud-foo", 145 }}}) 146 *result.(*params.StringsResults) = params.StringsResults{ 147 Results: []params.StringsResult{{ 148 Result: []string{ 149 "cloudcred-foo_bob_one", 150 "cloudcred-foo_bob_two", 151 }, 152 }}, 153 } 154 return nil 155 }, 156 ) 157 158 client := cloudapi.NewClient(apiCaller) 159 result, err := client.UserCredentials(names.NewUserTag("bob"), names.NewCloudTag("foo")) 160 c.Assert(err, jc.ErrorIsNil) 161 c.Assert(result, jc.SameContents, []names.CloudCredentialTag{ 162 names.NewCloudCredentialTag("foo/bob/one"), 163 names.NewCloudCredentialTag("foo/bob/two"), 164 }) 165 } 166 167 func (s *cloudSuite) TestUpdateCredentialV2(c *gc.C) { 168 var called bool 169 apiCaller := basetesting.BestVersionCaller{ 170 APICallerFunc: basetesting.APICallerFunc( 171 func(objType string, 172 version int, 173 id, request string, 174 a, result interface{}, 175 ) error { 176 c.Check(objType, gc.Equals, "Cloud") 177 c.Check(id, gc.Equals, "") 178 c.Check(request, gc.Equals, "UpdateCredentials") 179 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 180 c.Assert(a, jc.DeepEquals, params.UpdateCredentialArgs{ 181 Credentials: []params.TaggedCredential{{ 182 Tag: "cloudcred-foo_bob_bar", 183 Credential: params.CloudCredential{ 184 AuthType: "userpass", 185 Attributes: map[string]string{ 186 "username": "admin", 187 "password": "adm1n", 188 }, 189 }, 190 }}}) 191 *result.(*params.ErrorResults) = params.ErrorResults{ 192 Results: []params.ErrorResult{{}}, 193 } 194 called = true 195 return nil 196 }, 197 ), 198 BestVersion: 2, 199 } 200 client := cloudapi.NewClient(apiCaller) 201 result, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 202 c.Assert(err, jc.ErrorIsNil) 203 c.Assert(result, gc.IsNil) 204 c.Assert(called, jc.IsTrue) 205 } 206 207 func (s *cloudSuite) TestUpdateCredential(c *gc.C) { 208 var called bool 209 apiCaller := basetesting.BestVersionCaller{ 210 APICallerFunc: basetesting.APICallerFunc( 211 func(objType string, 212 version int, 213 id, request string, 214 a, result interface{}, 215 ) error { 216 c.Check(objType, gc.Equals, "Cloud") 217 c.Check(id, gc.Equals, "") 218 c.Check(request, gc.Equals, "UpdateCredentialsCheckModels") 219 c.Assert(result, gc.FitsTypeOf, ¶ms.UpdateCredentialResults{}) 220 c.Assert(a, jc.DeepEquals, params.UpdateCredentialArgs{ 221 Credentials: []params.TaggedCredential{{ 222 Tag: "cloudcred-foo_bob_bar", 223 Credential: params.CloudCredential{ 224 AuthType: "userpass", 225 Attributes: map[string]string{ 226 "username": "admin", 227 "password": "adm1n", 228 }, 229 }, 230 }}}) 231 *result.(*params.UpdateCredentialResults) = params.UpdateCredentialResults{ 232 Results: []params.UpdateCredentialResult{{}}, 233 } 234 called = true 235 return nil 236 }, 237 ), 238 BestVersion: 3, 239 } 240 client := cloudapi.NewClient(apiCaller) 241 result, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 242 c.Assert(err, jc.ErrorIsNil) 243 c.Assert(result, gc.IsNil) 244 c.Assert(called, jc.IsTrue) 245 } 246 247 func (s *cloudSuite) TestUpdateCredentialErrorV2(c *gc.C) { 248 var called bool 249 apiCaller := basetesting.BestVersionCaller{ 250 APICallerFunc: basetesting.APICallerFunc( 251 func(objType string, 252 version int, 253 id, request string, 254 a, result interface{}, 255 ) error { 256 c.Check(request, gc.Equals, "UpdateCredentials") 257 *result.(*params.ErrorResults) = params.ErrorResults{ 258 Results: []params.ErrorResult{{common.ServerError(errors.New("validation failure"))}}, 259 } 260 called = true 261 return nil 262 }, 263 ), 264 BestVersion: 2, 265 } 266 client := cloudapi.NewClient(apiCaller) 267 errs, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 268 c.Assert(err, gc.ErrorMatches, "validation failure") 269 c.Assert(errs, gc.IsNil) 270 c.Assert(called, jc.IsTrue) 271 } 272 273 func (s *cloudSuite) TestUpdateCredentialError(c *gc.C) { 274 var called bool 275 apiCaller := basetesting.BestVersionCaller{ 276 APICallerFunc: basetesting.APICallerFunc( 277 func(objType string, 278 version int, 279 id, request string, 280 a, result interface{}, 281 ) error { 282 c.Check(request, gc.Equals, "UpdateCredentialsCheckModels") 283 *result.(*params.UpdateCredentialResults) = params.UpdateCredentialResults{ 284 Results: []params.UpdateCredentialResult{ 285 {CredentialTag: "cloudcred-foo_bob_bar", 286 Error: common.ServerError(errors.New("validation failure")), 287 }, 288 }, 289 } 290 called = true 291 return nil 292 }, 293 ), 294 BestVersion: 3, 295 } 296 client := cloudapi.NewClient(apiCaller) 297 errs, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 298 c.Assert(err, gc.ErrorMatches, "validation failure") 299 c.Assert(errs, gc.IsNil) 300 c.Assert(called, jc.IsTrue) 301 } 302 303 func (s *cloudSuite) TestUpdateCredentialCallErrorV2(c *gc.C) { 304 var called bool 305 apiCaller := basetesting.BestVersionCaller{ 306 APICallerFunc: basetesting.APICallerFunc( 307 func(objType string, 308 version int, 309 id, request string, 310 a, result interface{}, 311 ) error { 312 c.Check(request, gc.Equals, "UpdateCredentials") 313 called = true 314 return errors.New("scary but true") 315 }, 316 ), 317 BestVersion: 2, 318 } 319 client := cloudapi.NewClient(apiCaller) 320 result, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 321 c.Assert(err, gc.ErrorMatches, "scary but true") 322 c.Assert(result, gc.IsNil) 323 c.Assert(called, jc.IsTrue) 324 } 325 326 func (s *cloudSuite) TestUpdateCredentialCallError(c *gc.C) { 327 var called bool 328 apiCaller := basetesting.BestVersionCaller{ 329 APICallerFunc: basetesting.APICallerFunc( 330 func(objType string, 331 version int, 332 id, request string, 333 a, result interface{}, 334 ) error { 335 c.Check(request, gc.Equals, "UpdateCredentialsCheckModels") 336 called = true 337 return errors.New("scary but true") 338 }, 339 ), 340 BestVersion: 3, 341 } 342 client := cloudapi.NewClient(apiCaller) 343 result, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 344 c.Assert(err, gc.ErrorMatches, "scary but true") 345 c.Assert(result, gc.IsNil) 346 c.Assert(called, jc.IsTrue) 347 } 348 349 func (s *cloudSuite) TestUpdateCredentialManyResultsV2(c *gc.C) { 350 var called bool 351 apiCaller := basetesting.BestVersionCaller{ 352 APICallerFunc: basetesting.APICallerFunc( 353 func(objType string, 354 version int, 355 id, request string, 356 a, result interface{}, 357 ) error { 358 c.Check(request, gc.Equals, "UpdateCredentials") 359 *result.(*params.ErrorResults) = params.ErrorResults{ 360 Results: []params.ErrorResult{ 361 {}, 362 {}, 363 }, 364 } 365 called = true 366 return nil 367 }, 368 ), 369 BestVersion: 2, 370 } 371 client := cloudapi.NewClient(apiCaller) 372 result, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 373 c.Assert(err, gc.ErrorMatches, `expected 1 result for when updating credential "bar", got 2`) 374 c.Assert(result, gc.IsNil) 375 c.Assert(called, jc.IsTrue) 376 } 377 378 func (s *cloudSuite) TestUpdateCredentialManyResults(c *gc.C) { 379 var called bool 380 apiCaller := basetesting.BestVersionCaller{ 381 APICallerFunc: basetesting.APICallerFunc( 382 func(objType string, 383 version int, 384 id, request string, 385 a, result interface{}, 386 ) error { 387 c.Check(request, gc.Equals, "UpdateCredentialsCheckModels") 388 *result.(*params.UpdateCredentialResults) = params.UpdateCredentialResults{ 389 Results: []params.UpdateCredentialResult{ 390 {}, 391 {}, 392 }} 393 called = true 394 return nil 395 }, 396 ), 397 BestVersion: 3, 398 } 399 client := cloudapi.NewClient(apiCaller) 400 result, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 401 c.Assert(err, gc.ErrorMatches, `expected 1 result for when updating credential "bar", got 2`) 402 c.Assert(result, gc.IsNil) 403 c.Assert(called, jc.IsTrue) 404 } 405 406 func (s *cloudSuite) TestUpdateCredentialModelErrors(c *gc.C) { 407 var called bool 408 apiCaller := basetesting.BestVersionCaller{ 409 APICallerFunc: basetesting.APICallerFunc( 410 func(objType string, 411 version int, 412 id, request string, 413 a, result interface{}, 414 ) error { 415 c.Check(request, gc.Equals, "UpdateCredentialsCheckModels") 416 *result.(*params.UpdateCredentialResults) = params.UpdateCredentialResults{ 417 Results: []params.UpdateCredentialResult{ 418 { 419 CredentialTag: testCredentialTag.String(), 420 Models: []params.UpdateCredentialModelResult{ 421 { 422 ModelUUID: coretesting.ModelTag.Id(), 423 ModelName: "test-model", 424 Errors: []params.ErrorResult{ 425 {common.ServerError(errors.New("validation failure one"))}, 426 {common.ServerError(errors.New("validation failure two"))}, 427 }, 428 }, 429 }, 430 }, 431 }} 432 called = true 433 return nil 434 }, 435 ), 436 BestVersion: 3, 437 } 438 client := cloudapi.NewClient(apiCaller) 439 errs, err := client.UpdateCredentialsCheckModels(testCredentialTag, testCredential) 440 c.Assert(err, jc.ErrorIsNil) 441 c.Assert(errs, gc.DeepEquals, []params.UpdateCredentialModelResult{ 442 { 443 ModelUUID: "deadbeef-0bad-400d-8000-4b1d0d06f00d", 444 ModelName: "test-model", 445 Errors: []params.ErrorResult{ 446 {Error: ¶ms.Error{Message: "validation failure one", Code: ""}}, 447 {Error: ¶ms.Error{Message: "validation failure two", Code: ""}}, 448 }, 449 }, 450 }) 451 c.Assert(called, jc.IsTrue) 452 } 453 454 var ( 455 testCredentialTag = names.NewCloudCredentialTag("foo/bob/bar") 456 testCredential = cloud.NewCredential(cloud.UserPassAuthType, map[string]string{ 457 "username": "admin", 458 "password": "adm1n", 459 }) 460 ) 461 462 func (s *cloudSuite) TestRevokeCredential(c *gc.C) { 463 var called bool 464 apiCallerF := basetesting.APICallerFunc( 465 func(objType string, 466 version int, 467 id, request string, 468 a, result interface{}, 469 ) error { 470 c.Check(objType, gc.Equals, "Cloud") 471 c.Check(id, gc.Equals, "") 472 c.Check(request, gc.Equals, "RevokeCredentialsCheckModels") 473 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 474 c.Assert(a, jc.DeepEquals, params.RevokeCredentialArgs{ 475 Credentials: []params.RevokeCredentialArg{ 476 {Tag: "cloudcred-foo_bob_bar"}, 477 }, 478 }) 479 *result.(*params.ErrorResults) = params.ErrorResults{ 480 Results: []params.ErrorResult{{}}, 481 } 482 called = true 483 return nil 484 }, 485 ) 486 apiCaller := basetesting.BestVersionCaller{ 487 APICallerFunc: apiCallerF, 488 BestVersion: 3, 489 } 490 491 client := cloudapi.NewClient(apiCaller) 492 tag := names.NewCloudCredentialTag("foo/bob/bar") 493 err := client.RevokeCredential(tag) 494 c.Assert(err, jc.ErrorIsNil) 495 c.Assert(called, jc.IsTrue) 496 } 497 498 func (s *cloudSuite) TestRevokeCredentialV2(c *gc.C) { 499 var called bool 500 apiCallerF := basetesting.APICallerFunc( 501 func(objType string, 502 version int, 503 id, request string, 504 a, result interface{}, 505 ) error { 506 c.Check(objType, gc.Equals, "Cloud") 507 c.Check(id, gc.Equals, "") 508 c.Check(request, gc.Equals, "RevokeCredentials") 509 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 510 c.Assert(a, jc.DeepEquals, params.Entities{Entities: []params.Entity{{ 511 Tag: "cloudcred-foo_bob_bar", 512 }}}) 513 *result.(*params.ErrorResults) = params.ErrorResults{ 514 Results: []params.ErrorResult{{}}, 515 } 516 called = true 517 return nil 518 }, 519 ) 520 apiCaller := basetesting.BestVersionCaller{ 521 APICallerFunc: apiCallerF, 522 BestVersion: 2, 523 } 524 525 client := cloudapi.NewClient(apiCaller) 526 tag := names.NewCloudCredentialTag("foo/bob/bar") 527 err := client.RevokeCredential(tag) 528 c.Assert(err, jc.ErrorIsNil) 529 c.Assert(called, jc.IsTrue) 530 } 531 532 func (s *cloudSuite) TestCredentials(c *gc.C) { 533 apiCaller := basetesting.APICallerFunc( 534 func(objType string, 535 version int, 536 id, request string, 537 a, result interface{}, 538 ) error { 539 c.Check(objType, gc.Equals, "Cloud") 540 c.Check(id, gc.Equals, "") 541 c.Check(request, gc.Equals, "Credential") 542 c.Assert(result, gc.FitsTypeOf, ¶ms.CloudCredentialResults{}) 543 c.Assert(a, jc.DeepEquals, params.Entities{Entities: []params.Entity{{ 544 Tag: "cloudcred-foo_bob_bar", 545 }}}) 546 *result.(*params.CloudCredentialResults) = params.CloudCredentialResults{ 547 Results: []params.CloudCredentialResult{ 548 { 549 Result: ¶ms.CloudCredential{ 550 AuthType: "userpass", 551 Attributes: map[string]string{"username": "fred"}, 552 Redacted: []string{"password"}, 553 }, 554 }, { 555 Result: ¶ms.CloudCredential{ 556 AuthType: "userpass", 557 Attributes: map[string]string{"username": "mary"}, 558 Redacted: []string{"password"}, 559 }, 560 }, 561 }, 562 } 563 return nil 564 }, 565 ) 566 567 client := cloudapi.NewClient(apiCaller) 568 tag := names.NewCloudCredentialTag("foo/bob/bar") 569 result, err := client.Credentials(tag) 570 c.Assert(err, jc.ErrorIsNil) 571 c.Assert(result, jc.DeepEquals, []params.CloudCredentialResult{ 572 { 573 Result: ¶ms.CloudCredential{ 574 AuthType: "userpass", 575 Attributes: map[string]string{"username": "fred"}, 576 Redacted: []string{"password"}, 577 }, 578 }, { 579 Result: ¶ms.CloudCredential{ 580 AuthType: "userpass", 581 Attributes: map[string]string{"username": "mary"}, 582 Redacted: []string{"password"}, 583 }, 584 }, 585 }) 586 } 587 588 func (s *cloudSuite) TestAddCloudNotInV1API(c *gc.C) { 589 apiCaller := basetesting.BestVersionCaller{ 590 APICallerFunc: basetesting.APICallerFunc( 591 func(objType string, 592 version int, 593 id, request string, 594 a, result interface{}, 595 ) error { 596 c.Check(objType, gc.Equals, "Cloud") 597 c.Check(id, gc.Equals, "") 598 c.Check(request, gc.Equals, "AddCloud") 599 return nil 600 }, 601 ), 602 BestVersion: 1, 603 } 604 client := cloudapi.NewClient(apiCaller) 605 err := client.AddCloud(cloud.Cloud{ 606 Name: "foo", 607 Type: "dummy", 608 AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType}, 609 Regions: []cloud.Region{{Name: "nether", Endpoint: "endpoint"}}, 610 }) 611 612 c.Assert(err, gc.ErrorMatches, "AddCloud\\(\\).* not implemented") 613 } 614 615 func (s *cloudSuite) TestAddCloudV2API(c *gc.C) { 616 var called bool 617 apiCaller := basetesting.BestVersionCaller{ 618 APICallerFunc: basetesting.APICallerFunc( 619 func(objType string, 620 version int, 621 id, request string, 622 a, result interface{}, 623 ) error { 624 called = true 625 c.Check(objType, gc.Equals, "Cloud") 626 c.Check(id, gc.Equals, "") 627 c.Check(request, gc.Equals, "AddCloud") 628 return nil 629 }, 630 ), 631 BestVersion: 2, 632 } 633 634 client := cloudapi.NewClient(apiCaller) 635 err := client.AddCloud(cloud.Cloud{ 636 Name: "foo", 637 Type: "dummy", 638 AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType}, 639 Regions: []cloud.Region{{Name: "nether", Endpoint: "endpoint"}}, 640 }) 641 642 c.Assert(err, jc.ErrorIsNil) 643 c.Assert(called, jc.IsTrue) 644 } 645 646 func (s *cloudSuite) TestAddCredentialNotInV1API(c *gc.C) { 647 apiCaller := basetesting.BestVersionCaller{ 648 APICallerFunc: basetesting.APICallerFunc( 649 func(objType string, 650 version int, 651 id, request string, 652 a, result interface{}, 653 ) error { 654 return nil 655 }, 656 ), 657 BestVersion: 1, 658 } 659 client := cloudapi.NewClient(apiCaller) 660 err := client.AddCredential("cloudcred-acloud-user-credname", 661 cloud.NewCredential(cloud.UserPassAuthType, map[string]string{})) 662 663 c.Assert(err, gc.ErrorMatches, "AddCredential\\(\\).* not implemented") 664 } 665 666 func (s *cloudSuite) TestAddCredentialV2API(c *gc.C) { 667 var called bool 668 apiCaller := basetesting.BestVersionCaller{ 669 APICallerFunc: basetesting.APICallerFunc( 670 func(objType string, 671 version int, 672 id, request string, 673 a, result interface{}, 674 ) error { 675 called = true 676 c.Check(objType, gc.Equals, "Cloud") 677 c.Check(id, gc.Equals, "") 678 c.Check(request, gc.Equals, "AddCredentials") 679 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 680 *result.(*params.ErrorResults) = params.ErrorResults{ 681 Results: []params.ErrorResult{{}}, 682 } 683 684 return nil 685 }, 686 ), 687 BestVersion: 2, 688 } 689 690 client := cloudapi.NewClient(apiCaller) 691 err := client.AddCredential("cloudcred-acloud-user-credname", 692 cloud.NewCredential(cloud.UserPassAuthType, 693 map[string]string{})) 694 695 c.Assert(err, jc.ErrorIsNil) 696 c.Assert(called, jc.IsTrue) 697 } 698 699 func (s *cloudSuite) TestCredentialContentsArgumentCheck(c *gc.C) { 700 apiCaller := basetesting.BestVersionCaller{BestVersion: 2} 701 client := cloudapi.NewClient(apiCaller) 702 703 // Check supplying cloud name without credential name is invalid. 704 result, err := client.CredentialContents("cloud", "", true) 705 c.Assert(result, gc.IsNil) 706 c.Assert(err, gc.ErrorMatches, "credential name must be supplied") 707 708 // Check supplying credential name without cloud name is invalid. 709 result, err = client.CredentialContents("", "credential", true) 710 c.Assert(result, gc.IsNil) 711 c.Assert(err, gc.ErrorMatches, "cloud name must be supplied") 712 } 713 714 func (s *cloudSuite) TestCredentialContentsAll(c *gc.C) { 715 expectedResults := []params.CredentialContentResult{ 716 { 717 Result: ¶ms.ControllerCredentialInfo{ 718 Content: params.CredentialContent{ 719 Cloud: "cloud-name", 720 Name: "credential-name", 721 AuthType: "userpass", 722 Attributes: map[string]string{ 723 "username": "fred", 724 "password": "sekret"}, 725 }, 726 Models: []params.ModelAccess{ 727 {Model: "abcmodel", Access: "admin"}, 728 {Model: "xyzmodel", Access: "read"}, 729 {Model: "no-access-model"}, // no access 730 }, 731 }, 732 }, { 733 Error: common.ServerError(errors.New("boom")), 734 }, 735 } 736 apiCaller := basetesting.BestVersionCaller{ 737 APICallerFunc: basetesting.APICallerFunc( 738 func(objType string, 739 version int, 740 id, request string, 741 a, result interface{}, 742 ) error { 743 c.Check(objType, gc.Equals, "Cloud") 744 c.Check(id, gc.Equals, "") 745 c.Check(request, gc.Equals, "CredentialContents") 746 c.Assert(result, gc.FitsTypeOf, ¶ms.CredentialContentResults{}) 747 c.Assert(a, jc.DeepEquals, params.CloudCredentialArgs{ 748 IncludeSecrets: true, 749 }) 750 *result.(*params.CredentialContentResults) = params.CredentialContentResults{ 751 Results: expectedResults, 752 } 753 return nil 754 }, 755 ), 756 BestVersion: 2, 757 } 758 759 client := cloudapi.NewClient(apiCaller) 760 results, err := client.CredentialContents("", "", true) 761 c.Assert(err, jc.ErrorIsNil) 762 c.Assert(results, jc.DeepEquals, expectedResults) 763 } 764 765 func (s *cloudSuite) TestCredentialContentsOne(c *gc.C) { 766 apiCaller := basetesting.BestVersionCaller{ 767 APICallerFunc: basetesting.APICallerFunc( 768 func(objType string, 769 version int, 770 id, request string, 771 a, result interface{}, 772 ) error { 773 c.Check(objType, gc.Equals, "Cloud") 774 c.Check(id, gc.Equals, "") 775 c.Check(request, gc.Equals, "CredentialContents") 776 c.Assert(result, gc.FitsTypeOf, ¶ms.CredentialContentResults{}) 777 c.Assert(a, jc.DeepEquals, params.CloudCredentialArgs{ 778 IncludeSecrets: true, 779 Credentials: []params.CloudCredentialArg{ 780 {CloudName: "cloud-name", CredentialName: "credential-name"}, 781 }, 782 }) 783 *result.(*params.CredentialContentResults) = params.CredentialContentResults{ 784 Results: []params.CredentialContentResult{ 785 {}, 786 }, 787 } 788 return nil 789 }, 790 ), 791 BestVersion: 2, 792 } 793 794 client := cloudapi.NewClient(apiCaller) 795 results, err := client.CredentialContents("cloud-name", "credential-name", true) 796 c.Assert(err, jc.ErrorIsNil) 797 c.Assert(results, gc.HasLen, 1) 798 } 799 800 func (s *cloudSuite) TestCredentialContentsGotMoreThanBargainedFor(c *gc.C) { 801 apiCaller := basetesting.BestVersionCaller{ 802 APICallerFunc: basetesting.APICallerFunc( 803 func(objType string, 804 version int, 805 id, request string, 806 a, result interface{}, 807 ) error { 808 *result.(*params.CredentialContentResults) = params.CredentialContentResults{ 809 Results: []params.CredentialContentResult{ 810 {}, 811 {}, 812 }, 813 } 814 return nil 815 }, 816 ), 817 BestVersion: 2, 818 } 819 820 client := cloudapi.NewClient(apiCaller) 821 results, err := client.CredentialContents("cloud-name", "credential-name", true) 822 c.Assert(results, gc.IsNil) 823 c.Assert(err, gc.ErrorMatches, "expected 1 result for credential \"cloud-name\" on cloud \"credential-name\", got 2") 824 } 825 826 func (s *cloudSuite) TestCredentialContentsServerError(c *gc.C) { 827 apiCaller := basetesting.BestVersionCaller{ 828 APICallerFunc: basetesting.APICallerFunc( 829 func(objType string, 830 version int, 831 id, request string, 832 a, result interface{}, 833 ) error { 834 return errors.New("boom") 835 }), 836 BestVersion: 2, 837 } 838 839 client := cloudapi.NewClient(apiCaller) 840 results, err := client.CredentialContents("", "", true) 841 c.Assert(results, gc.IsNil) 842 c.Assert(err, gc.ErrorMatches, "boom") 843 } 844 845 func (s *cloudSuite) TestCredentialContentsNotInV2API(c *gc.C) { 846 apiCaller := basetesting.BestVersionCaller{ 847 APICallerFunc: basetesting.APICallerFunc( 848 func(objType string, 849 version int, 850 id, request string, 851 a, result interface{}, 852 ) error { 853 return nil 854 }, 855 ), 856 BestVersion: 1, 857 } 858 client := cloudapi.NewClient(apiCaller) 859 _, err := client.CredentialContents("", "", true) 860 c.Assert(err, gc.ErrorMatches, "CredentialContents\\(\\).* not implemented") 861 } 862 863 func (s *cloudSuite) TestRemoveCloud(c *gc.C) { 864 var called bool 865 apiCaller := basetesting.BestVersionCaller{ 866 APICallerFunc: basetesting.APICallerFunc( 867 func(objType string, 868 version int, 869 id, request string, 870 a, result interface{}, 871 ) error { 872 called = true 873 c.Check(objType, gc.Equals, "Cloud") 874 c.Check(id, gc.Equals, "") 875 c.Check(request, gc.Equals, "RemoveClouds") 876 c.Check(a, jc.DeepEquals, params.Entities{ 877 Entities: []params.Entity{{Tag: "cloud-foo"}}, 878 }) 879 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 880 results := result.(*params.ErrorResults) 881 results.Results = append(results.Results, params.ErrorResult{ 882 Error: ¶ms.Error{Message: "FAIL"}, 883 }) 884 return nil 885 }, 886 ), 887 BestVersion: 2, 888 } 889 890 client := cloudapi.NewClient(apiCaller) 891 err := client.RemoveCloud("foo") 892 c.Assert(err, gc.ErrorMatches, "FAIL") 893 c.Assert(called, jc.IsTrue) 894 } 895 896 func (s *cloudSuite) TestRemoveCloudNotInV1API(c *gc.C) { 897 apiCaller := basetesting.BestVersionCaller{ 898 APICallerFunc: basetesting.APICallerFunc( 899 func(objType string, 900 version int, 901 id, request string, 902 a, result interface{}, 903 ) error { 904 c.Check(objType, gc.Equals, "Cloud") 905 c.Check(id, gc.Equals, "") 906 c.Check(request, gc.Equals, "RemoveCloud") 907 return nil 908 }, 909 ), 910 BestVersion: 1, 911 } 912 client := cloudapi.NewClient(apiCaller) 913 err := client.RemoveCloud("foo") 914 915 c.Assert(err, gc.ErrorMatches, "RemoveCloud\\(\\).* not implemented") 916 } 917 918 func (s *cloudSuite) TestGrantCloud(c *gc.C) { 919 var called bool 920 apiCaller := basetesting.BestVersionCaller{ 921 APICallerFunc: basetesting.APICallerFunc( 922 func(objType string, 923 version int, 924 id, request string, 925 a, result interface{}, 926 ) error { 927 called = true 928 c.Check(objType, gc.Equals, "Cloud") 929 c.Check(id, gc.Equals, "") 930 c.Check(request, gc.Equals, "ModifyCloudAccess") 931 c.Check(a, jc.DeepEquals, params.ModifyCloudAccessRequest{ 932 Changes: []params.ModifyCloudAccess{ 933 {UserTag: "user-fred", CloudTag: "cloud-fluffy", Action: "grant", Access: "admin"}, 934 }, 935 }) 936 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 937 results := result.(*params.ErrorResults) 938 results.Results = append(results.Results, params.ErrorResult{ 939 Error: ¶ms.Error{Message: "FAIL"}, 940 }) 941 return nil 942 }, 943 ), 944 BestVersion: 3, 945 } 946 947 client := cloudapi.NewClient(apiCaller) 948 err := client.GrantCloud("fred", "admin", "fluffy") 949 c.Assert(err, gc.ErrorMatches, "FAIL") 950 c.Assert(called, jc.IsTrue) 951 } 952 953 func (s *cloudSuite) TestGrantCloudAccessNotInV2API(c *gc.C) { 954 apiCaller := basetesting.BestVersionCaller{ 955 APICallerFunc: basetesting.APICallerFunc( 956 func(objType string, 957 version int, 958 id, request string, 959 a, result interface{}, 960 ) error { 961 c.Fail() 962 return nil 963 }, 964 ), 965 BestVersion: 2, 966 } 967 client := cloudapi.NewClient(apiCaller) 968 err := client.GrantCloud("foo", "admin", "fluffy") 969 c.Assert(err, gc.ErrorMatches, "GrantCloud\\(\\).* not implemented") 970 } 971 972 func (s *cloudSuite) TestRevokeCloud(c *gc.C) { 973 var called bool 974 apiCaller := basetesting.BestVersionCaller{ 975 APICallerFunc: basetesting.APICallerFunc( 976 func(objType string, 977 version int, 978 id, request string, 979 a, result interface{}, 980 ) error { 981 called = true 982 c.Check(objType, gc.Equals, "Cloud") 983 c.Check(id, gc.Equals, "") 984 c.Check(request, gc.Equals, "ModifyCloudAccess") 985 c.Check(a, jc.DeepEquals, params.ModifyCloudAccessRequest{ 986 Changes: []params.ModifyCloudAccess{ 987 {UserTag: "user-fred", CloudTag: "cloud-fluffy", Action: "revoke", Access: "admin"}, 988 }, 989 }) 990 c.Assert(result, gc.FitsTypeOf, ¶ms.ErrorResults{}) 991 results := result.(*params.ErrorResults) 992 results.Results = append(results.Results, params.ErrorResult{ 993 Error: ¶ms.Error{Message: "FAIL"}, 994 }) 995 return nil 996 }, 997 ), 998 BestVersion: 3, 999 } 1000 1001 client := cloudapi.NewClient(apiCaller) 1002 err := client.RevokeCloud("fred", "admin", "fluffy") 1003 c.Assert(err, gc.ErrorMatches, "FAIL") 1004 c.Assert(called, jc.IsTrue) 1005 } 1006 1007 func (s *cloudSuite) TestRevokeCloudAccessNotInV2API(c *gc.C) { 1008 apiCaller := basetesting.BestVersionCaller{ 1009 APICallerFunc: basetesting.APICallerFunc( 1010 func(objType string, 1011 version int, 1012 id, request string, 1013 a, result interface{}, 1014 ) error { 1015 c.Fail() 1016 return nil 1017 }, 1018 ), 1019 BestVersion: 2, 1020 } 1021 client := cloudapi.NewClient(apiCaller) 1022 err := client.RevokeCloud("foo", "admin", "fluffy") 1023 c.Assert(err, gc.ErrorMatches, "RevokeCloud\\(\\).* not implemented") 1024 }