github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/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/resources" 9 "code.cloudfoundry.org/cli/types" 10 11 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 . "github.com/onsi/gomega/ghttp" 15 ) 16 17 var _ = Describe("Domain", func() { 18 var client *Client 19 20 BeforeEach(func() { 21 client, _ = NewTestClient() 22 }) 23 24 Describe("CheckRoute", func() { 25 var ( 26 matches bool 27 warnings Warnings 28 executeErr error 29 30 domainGUID string 31 hostname string 32 path string 33 port int 34 ) 35 36 BeforeEach(func() { 37 domainGUID = "domain-guid" 38 hostname = "" 39 path = "" 40 port = 0 41 }) 42 43 JustBeforeEach(func() { 44 matches, warnings, executeErr = client.CheckRoute(domainGUID, hostname, path, port) 45 }) 46 47 When("the request succeeds", func() { 48 When("no query params given", func() { 49 BeforeEach(func() { 50 response := `{ "matching_route": true }` 51 52 server.AppendHandlers( 53 CombineHandlers( 54 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations"), 55 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 56 ), 57 ) 58 }) 59 60 It("returns whether the route matches and all warnings", func() { 61 Expect(matches).To(BeTrue()) 62 Expect(executeErr).ToNot(HaveOccurred()) 63 Expect(warnings).To(ConsistOf("warning-1")) 64 }) 65 }) 66 67 When("hostname is passed in", func() { 68 BeforeEach(func() { 69 hostname = "hello" 70 response := `{ "matching_route": true }` 71 72 server.AppendHandlers( 73 CombineHandlers( 74 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "host=hello"), 75 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 76 ), 77 ) 78 }) 79 80 It("returns whether the route matches and all warnings", func() { 81 Expect(matches).To(BeTrue()) 82 Expect(executeErr).ToNot(HaveOccurred()) 83 Expect(warnings).To(ConsistOf("warning-1")) 84 }) 85 }) 86 87 When("path is passed in", func() { 88 BeforeEach(func() { 89 path = "/potato" 90 response := `{ "matching_route": true }` 91 92 server.AppendHandlers( 93 CombineHandlers( 94 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "path=/potato"), 95 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 96 ), 97 ) 98 }) 99 100 It("returns whether the route matches and all warnings", func() { 101 Expect(matches).To(BeTrue()) 102 Expect(executeErr).ToNot(HaveOccurred()) 103 Expect(warnings).To(ConsistOf("warning-1")) 104 }) 105 }) 106 107 When("hostname and path are passed in", func() { 108 BeforeEach(func() { 109 hostname = "hello" 110 path = "/potato" 111 response := `{ "matching_route": true }` 112 113 server.AppendHandlers( 114 CombineHandlers( 115 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "host=hello&path=/potato"), 116 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 117 ), 118 ) 119 }) 120 121 It("returns whether the route matches and all warnings", func() { 122 Expect(matches).To(BeTrue()) 123 Expect(executeErr).ToNot(HaveOccurred()) 124 Expect(warnings).To(ConsistOf("warning-1")) 125 }) 126 }) 127 128 When("port is passed in", func() { 129 BeforeEach(func() { 130 port = 1024 131 response := `{ "matching_route": true }` 132 133 server.AppendHandlers( 134 CombineHandlers( 135 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "port=1024"), 136 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 137 ), 138 ) 139 }) 140 141 It("returns whether the route matches and all warnings", func() { 142 Expect(matches).To(BeTrue()) 143 Expect(executeErr).ToNot(HaveOccurred()) 144 Expect(warnings).To(ConsistOf("warning-1")) 145 }) 146 }) 147 }) 148 149 When("the cloud controller returns errors and warnings", func() { 150 BeforeEach(func() { 151 response := `{ 152 "errors": [ 153 { 154 "code": 10008, 155 "detail": "The request is semantically invalid: command presence", 156 "title": "CF-UnprocessableEntity" 157 }, 158 { 159 "code": 10010, 160 "detail": "Domain not found", 161 "title": "CF-ResourceNotFound" 162 } 163 ] 164 }` 165 server.AppendHandlers( 166 CombineHandlers( 167 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations"), 168 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 169 ), 170 ) 171 }) 172 173 It("returns the error and all warnings", func() { 174 Expect(executeErr).To(MatchError(ccerror.MultiError{ 175 ResponseCode: http.StatusTeapot, 176 Errors: []ccerror.V3Error{ 177 { 178 Code: 10008, 179 Detail: "The request is semantically invalid: command presence", 180 Title: "CF-UnprocessableEntity", 181 }, 182 { 183 Code: 10010, 184 Detail: "Domain not found", 185 Title: "CF-ResourceNotFound", 186 }, 187 }, 188 })) 189 Expect(warnings).To(ConsistOf("this is a warning")) 190 }) 191 }) 192 }) 193 194 Describe("CreateDomain for Shared Domains", func() { 195 var ( 196 domain resources.Domain 197 warnings Warnings 198 executeErr error 199 ) 200 201 JustBeforeEach(func() { 202 domain, warnings, executeErr = client.CreateDomain( 203 resources.Domain{ 204 Name: "some-name", 205 Internal: types.NullBool{IsSet: true, Value: true}, 206 RouterGroup: "some-router-group", 207 }, 208 ) 209 }) 210 211 When("the request succeeds", func() { 212 BeforeEach(func() { 213 response := `{ 214 "guid": "some-guid", 215 "name": "some-name", 216 "internal": true, 217 "router_group": { 218 "guid": "some-router-group" 219 } 220 }` 221 222 expectedBody := `{ 223 "name": "some-name", 224 "internal": true, 225 "router_group": { 226 "guid": "some-router-group" 227 } 228 }` 229 230 server.AppendHandlers( 231 CombineHandlers( 232 VerifyRequest(http.MethodPost, "/v3/domains"), 233 VerifyJSON(expectedBody), 234 RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 235 ), 236 ) 237 }) 238 239 It("returns the given domain and all warnings", func() { 240 Expect(executeErr).ToNot(HaveOccurred()) 241 Expect(warnings).To(ConsistOf("warning-1")) 242 243 Expect(domain).To(Equal(resources.Domain{ 244 GUID: "some-guid", 245 Name: "some-name", 246 Internal: types.NullBool{IsSet: true, Value: true}, 247 RouterGroup: "some-router-group", 248 })) 249 }) 250 }) 251 252 When("the cloud controller returns errors and warnings", func() { 253 BeforeEach(func() { 254 response := `{ 255 "errors": [ 256 { 257 "code": 10008, 258 "detail": "The request is semantically invalid: command presence", 259 "title": "CF-UnprocessableEntity" 260 }, 261 { 262 "code": 10010, 263 "detail": "Isolation segment not found", 264 "title": "CF-ResourceNotFound" 265 } 266 ] 267 }` 268 server.AppendHandlers( 269 CombineHandlers( 270 VerifyRequest(http.MethodPost, "/v3/domains"), 271 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 272 ), 273 ) 274 }) 275 276 It("returns the error and all warnings", func() { 277 Expect(executeErr).To(MatchError(ccerror.MultiError{ 278 ResponseCode: http.StatusTeapot, 279 Errors: []ccerror.V3Error{ 280 { 281 Code: 10008, 282 Detail: "The request is semantically invalid: command presence", 283 Title: "CF-UnprocessableEntity", 284 }, 285 { 286 Code: 10010, 287 Detail: "Isolation segment not found", 288 Title: "CF-ResourceNotFound", 289 }, 290 }, 291 })) 292 Expect(warnings).To(ConsistOf("this is a warning")) 293 }) 294 }) 295 }) 296 297 Describe("CreateDomain for Private Domains", func() { 298 var ( 299 domain resources.Domain 300 warnings Warnings 301 executeErr error 302 ) 303 304 JustBeforeEach(func() { 305 domain, warnings, executeErr = client.CreateDomain(resources.Domain{Name: "some-name", Internal: types.NullBool{IsSet: false, Value: true}, OrganizationGUID: "organization-guid"}) 306 }) 307 308 When("the request succeeds", func() { 309 BeforeEach(func() { 310 response := `{ 311 "guid": "some-guid", 312 "name": "some-name", 313 "relationships": { 314 "organization": { 315 "data" : { 316 "guid" : "organization-guid" 317 } 318 } 319 }, 320 "internal": false 321 }` 322 323 expectedRequestBody := `{ 324 "name": "some-name", 325 "relationships": { 326 "organization": { 327 "data" : { 328 "guid" : "organization-guid" 329 } 330 } 331 } 332 }` 333 334 server.AppendHandlers( 335 CombineHandlers( 336 VerifyRequest(http.MethodPost, "/v3/domains"), 337 VerifyJSON(expectedRequestBody), 338 RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 339 ), 340 ) 341 }) 342 343 It("returns the given domain and all warnings", func() { 344 Expect(executeErr).ToNot(HaveOccurred()) 345 Expect(warnings).To(ConsistOf("warning-1")) 346 347 Expect(domain).To(Equal(resources.Domain{ 348 GUID: "some-guid", 349 Name: "some-name", 350 OrganizationGUID: "organization-guid", 351 Internal: types.NullBool{IsSet: true, Value: false}, 352 })) 353 }) 354 }) 355 356 When("the cloud controller returns errors and warnings", func() { 357 BeforeEach(func() { 358 response := `{ 359 "errors": [ 360 { 361 "code": 10008, 362 "detail": "The request is semantically invalid: command presence", 363 "title": "CF-UnprocessableEntity" 364 }, 365 { 366 "code": 10010, 367 "detail": "Isolation segment not found", 368 "title": "CF-ResourceNotFound" 369 } 370 ] 371 }` 372 server.AppendHandlers( 373 CombineHandlers( 374 VerifyRequest(http.MethodPost, "/v3/domains"), 375 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 376 ), 377 ) 378 }) 379 380 It("returns the error and all warnings", func() { 381 Expect(executeErr).To(MatchError(ccerror.MultiError{ 382 ResponseCode: http.StatusTeapot, 383 Errors: []ccerror.V3Error{ 384 { 385 Code: 10008, 386 Detail: "The request is semantically invalid: command presence", 387 Title: "CF-UnprocessableEntity", 388 }, 389 { 390 Code: 10010, 391 Detail: "Isolation segment not found", 392 Title: "CF-ResourceNotFound", 393 }, 394 }, 395 })) 396 Expect(warnings).To(ConsistOf("this is a warning")) 397 }) 398 }) 399 }) 400 401 Describe("DeleteDomain", func() { 402 var ( 403 domainGUID string 404 jobURLString string 405 jobURL JobURL 406 warnings Warnings 407 executeErr error 408 ) 409 410 JustBeforeEach(func() { 411 jobURL, warnings, executeErr = client.DeleteDomain(domainGUID) 412 }) 413 414 When("domain exists", func() { 415 domainGUID = "domain-guid" 416 jobURLString = "https://api.test.com/v3/jobs/job-guid" 417 418 BeforeEach(func() { 419 server.AppendHandlers( 420 CombineHandlers( 421 VerifyRequest(http.MethodDelete, "/v3/domains/domain-guid"), 422 RespondWith(http.StatusAccepted, nil, http.Header{ 423 "X-Cf-Warnings": {"this is a warning"}, 424 "Location": {jobURLString}, 425 }), 426 ), 427 ) 428 }) 429 430 It("returns all warnings", func() { 431 Expect(executeErr).NotTo(HaveOccurred()) 432 Expect(jobURL).To(Equal(JobURL(jobURLString))) 433 Expect(warnings).To(ConsistOf("this is a warning")) 434 }) 435 }) 436 437 When("the cloud controller returns errors and warnings", func() { 438 BeforeEach(func() { 439 response := `{ 440 "errors": [ 441 { 442 "code": 10008, 443 "detail": "The request is semantically invalid: command presence", 444 "title": "CF-UnprocessableEntity" 445 }, 446 { 447 "code": 10010, 448 "detail": "Isolation segment not found", 449 "title": "CF-ResourceNotFound" 450 } 451 ] 452 }` 453 server.AppendHandlers( 454 CombineHandlers( 455 VerifyRequest(http.MethodDelete, "/v3/domains/domain-guid"), 456 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 457 ), 458 ) 459 }) 460 461 It("returns the error and all warnings", func() { 462 Expect(executeErr).To(MatchError(ccerror.MultiError{ 463 ResponseCode: http.StatusTeapot, 464 Errors: []ccerror.V3Error{ 465 { 466 Code: 10008, 467 Detail: "The request is semantically invalid: command presence", 468 Title: "CF-UnprocessableEntity", 469 }, 470 { 471 Code: 10010, 472 Detail: "Isolation segment not found", 473 Title: "CF-ResourceNotFound", 474 }, 475 }, 476 })) 477 Expect(warnings).To(ConsistOf("this is a warning")) 478 }) 479 }) 480 }) 481 482 Describe("GetDomains", func() { 483 var ( 484 query Query 485 domains []resources.Domain 486 warnings Warnings 487 executeErr error 488 ) 489 490 JustBeforeEach(func() { 491 domains, warnings, executeErr = client.GetDomains(query) 492 }) 493 494 When("domains exist", func() { 495 BeforeEach(func() { 496 response1 := fmt.Sprintf(`{ 497 "pagination": { 498 "next": { 499 "href": "%s/v3/domains?page=2&per_page=2" 500 } 501 }, 502 "resources": [ 503 { 504 "name": "domain-name-1", 505 "guid": "domain-guid-1", 506 "relationships": { 507 "organization": { 508 "data": { 509 "guid": "owning-org-1" 510 } 511 } 512 } 513 }, 514 { 515 "name": "domain-name-2", 516 "guid": "domain-guid-2", 517 "relationships": { 518 "organization": { 519 "data": { 520 "guid": "owning-org-2" 521 } 522 } 523 } 524 } 525 ] 526 }`, server.URL()) 527 response2 := `{ 528 "pagination": { 529 "next": null 530 }, 531 "resources": [ 532 { 533 "name": "domain-name-3", 534 "guid": "domain-guid-3", 535 "relationships": { 536 "organization": { 537 "data": { 538 "guid": "owning-org-3" 539 } 540 } 541 } 542 } 543 ] 544 }` 545 546 server.AppendHandlers( 547 CombineHandlers( 548 VerifyRequest(http.MethodGet, "/v3/domains"), 549 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 550 ), 551 ) 552 server.AppendHandlers( 553 CombineHandlers( 554 VerifyRequest(http.MethodGet, "/v3/domains", "page=2&per_page=2"), 555 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 556 ), 557 ) 558 559 query = Query{} 560 }) 561 562 It("returns the queried domain and all warnings", func() { 563 Expect(executeErr).NotTo(HaveOccurred()) 564 565 Expect(domains).To(ConsistOf( 566 resources.Domain{Name: "domain-name-1", GUID: "domain-guid-1", OrganizationGUID: "owning-org-1"}, 567 resources.Domain{Name: "domain-name-2", GUID: "domain-guid-2", OrganizationGUID: "owning-org-2"}, 568 resources.Domain{Name: "domain-name-3", GUID: "domain-guid-3", OrganizationGUID: "owning-org-3"}, 569 )) 570 Expect(warnings).To(ConsistOf("this is a warning", "this is another warning")) 571 }) 572 }) 573 574 When("the cloud controller returns errors and warnings", func() { 575 BeforeEach(func() { 576 response := `{ 577 "errors": [ 578 { 579 "code": 10008, 580 "detail": "The request is semantically invalid: command presence", 581 "title": "CF-UnprocessableEntity" 582 }, 583 { 584 "code": 10010, 585 "detail": "Isolation segment not found", 586 "title": "CF-ResourceNotFound" 587 } 588 ] 589 }` 590 server.AppendHandlers( 591 CombineHandlers( 592 VerifyRequest(http.MethodGet, "/v3/domains"), 593 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 594 ), 595 ) 596 }) 597 598 It("returns the error and all warnings", func() { 599 Expect(executeErr).To(MatchError(ccerror.MultiError{ 600 ResponseCode: http.StatusTeapot, 601 Errors: []ccerror.V3Error{ 602 { 603 Code: 10008, 604 Detail: "The request is semantically invalid: command presence", 605 Title: "CF-UnprocessableEntity", 606 }, 607 { 608 Code: 10010, 609 Detail: "Isolation segment not found", 610 Title: "CF-ResourceNotFound", 611 }, 612 }, 613 })) 614 Expect(warnings).To(ConsistOf("this is a warning")) 615 }) 616 }) 617 }) 618 619 Describe("GetDomain", func() { 620 621 var ( 622 domainGUID string 623 domain resources.Domain 624 warnings Warnings 625 executeErr error 626 ) 627 JustBeforeEach(func() { 628 domainGUID = "domain-guid-1" 629 domain, warnings, executeErr = client.GetDomain(domainGUID) 630 }) 631 632 When("domain is found", func() { 633 BeforeEach(func() { 634 response := `{ 635 "name": "domain-name-1", 636 "guid": "domain-guid-1", 637 "metadata": { 638 "annotations": {}, 639 "labels": { 640 "fun": "superfun", 641 "fun2": "super--fun" 642 } 643 } 644 }` 645 server.AppendHandlers( 646 CombineHandlers( 647 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid-1"), 648 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 649 ), 650 ) 651 }) 652 653 It("returns a domain and prints all warnings", func() { 654 Expect(executeErr).To(Not(HaveOccurred())) 655 656 Expect(domain.Name).To(Equal("domain-name-1")) 657 658 Expect(domain.GUID).To(Equal("domain-guid-1")) 659 660 Expect(domain.Metadata.Labels).To(Equal(map[string]types.NullString{ 661 "fun": types.NewNullString("superfun"), 662 "fun2": types.NewNullString("super--fun"), 663 })) 664 665 Expect(warnings).To(ConsistOf("this is a warning")) 666 }) 667 }) 668 669 When("cloud controller returns an error", func() { 670 BeforeEach(func() { 671 response := `{ 672 "errors": [ 673 { 674 "code": 10008, 675 "detail": "The request is semantically invalid: command presence", 676 "title": "CF-UnprocessableEntity" 677 }, 678 { 679 "code": 10010, 680 "detail": "Domain not found", 681 "title": "CF-ResourceNotFound" 682 } 683 ] 684 }` 685 server.AppendHandlers( 686 CombineHandlers( 687 VerifyRequest(http.MethodGet, "/v3/domains/domain-guid-1"), 688 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 689 ), 690 ) 691 }) 692 693 It("returns the error and all warnings", func() { 694 Expect(executeErr).To(MatchError(ccerror.MultiError{ 695 ResponseCode: http.StatusTeapot, 696 Errors: []ccerror.V3Error{ 697 { 698 Code: 10008, 699 Detail: "The request is semantically invalid: command presence", 700 Title: "CF-UnprocessableEntity", 701 }, 702 { 703 Code: 10010, 704 Detail: "Domain not found", 705 Title: "CF-ResourceNotFound", 706 }, 707 }, 708 })) 709 Expect(warnings).To(ConsistOf("this is a warning")) 710 }) 711 }) 712 }) 713 714 Describe("GetOrganizationDomains", func() { 715 var ( 716 orgGUID string 717 query Query 718 domains []resources.Domain 719 warnings Warnings 720 executeErr error 721 ) 722 723 BeforeEach(func() { 724 orgGUID = "some-org-guid" 725 }) 726 727 JustBeforeEach(func() { 728 domains, warnings, executeErr = client.GetOrganizationDomains(orgGUID, query) 729 }) 730 731 When("domains exist", func() { 732 BeforeEach(func() { 733 response1 := fmt.Sprintf(`{ 734 "pagination": { 735 "next": { 736 "href": "%s/v3/organizations/some-org-guid/domains?organization_guids=some-org-guid&page=2&per_page=2" 737 } 738 }, 739 "resources": [ 740 { 741 "name": "domain-name-1", 742 "guid": "domain-guid-1", 743 "relationships": { 744 "organization": { 745 "data": { 746 "guid": "some-org-guid" 747 } 748 } 749 } 750 }, 751 { 752 "name": "domain-name-2", 753 "guid": "domain-guid-2", 754 "relationships": { 755 "organization": { 756 "data": { 757 "guid": "some-org-guid" 758 } 759 } 760 } 761 } 762 ] 763 }`, server.URL()) 764 response2 := `{ 765 "pagination": { 766 "next": null 767 }, 768 "resources": [ 769 { 770 "name": "domain-name-3", 771 "guid": "domain-guid-3", 772 "relationships": { 773 "organization": { 774 "data": { 775 "guid": "some-org-guid" 776 } 777 } 778 } 779 } 780 ] 781 }` 782 783 server.AppendHandlers( 784 CombineHandlers( 785 VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains", "organization_guids=some-org-guid"), 786 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 787 ), 788 ) 789 server.AppendHandlers( 790 CombineHandlers( 791 VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains", "organization_guids=some-org-guid&page=2&per_page=2"), 792 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 793 ), 794 ) 795 796 query = Query{ 797 Key: OrganizationGUIDFilter, 798 Values: []string{orgGUID}, 799 } 800 }) 801 802 It("returns the queried domain and all warnings", func() { 803 Expect(executeErr).NotTo(HaveOccurred()) 804 805 Expect(domains).To(ConsistOf( 806 resources.Domain{Name: "domain-name-1", GUID: "domain-guid-1", OrganizationGUID: orgGUID}, 807 resources.Domain{Name: "domain-name-2", GUID: "domain-guid-2", OrganizationGUID: orgGUID}, 808 resources.Domain{Name: "domain-name-3", GUID: "domain-guid-3", OrganizationGUID: orgGUID}, 809 )) 810 Expect(warnings).To(ConsistOf("this is a warning", "this is another warning")) 811 }) 812 }) 813 814 When("the cloud controller returns errors and warnings", func() { 815 BeforeEach(func() { 816 response := `{ 817 "errors": [ 818 { 819 "code": 10008, 820 "detail": "The request is semantically invalid: command presence", 821 "title": "CF-UnprocessableEntity" 822 }, 823 { 824 "code": 10010, 825 "detail": "Isolation segment not found", 826 "title": "CF-ResourceNotFound" 827 } 828 ] 829 }` 830 server.AppendHandlers( 831 CombineHandlers( 832 VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains"), 833 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 834 ), 835 ) 836 }) 837 838 It("returns the error and all warnings", func() { 839 Expect(executeErr).To(MatchError(ccerror.MultiError{ 840 ResponseCode: http.StatusTeapot, 841 Errors: []ccerror.V3Error{ 842 { 843 Code: 10008, 844 Detail: "The request is semantically invalid: command presence", 845 Title: "CF-UnprocessableEntity", 846 }, 847 { 848 Code: 10010, 849 Detail: "Isolation segment not found", 850 Title: "CF-ResourceNotFound", 851 }, 852 }, 853 })) 854 Expect(warnings).To(ConsistOf("this is a warning")) 855 }) 856 }) 857 }) 858 859 Describe("SharePrivateDomainToOrgs", func() { 860 var ( 861 orgGUID = "some-org-guid" 862 domainGUID = "some-domain-guid" 863 warnings Warnings 864 executeErr error 865 ) 866 867 JustBeforeEach(func() { 868 warnings, executeErr = client.SharePrivateDomainToOrgs( 869 domainGUID, 870 SharedOrgs{GUIDs: []string{orgGUID}}, 871 ) 872 }) 873 874 When("the request succeeds", func() { 875 BeforeEach(func() { 876 response := `{"data": 877 [{ 878 "guid": "some-org-guid" 879 }] 880 }` 881 882 expectedBody := `{ 883 "data": [ 884 {"guid": "some-org-guid"} 885 ] 886 }` 887 888 server.AppendHandlers( 889 CombineHandlers( 890 VerifyRequest(http.MethodPost, "/v3/domains/some-domain-guid/relationships/shared_organizations"), 891 VerifyJSON(expectedBody), 892 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 893 ), 894 ) 895 }) 896 897 It("returns all warnings", func() { 898 Expect(warnings).To(ConsistOf("this is a warning")) 899 Expect(executeErr).To(BeNil()) 900 }) 901 }) 902 903 When("the cloud controller returns errors and warnings", func() { 904 BeforeEach(func() { 905 response := `{ 906 "errors": [ 907 { 908 "code": 10008, 909 "detail": "The request is semantically invalid: command presence", 910 "title": "CF-UnprocessableEntity" 911 }, 912 { 913 "code": 10010, 914 "detail": "Organization not found", 915 "title": "CF-ResourceNotFound" 916 } 917 ] 918 }` 919 server.AppendHandlers( 920 CombineHandlers( 921 VerifyRequest(http.MethodPost, "/v3/domains/some-domain-guid/relationships/shared_organizations"), 922 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 923 ), 924 ) 925 }) 926 927 It("returns the error and all warnings", func() { 928 Expect(executeErr).To(MatchError(ccerror.MultiError{ 929 ResponseCode: http.StatusTeapot, 930 Errors: []ccerror.V3Error{ 931 { 932 Code: 10008, 933 Detail: "The request is semantically invalid: command presence", 934 Title: "CF-UnprocessableEntity", 935 }, 936 { 937 Code: 10010, 938 Detail: "Organization not found", 939 Title: "CF-ResourceNotFound", 940 }, 941 }, 942 })) 943 Expect(warnings).To(ConsistOf("this is a warning")) 944 }) 945 }) 946 }) 947 948 Describe("UnsharePrivateDomainFromOrg", func() { 949 var ( 950 orgGUID = "some-org-guid" 951 domainGUID = "some-domain-guid" 952 warnings Warnings 953 executeErr error 954 ) 955 956 JustBeforeEach(func() { 957 warnings, executeErr = client.UnsharePrivateDomainFromOrg( 958 domainGUID, 959 orgGUID, 960 ) 961 }) 962 963 When("the request succeeds", func() { 964 BeforeEach(func() { 965 server.AppendHandlers( 966 CombineHandlers( 967 VerifyRequest(http.MethodDelete, "/v3/domains/some-domain-guid/relationships/shared_organizations/some-org-guid"), 968 RespondWith(http.StatusNoContent, "", http.Header{"X-Cf-Warnings": {"this is a warning"}}), 969 ), 970 ) 971 }) 972 973 It("returns all warnings", func() { 974 Expect(warnings).To(ConsistOf("this is a warning")) 975 Expect(executeErr).To(BeNil()) 976 }) 977 }) 978 979 When("the cloud controller returns errors and warnings", func() { 980 BeforeEach(func() { 981 response := `{ 982 "errors": [ 983 { 984 "code": 10008, 985 "detail": "The request is semantically invalid: command presence", 986 "title": "CF-UnprocessableEntity" 987 }, 988 { 989 "code": 10010, 990 "detail": "Organization not found", 991 "title": "CF-ResourceNotFound" 992 } 993 ] 994 }` 995 server.AppendHandlers( 996 CombineHandlers( 997 VerifyRequest(http.MethodDelete, "/v3/domains/some-domain-guid/relationships/shared_organizations/some-org-guid"), 998 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 999 ), 1000 ) 1001 }) 1002 1003 It("returns the error and all warnings", func() { 1004 Expect(executeErr).To(MatchError(ccerror.MultiError{ 1005 ResponseCode: http.StatusTeapot, 1006 Errors: []ccerror.V3Error{ 1007 { 1008 Code: 10008, 1009 Detail: "The request is semantically invalid: command presence", 1010 Title: "CF-UnprocessableEntity", 1011 }, 1012 { 1013 Code: 10010, 1014 Detail: "Organization not found", 1015 Title: "CF-ResourceNotFound", 1016 }, 1017 }, 1018 })) 1019 Expect(warnings).To(ConsistOf("this is a warning")) 1020 }) 1021 }) 1022 }) 1023 })