github.com/arunkumar7540/cli@v6.45.0+incompatible/api/cloudcontroller/ccv3/domain_test.go (about) 1 package ccv3_test 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 8 "code.cloudfoundry.org/cli/types" 9 10 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 . "github.com/onsi/gomega/ghttp" 14 ) 15 16 var _ = Describe("Domain", func() { 17 var client *Client 18 19 BeforeEach(func() { 20 client, _ = NewTestClient() 21 }) 22 23 Describe("CreateDomain for Shared Domains", func() { 24 var ( 25 domain Domain 26 warnings Warnings 27 executeErr error 28 ) 29 30 JustBeforeEach(func() { 31 domain, warnings, executeErr = client.CreateDomain(Domain{Name: "some-name", Internal: types.NullBool{IsSet: true, Value: true}}) 32 }) 33 34 When("the request succeeds", func() { 35 BeforeEach(func() { 36 response := `{ 37 "guid": "some-guid", 38 "name": "some-name", 39 "internal": true 40 }` 41 42 expectedBody := `{ 43 "name": "some-name", 44 "internal": true 45 }` 46 47 server.AppendHandlers( 48 CombineHandlers( 49 VerifyRequest(http.MethodPost, "/v3/domains"), 50 VerifyJSON(expectedBody), 51 RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 52 ), 53 ) 54 }) 55 56 It("returns the given domain and all warnings", func() { 57 Expect(executeErr).ToNot(HaveOccurred()) 58 Expect(warnings).To(ConsistOf("warning-1")) 59 60 Expect(domain).To(Equal(Domain{ 61 GUID: "some-guid", 62 Name: "some-name", 63 Internal: types.NullBool{IsSet: true, Value: true}, 64 })) 65 }) 66 }) 67 68 When("the cloud controller returns errors and warnings", func() { 69 BeforeEach(func() { 70 response := `{ 71 "errors": [ 72 { 73 "code": 10008, 74 "detail": "The request is semantically invalid: command presence", 75 "title": "CF-UnprocessableEntity" 76 }, 77 { 78 "code": 10010, 79 "detail": "Isolation segment not found", 80 "title": "CF-ResourceNotFound" 81 } 82 ] 83 }` 84 server.AppendHandlers( 85 CombineHandlers( 86 VerifyRequest(http.MethodPost, "/v3/domains"), 87 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 88 ), 89 ) 90 }) 91 92 It("returns the error and all warnings", func() { 93 Expect(executeErr).To(MatchError(ccerror.MultiError{ 94 ResponseCode: http.StatusTeapot, 95 Errors: []ccerror.V3Error{ 96 { 97 Code: 10008, 98 Detail: "The request is semantically invalid: command presence", 99 Title: "CF-UnprocessableEntity", 100 }, 101 { 102 Code: 10010, 103 Detail: "Isolation segment not found", 104 Title: "CF-ResourceNotFound", 105 }, 106 }, 107 })) 108 Expect(warnings).To(ConsistOf("this is a warning")) 109 }) 110 }) 111 }) 112 113 Describe("CreateDomain for Private Domains", func() { 114 var ( 115 domain Domain 116 warnings Warnings 117 executeErr error 118 ) 119 120 JustBeforeEach(func() { 121 domain, warnings, executeErr = client.CreateDomain(Domain{Name: "some-name", Internal: types.NullBool{IsSet: false, Value: true}, OrganizationGUID: "organization-guid"}) 122 }) 123 124 When("the request succeeds", func() { 125 BeforeEach(func() { 126 response := `{ 127 "guid": "some-guid", 128 "name": "some-name", 129 "relationships": { 130 "organization": { 131 "data" : { 132 "guid" : "organization-guid" 133 } 134 } 135 }, 136 "internal": false 137 }` 138 139 expectedRequestBody := `{ 140 "name": "some-name", 141 "relationships": { 142 "organization": { 143 "data" : { 144 "guid" : "organization-guid" 145 } 146 } 147 } 148 }` 149 150 server.AppendHandlers( 151 CombineHandlers( 152 VerifyRequest(http.MethodPost, "/v3/domains"), 153 VerifyJSON(expectedRequestBody), 154 RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 155 ), 156 ) 157 }) 158 159 It("returns the given domain and all warnings", func() { 160 Expect(executeErr).ToNot(HaveOccurred()) 161 Expect(warnings).To(ConsistOf("warning-1")) 162 163 Expect(domain).To(Equal(Domain{ 164 GUID: "some-guid", 165 Name: "some-name", 166 OrganizationGUID: "organization-guid", 167 Internal: types.NullBool{IsSet: true, Value: false}, 168 })) 169 }) 170 }) 171 172 When("the cloud controller returns errors and warnings", func() { 173 BeforeEach(func() { 174 response := `{ 175 "errors": [ 176 { 177 "code": 10008, 178 "detail": "The request is semantically invalid: command presence", 179 "title": "CF-UnprocessableEntity" 180 }, 181 { 182 "code": 10010, 183 "detail": "Isolation segment not found", 184 "title": "CF-ResourceNotFound" 185 } 186 ] 187 }` 188 server.AppendHandlers( 189 CombineHandlers( 190 VerifyRequest(http.MethodPost, "/v3/domains"), 191 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 192 ), 193 ) 194 }) 195 196 It("returns the error and all warnings", func() { 197 Expect(executeErr).To(MatchError(ccerror.MultiError{ 198 ResponseCode: http.StatusTeapot, 199 Errors: []ccerror.V3Error{ 200 { 201 Code: 10008, 202 Detail: "The request is semantically invalid: command presence", 203 Title: "CF-UnprocessableEntity", 204 }, 205 { 206 Code: 10010, 207 Detail: "Isolation segment not found", 208 Title: "CF-ResourceNotFound", 209 }, 210 }, 211 })) 212 Expect(warnings).To(ConsistOf("this is a warning")) 213 }) 214 }) 215 }) 216 217 Describe("DeleteDomain", func() { 218 var ( 219 domainGUID string 220 jobURLString string 221 jobURL JobURL 222 warnings Warnings 223 executeErr error 224 ) 225 226 JustBeforeEach(func() { 227 jobURL, warnings, executeErr = client.DeleteDomain(domainGUID) 228 }) 229 230 When("domain exists", func() { 231 domainGUID = "domain-guid" 232 jobURLString = "https://api.test.com/v3/jobs/job-guid" 233 234 BeforeEach(func() { 235 server.AppendHandlers( 236 CombineHandlers( 237 VerifyRequest(http.MethodDelete, "/v3/domains/domain-guid"), 238 RespondWith(http.StatusAccepted, nil, http.Header{ 239 "X-Cf-Warnings": {"this is a warning"}, 240 "Location": {jobURLString}, 241 }), 242 ), 243 ) 244 }) 245 246 It("returns all warnings", func() { 247 Expect(executeErr).NotTo(HaveOccurred()) 248 Expect(jobURL).To(Equal(JobURL(jobURLString))) 249 Expect(warnings).To(ConsistOf("this is a warning")) 250 }) 251 }) 252 253 When("the cloud controller returns errors and warnings", func() { 254 BeforeEach(func() { 255 response := `{ 256 "errors": [ 257 { 258 "code": 10008, 259 "detail": "The request is semantically invalid: command presence", 260 "title": "CF-UnprocessableEntity" 261 }, 262 { 263 "code": 10010, 264 "detail": "Isolation segment not found", 265 "title": "CF-ResourceNotFound" 266 } 267 ] 268 }` 269 server.AppendHandlers( 270 CombineHandlers( 271 VerifyRequest(http.MethodDelete, "/v3/domains/domain-guid"), 272 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 273 ), 274 ) 275 }) 276 277 It("returns the error and all warnings", func() { 278 Expect(executeErr).To(MatchError(ccerror.MultiError{ 279 ResponseCode: http.StatusTeapot, 280 Errors: []ccerror.V3Error{ 281 { 282 Code: 10008, 283 Detail: "The request is semantically invalid: command presence", 284 Title: "CF-UnprocessableEntity", 285 }, 286 { 287 Code: 10010, 288 Detail: "Isolation segment not found", 289 Title: "CF-ResourceNotFound", 290 }, 291 }, 292 })) 293 Expect(warnings).To(ConsistOf("this is a warning")) 294 }) 295 }) 296 }) 297 298 Describe("GetDomains", func() { 299 var ( 300 query Query 301 domains []Domain 302 warnings Warnings 303 executeErr error 304 ) 305 306 JustBeforeEach(func() { 307 domains, warnings, executeErr = client.GetDomains(query) 308 }) 309 310 When("domains exist", func() { 311 BeforeEach(func() { 312 response1 := fmt.Sprintf(`{ 313 "pagination": { 314 "next": { 315 "href": "%s/v3/domains?page=2&per_page=2" 316 } 317 }, 318 "resources": [ 319 { 320 "name": "domain-name-1", 321 "guid": "domain-guid-1", 322 "relationships": { 323 "organization": { 324 "data": { 325 "guid": "owning-org-1" 326 } 327 } 328 } 329 }, 330 { 331 "name": "domain-name-2", 332 "guid": "domain-guid-2", 333 "relationships": { 334 "organization": { 335 "data": { 336 "guid": "owning-org-2" 337 } 338 } 339 } 340 } 341 ] 342 }`, server.URL()) 343 response2 := `{ 344 "pagination": { 345 "next": null 346 }, 347 "resources": [ 348 { 349 "name": "domain-name-3", 350 "guid": "domain-guid-3", 351 "relationships": { 352 "organization": { 353 "data": { 354 "guid": "owning-org-3" 355 } 356 } 357 } 358 } 359 ] 360 }` 361 362 server.AppendHandlers( 363 CombineHandlers( 364 VerifyRequest(http.MethodGet, "/v3/domains"), 365 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 366 ), 367 ) 368 server.AppendHandlers( 369 CombineHandlers( 370 VerifyRequest(http.MethodGet, "/v3/domains", "page=2&per_page=2"), 371 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 372 ), 373 ) 374 375 query = Query{} 376 }) 377 378 It("returns the queried domain and all warnings", func() { 379 Expect(executeErr).NotTo(HaveOccurred()) 380 381 Expect(domains).To(ConsistOf( 382 Domain{Name: "domain-name-1", GUID: "domain-guid-1", OrganizationGUID: "owning-org-1"}, 383 Domain{Name: "domain-name-2", GUID: "domain-guid-2", OrganizationGUID: "owning-org-2"}, 384 Domain{Name: "domain-name-3", GUID: "domain-guid-3", OrganizationGUID: "owning-org-3"}, 385 )) 386 Expect(warnings).To(ConsistOf("this is a warning", "this is another warning")) 387 }) 388 }) 389 390 When("the cloud controller returns errors and warnings", func() { 391 BeforeEach(func() { 392 response := `{ 393 "errors": [ 394 { 395 "code": 10008, 396 "detail": "The request is semantically invalid: command presence", 397 "title": "CF-UnprocessableEntity" 398 }, 399 { 400 "code": 10010, 401 "detail": "Isolation segment not found", 402 "title": "CF-ResourceNotFound" 403 } 404 ] 405 }` 406 server.AppendHandlers( 407 CombineHandlers( 408 VerifyRequest(http.MethodGet, "/v3/domains"), 409 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 410 ), 411 ) 412 }) 413 414 It("returns the error and all warnings", func() { 415 Expect(executeErr).To(MatchError(ccerror.MultiError{ 416 ResponseCode: http.StatusTeapot, 417 Errors: []ccerror.V3Error{ 418 { 419 Code: 10008, 420 Detail: "The request is semantically invalid: command presence", 421 Title: "CF-UnprocessableEntity", 422 }, 423 { 424 Code: 10010, 425 Detail: "Isolation segment not found", 426 Title: "CF-ResourceNotFound", 427 }, 428 }, 429 })) 430 Expect(warnings).To(ConsistOf("this is a warning")) 431 }) 432 }) 433 }) 434 435 Describe("GetDomain", func() { 436 437 var ( 438 domainGUID string 439 domain Domain 440 warnings Warnings 441 executeErr error 442 ) 443 JustBeforeEach(func() { 444 domainGUID = "domain-guid-1" 445 domain, warnings, executeErr = client.GetDomain(domainGUID) 446 }) 447 448 When("domain is found", func() { 449 BeforeEach(func() { 450 response := `{ 451 "name": "domain-name-1", 452 "guid": "domain-guid-1" 453 }` 454 server.AppendHandlers( 455 CombineHandlers( 456 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid-1"), 457 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 458 ), 459 ) 460 }) 461 462 It("returns a domain and prints all warnings", func() { 463 Expect(executeErr).To(Not(HaveOccurred())) 464 465 Expect(domain).To(Equal(Domain{ 466 Name: "domain-name-1", 467 GUID: "domain-guid-1", 468 })) 469 470 Expect(warnings).To(ConsistOf("this is a warning")) 471 }) 472 }) 473 474 When("cloud controller returns an error", func() { 475 BeforeEach(func() { 476 response := `{ 477 "errors": [ 478 { 479 "code": 10008, 480 "detail": "The request is semantically invalid: command presence", 481 "title": "CF-UnprocessableEntity" 482 }, 483 { 484 "code": 10010, 485 "detail": "Domain not found", 486 "title": "CF-ResourceNotFound" 487 } 488 ] 489 }` 490 server.AppendHandlers( 491 CombineHandlers( 492 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid-1"), 493 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 494 ), 495 ) 496 }) 497 498 It("returns the error and all warnings", func() { 499 Expect(executeErr).To(MatchError(ccerror.MultiError{ 500 ResponseCode: http.StatusTeapot, 501 Errors: []ccerror.V3Error{ 502 { 503 Code: 10008, 504 Detail: "The request is semantically invalid: command presence", 505 Title: "CF-UnprocessableEntity", 506 }, 507 { 508 Code: 10010, 509 Detail: "Domain not found", 510 Title: "CF-ResourceNotFound", 511 }, 512 }, 513 })) 514 Expect(warnings).To(ConsistOf("this is a warning")) 515 }) 516 }) 517 }) 518 519 Describe("GetOrganizationDomains", func() { 520 var ( 521 orgGUID string 522 query Query 523 domains []Domain 524 warnings Warnings 525 executeErr error 526 ) 527 528 BeforeEach(func() { 529 orgGUID = "some-org-guid" 530 }) 531 532 JustBeforeEach(func() { 533 domains, warnings, executeErr = client.GetOrganizationDomains(orgGUID, query) 534 }) 535 536 When("domains exist", func() { 537 BeforeEach(func() { 538 response1 := fmt.Sprintf(`{ 539 "pagination": { 540 "next": { 541 "href": "%s/v3/organizations/some-org-guid/domains?organization_guids=some-org-guid&page=2&per_page=2" 542 } 543 }, 544 "resources": [ 545 { 546 "name": "domain-name-1", 547 "guid": "domain-guid-1", 548 "relationships": { 549 "organization": { 550 "data": { 551 "guid": "some-org-guid" 552 } 553 } 554 } 555 }, 556 { 557 "name": "domain-name-2", 558 "guid": "domain-guid-2", 559 "relationships": { 560 "organization": { 561 "data": { 562 "guid": "some-org-guid" 563 } 564 } 565 } 566 } 567 ] 568 }`, server.URL()) 569 response2 := `{ 570 "pagination": { 571 "next": null 572 }, 573 "resources": [ 574 { 575 "name": "domain-name-3", 576 "guid": "domain-guid-3", 577 "relationships": { 578 "organization": { 579 "data": { 580 "guid": "some-org-guid" 581 } 582 } 583 } 584 } 585 ] 586 }` 587 588 server.AppendHandlers( 589 CombineHandlers( 590 VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains", "organization_guids=some-org-guid"), 591 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 592 ), 593 ) 594 server.AppendHandlers( 595 CombineHandlers( 596 VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains", "organization_guids=some-org-guid&page=2&per_page=2"), 597 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 598 ), 599 ) 600 601 query = Query{ 602 Key: OrganizationGUIDFilter, 603 Values: []string{orgGUID}, 604 } 605 }) 606 607 It("returns the queried domain and all warnings", func() { 608 Expect(executeErr).NotTo(HaveOccurred()) 609 610 Expect(domains).To(ConsistOf( 611 Domain{Name: "domain-name-1", GUID: "domain-guid-1", OrganizationGUID: orgGUID}, 612 Domain{Name: "domain-name-2", GUID: "domain-guid-2", OrganizationGUID: orgGUID}, 613 Domain{Name: "domain-name-3", GUID: "domain-guid-3", OrganizationGUID: orgGUID}, 614 )) 615 Expect(warnings).To(ConsistOf("this is a warning", "this is another warning")) 616 }) 617 }) 618 619 When("the cloud controller returns errors and warnings", func() { 620 BeforeEach(func() { 621 response := `{ 622 "errors": [ 623 { 624 "code": 10008, 625 "detail": "The request is semantically invalid: command presence", 626 "title": "CF-UnprocessableEntity" 627 }, 628 { 629 "code": 10010, 630 "detail": "Isolation segment not found", 631 "title": "CF-ResourceNotFound" 632 } 633 ] 634 }` 635 server.AppendHandlers( 636 CombineHandlers( 637 VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains"), 638 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 639 ), 640 ) 641 }) 642 643 It("returns the error and all warnings", func() { 644 Expect(executeErr).To(MatchError(ccerror.MultiError{ 645 ResponseCode: http.StatusTeapot, 646 Errors: []ccerror.V3Error{ 647 { 648 Code: 10008, 649 Detail: "The request is semantically invalid: command presence", 650 Title: "CF-UnprocessableEntity", 651 }, 652 { 653 Code: 10010, 654 Detail: "Isolation segment not found", 655 Title: "CF-ResourceNotFound", 656 }, 657 }, 658 })) 659 Expect(warnings).To(ConsistOf("this is a warning")) 660 }) 661 }) 662 }) 663 664 Describe("SharePrivateDomainToOrgs", func() { 665 var ( 666 orgGUID = "some-org-guid" 667 domainGUID = "some-domain-guid" 668 warnings Warnings 669 executeErr error 670 ) 671 672 JustBeforeEach(func() { 673 warnings, executeErr = client.SharePrivateDomainToOrgs( 674 domainGUID, 675 SharedOrgs{GUIDs: []string{orgGUID}}, 676 ) 677 }) 678 679 When("the request succeeds", func() { 680 BeforeEach(func() { 681 response := `{"data": 682 [{ 683 "guid": "some-org-guid" 684 }] 685 }` 686 687 expectedBody := `{ 688 "data": [ 689 {"guid": "some-org-guid"} 690 ] 691 }` 692 693 server.AppendHandlers( 694 CombineHandlers( 695 VerifyRequest(http.MethodPost, "/v3/domains/some-domain-guid/relationships/shared_organizations"), 696 VerifyJSON(expectedBody), 697 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 698 ), 699 ) 700 }) 701 702 It("returns all warnings", func() { 703 Expect(warnings).To(ConsistOf("this is a warning")) 704 Expect(executeErr).To(BeNil()) 705 }) 706 }) 707 708 When("the cloud controller returns errors and warnings", func() { 709 BeforeEach(func() { 710 response := `{ 711 "errors": [ 712 { 713 "code": 10008, 714 "detail": "The request is semantically invalid: command presence", 715 "title": "CF-UnprocessableEntity" 716 }, 717 { 718 "code": 10010, 719 "detail": "Organization not found", 720 "title": "CF-ResourceNotFound" 721 } 722 ] 723 }` 724 server.AppendHandlers( 725 CombineHandlers( 726 VerifyRequest(http.MethodPost, "/v3/domains/some-domain-guid/relationships/shared_organizations"), 727 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 728 ), 729 ) 730 }) 731 732 It("returns the error and all warnings", func() { 733 Expect(executeErr).To(MatchError(ccerror.MultiError{ 734 ResponseCode: http.StatusTeapot, 735 Errors: []ccerror.V3Error{ 736 { 737 Code: 10008, 738 Detail: "The request is semantically invalid: command presence", 739 Title: "CF-UnprocessableEntity", 740 }, 741 { 742 Code: 10010, 743 Detail: "Organization not found", 744 Title: "CF-ResourceNotFound", 745 }, 746 }, 747 })) 748 Expect(warnings).To(ConsistOf("this is a warning")) 749 }) 750 }) 751 }) 752 753 Describe("UnsharePrivateDomainFromOrg", func() { 754 var ( 755 orgGUID = "some-org-guid" 756 domainGUID = "some-domain-guid" 757 warnings Warnings 758 executeErr error 759 ) 760 761 JustBeforeEach(func() { 762 warnings, executeErr = client.UnsharePrivateDomainFromOrg( 763 domainGUID, 764 orgGUID, 765 ) 766 }) 767 768 When("the request succeeds", func() { 769 BeforeEach(func() { 770 server.AppendHandlers( 771 CombineHandlers( 772 VerifyRequest(http.MethodDelete, "/v3/domains/some-domain-guid/relationships/shared_organizations/some-org-guid"), 773 RespondWith(http.StatusNoContent, "", http.Header{"X-Cf-Warnings": {"this is a warning"}}), 774 ), 775 ) 776 }) 777 778 It("returns all warnings", func() { 779 Expect(warnings).To(ConsistOf("this is a warning")) 780 Expect(executeErr).To(BeNil()) 781 }) 782 }) 783 784 When("the cloud controller returns errors and warnings", func() { 785 BeforeEach(func() { 786 response := `{ 787 "errors": [ 788 { 789 "code": 10008, 790 "detail": "The request is semantically invalid: command presence", 791 "title": "CF-UnprocessableEntity" 792 }, 793 { 794 "code": 10010, 795 "detail": "Organization not found", 796 "title": "CF-ResourceNotFound" 797 } 798 ] 799 }` 800 server.AppendHandlers( 801 CombineHandlers( 802 VerifyRequest(http.MethodDelete, "/v3/domains/some-domain-guid/relationships/shared_organizations/some-org-guid"), 803 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 804 ), 805 ) 806 }) 807 808 It("returns the error and all warnings", func() { 809 Expect(executeErr).To(MatchError(ccerror.MultiError{ 810 ResponseCode: http.StatusTeapot, 811 Errors: []ccerror.V3Error{ 812 { 813 Code: 10008, 814 Detail: "The request is semantically invalid: command presence", 815 Title: "CF-UnprocessableEntity", 816 }, 817 { 818 Code: 10010, 819 Detail: "Organization not found", 820 Title: "CF-ResourceNotFound", 821 }, 822 }, 823 })) 824 Expect(warnings).To(ConsistOf("this is a warning")) 825 }) 826 }) 827 }) 828 })