github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/api/cloudcontroller/ccv3/droplet_test.go (about) 1 package ccv3_test 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "mime/multipart" 9 "net/http" 10 "strings" 11 12 "code.cloudfoundry.org/cli/api/cloudcontroller" 13 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/ccv3fakes" 14 "code.cloudfoundry.org/cli/api/cloudcontroller/wrapper" 15 16 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 17 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 18 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 19 . "github.com/onsi/ginkgo" 20 . "github.com/onsi/gomega" 21 . "github.com/onsi/gomega/ghttp" 22 ) 23 24 var _ = Describe("Droplet", func() { 25 var client *Client 26 27 BeforeEach(func() { 28 client, _ = NewTestClient() 29 }) 30 31 Describe("CreateDroplet", func() { 32 var ( 33 droplet Droplet 34 warnings Warnings 35 executeErr error 36 ) 37 38 JustBeforeEach(func() { 39 droplet, warnings, executeErr = client.CreateDroplet("app-guid") 40 }) 41 42 When("the request succeeds", func() { 43 BeforeEach(func() { 44 response := `{ 45 "guid": "some-guid", 46 "state": "AWAITING_UPLOAD", 47 "error": null, 48 "lifecycle": { 49 "type": "buildpack", 50 "data": {} 51 }, 52 "buildpacks": [ 53 { 54 "name": "some-buildpack", 55 "detect_output": "detected-buildpack" 56 } 57 ], 58 "image": "docker/some-image", 59 "stack": "some-stack", 60 "created_at": "2016-03-28T23:39:34Z", 61 "updated_at": "2016-03-28T23:39:47Z" 62 }` 63 server.AppendHandlers( 64 CombineHandlers( 65 VerifyRequest(http.MethodPost, "/v3/droplets"), 66 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 67 ), 68 ) 69 }) 70 71 It("returns the given droplet and all warnings", func() { 72 Expect(executeErr).ToNot(HaveOccurred()) 73 74 Expect(droplet).To(Equal(Droplet{ 75 GUID: "some-guid", 76 Stack: "some-stack", 77 State: constant.DropletAwaitingUpload, 78 Buildpacks: []DropletBuildpack{ 79 { 80 Name: "some-buildpack", 81 DetectOutput: "detected-buildpack", 82 }, 83 }, 84 Image: "docker/some-image", 85 CreatedAt: "2016-03-28T23:39:34Z", 86 })) 87 Expect(warnings).To(ConsistOf("warning-1")) 88 }) 89 }) 90 91 When("cloud controller returns an error", func() { 92 BeforeEach(func() { 93 response := `{ 94 "errors": [ 95 { 96 "code": 10010, 97 "detail": "Droplet not found", 98 "title": "CF-ResourceNotFound" 99 } 100 ] 101 }` 102 server.AppendHandlers( 103 CombineHandlers( 104 VerifyRequest(http.MethodPost, "/v3/droplets"), 105 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 106 ), 107 ) 108 }) 109 110 It("returns the error", func() { 111 Expect(executeErr).To(MatchError(ccerror.DropletNotFoundError{})) 112 Expect(warnings).To(ConsistOf("warning-1")) 113 }) 114 }) 115 }) 116 117 Describe("GetApplicationDropletCurrent", func() { 118 var ( 119 droplet Droplet 120 warnings Warnings 121 executeErr error 122 ) 123 124 JustBeforeEach(func() { 125 droplet, warnings, executeErr = client.GetApplicationDropletCurrent("some-guid") 126 }) 127 128 When("the request succeeds", func() { 129 BeforeEach(func() { 130 response := `{ 131 "guid": "some-guid", 132 "state": "STAGED", 133 "error": null, 134 "lifecycle": { 135 "type": "buildpack", 136 "data": {} 137 }, 138 "buildpacks": [ 139 { 140 "name": "some-buildpack", 141 "detect_output": "detected-buildpack" 142 } 143 ], 144 "image": "docker/some-image", 145 "stack": "some-stack", 146 "created_at": "2016-03-28T23:39:34Z", 147 "updated_at": "2016-03-28T23:39:47Z" 148 }` 149 server.AppendHandlers( 150 CombineHandlers( 151 VerifyRequest(http.MethodGet, "/v3/apps/some-guid/droplets/current"), 152 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 153 ), 154 ) 155 }) 156 157 It("returns the given droplet and all warnings", func() { 158 Expect(executeErr).ToNot(HaveOccurred()) 159 160 Expect(droplet).To(Equal(Droplet{ 161 GUID: "some-guid", 162 Stack: "some-stack", 163 State: constant.DropletStaged, 164 Buildpacks: []DropletBuildpack{ 165 { 166 Name: "some-buildpack", 167 DetectOutput: "detected-buildpack", 168 }, 169 }, 170 Image: "docker/some-image", 171 CreatedAt: "2016-03-28T23:39:34Z", 172 })) 173 Expect(warnings).To(ConsistOf("warning-1")) 174 }) 175 }) 176 177 When("cloud controller returns an error", func() { 178 BeforeEach(func() { 179 response := `{ 180 "errors": [ 181 { 182 "code": 10010, 183 "detail": "Droplet not found", 184 "title": "CF-ResourceNotFound" 185 } 186 ] 187 }` 188 server.AppendHandlers( 189 CombineHandlers( 190 VerifyRequest(http.MethodGet, "/v3/apps/some-guid/droplets/current"), 191 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 192 ), 193 ) 194 }) 195 196 It("returns the error and all given warnings", func() { 197 Expect(executeErr).To(MatchError(ccerror.DropletNotFoundError{})) 198 Expect(warnings).To(ConsistOf("warning-1")) 199 }) 200 }) 201 }) 202 203 Describe("GetPackageDroplets", func() { 204 var ( 205 droplets []Droplet 206 warnings Warnings 207 executeErr error 208 ) 209 210 JustBeforeEach(func() { 211 droplets, warnings, executeErr = client.GetPackageDroplets( 212 "package-guid", 213 Query{Key: PerPage, Values: []string{"2"}}, 214 ) 215 }) 216 217 When("the request succeeds", func() { 218 BeforeEach(func() { 219 response1 := fmt.Sprintf(`{ 220 "pagination": { 221 "next": { 222 "href": "%s/v3/packages/package-guid/droplets?per_page=2&page=2" 223 } 224 }, 225 "resources": [ 226 { 227 "guid": "some-guid-1", 228 "stack": "some-stack-1", 229 "buildpacks": [{ 230 "name": "some-buildpack-1", 231 "detect_output": "detected-buildpack-1" 232 }], 233 "state": "STAGED", 234 "created_at": "2017-08-16T00:18:24Z", 235 "links": { 236 "package": "https://api.com/v3/packages/package-guid" 237 } 238 }, 239 { 240 "guid": "some-guid-2", 241 "stack": "some-stack-2", 242 "buildpacks": [{ 243 "name": "some-buildpack-2", 244 "detect_output": "detected-buildpack-2" 245 }], 246 "state": "COPYING", 247 "created_at": "2017-08-16T00:19:05Z" 248 } 249 ] 250 }`, server.URL()) 251 response2 := `{ 252 "pagination": { 253 "next": null 254 }, 255 "resources": [ 256 { 257 "guid": "some-guid-3", 258 "stack": "some-stack-3", 259 "buildpacks": [{ 260 "name": "some-buildpack-3", 261 "detect_output": "detected-buildpack-3" 262 }], 263 "state": "FAILED", 264 "created_at": "2017-08-22T17:55:02Z" 265 } 266 ] 267 }` 268 server.AppendHandlers( 269 CombineHandlers( 270 VerifyRequest(http.MethodGet, "/v3/packages/package-guid/droplets", "per_page=2"), 271 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"warning-1"}}), 272 ), 273 ) 274 server.AppendHandlers( 275 CombineHandlers( 276 VerifyRequest(http.MethodGet, "/v3/packages/package-guid/droplets", "per_page=2&page=2"), 277 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"warning-2"}}), 278 ), 279 ) 280 }) 281 282 It("returns the droplets", func() { 283 Expect(executeErr).ToNot(HaveOccurred()) 284 Expect(droplets).To(HaveLen(3)) 285 286 Expect(droplets[0]).To(Equal(Droplet{ 287 GUID: "some-guid-1", 288 Stack: "some-stack-1", 289 State: constant.DropletStaged, 290 Buildpacks: []DropletBuildpack{ 291 { 292 Name: "some-buildpack-1", 293 DetectOutput: "detected-buildpack-1", 294 }, 295 }, 296 CreatedAt: "2017-08-16T00:18:24Z", 297 })) 298 Expect(droplets[1]).To(Equal(Droplet{ 299 GUID: "some-guid-2", 300 Stack: "some-stack-2", 301 State: constant.DropletCopying, 302 Buildpacks: []DropletBuildpack{ 303 { 304 Name: "some-buildpack-2", 305 DetectOutput: "detected-buildpack-2", 306 }, 307 }, 308 CreatedAt: "2017-08-16T00:19:05Z", 309 })) 310 Expect(droplets[2]).To(Equal(Droplet{ 311 GUID: "some-guid-3", 312 Stack: "some-stack-3", 313 State: constant.DropletFailed, 314 Buildpacks: []DropletBuildpack{ 315 { 316 Name: "some-buildpack-3", 317 DetectOutput: "detected-buildpack-3", 318 }, 319 }, 320 CreatedAt: "2017-08-22T17:55:02Z", 321 })) 322 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 323 }) 324 }) 325 326 When("the cloud controller returns an error", func() { 327 BeforeEach(func() { 328 response := `{ 329 "errors": [ 330 { 331 "code": 10010, 332 "detail": "Package not found", 333 "title": "CF-ResourceNotFound" 334 } 335 ] 336 }` 337 server.AppendHandlers( 338 CombineHandlers( 339 VerifyRequest(http.MethodGet, "/v3/packages/package-guid/droplets"), 340 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 341 ), 342 ) 343 }) 344 345 It("returns the error and all warnings", func() { 346 Expect(executeErr).To(MatchError(ccerror.ResourceNotFoundError{ 347 Message: "Package not found", 348 })) 349 Expect(warnings).To(ConsistOf("warning-1")) 350 }) 351 }) 352 }) 353 354 Describe("GetDroplet", func() { 355 var ( 356 droplet Droplet 357 warnings Warnings 358 executeErr error 359 ) 360 361 JustBeforeEach(func() { 362 droplet, warnings, executeErr = client.GetDroplet("some-guid") 363 }) 364 365 When("the request succeeds", func() { 366 BeforeEach(func() { 367 response := `{ 368 "guid": "some-guid", 369 "state": "STAGED", 370 "error": null, 371 "lifecycle": { 372 "type": "buildpack", 373 "data": {} 374 }, 375 "buildpacks": [ 376 { 377 "name": "some-buildpack", 378 "detect_output": "detected-buildpack" 379 } 380 ], 381 "image": "docker/some-image", 382 "stack": "some-stack", 383 "created_at": "2016-03-28T23:39:34Z", 384 "updated_at": "2016-03-28T23:39:47Z" 385 }` 386 server.AppendHandlers( 387 CombineHandlers( 388 VerifyRequest(http.MethodGet, "/v3/droplets/some-guid"), 389 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 390 ), 391 ) 392 }) 393 394 It("returns the given droplet and all warnings", func() { 395 Expect(executeErr).ToNot(HaveOccurred()) 396 397 Expect(droplet).To(Equal(Droplet{ 398 GUID: "some-guid", 399 Stack: "some-stack", 400 State: constant.DropletStaged, 401 Buildpacks: []DropletBuildpack{ 402 { 403 Name: "some-buildpack", 404 DetectOutput: "detected-buildpack", 405 }, 406 }, 407 Image: "docker/some-image", 408 CreatedAt: "2016-03-28T23:39:34Z", 409 })) 410 Expect(warnings).To(ConsistOf("warning-1")) 411 }) 412 }) 413 414 When("cloud controller returns an error", func() { 415 BeforeEach(func() { 416 response := `{ 417 "errors": [ 418 { 419 "code": 10010, 420 "detail": "Droplet not found", 421 "title": "CF-ResourceNotFound" 422 } 423 ] 424 }` 425 server.AppendHandlers( 426 CombineHandlers( 427 VerifyRequest(http.MethodGet, "/v3/droplets/some-guid"), 428 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 429 ), 430 ) 431 }) 432 433 It("returns the error", func() { 434 Expect(executeErr).To(MatchError(ccerror.DropletNotFoundError{})) 435 Expect(warnings).To(ConsistOf("warning-1")) 436 }) 437 }) 438 }) 439 440 Describe("GetDroplets", func() { 441 var ( 442 droplets []Droplet 443 warnings Warnings 444 executeErr error 445 ) 446 447 JustBeforeEach(func() { 448 droplets, warnings, executeErr = client.GetDroplets( 449 Query{Key: AppGUIDFilter, Values: []string{"some-app-guid"}}, 450 Query{Key: PerPage, Values: []string{"2"}}, 451 ) 452 }) 453 454 When("the CC returns back droplets", func() { 455 BeforeEach(func() { 456 response1 := fmt.Sprintf(`{ 457 "pagination": { 458 "next": { 459 "href": "%s/v3/droplets?app_guids=some-app-guid&per_page=2&page=2" 460 } 461 }, 462 "resources": [ 463 { 464 "guid": "some-guid-1", 465 "stack": "some-stack-1", 466 "buildpacks": [{ 467 "name": "some-buildpack-1", 468 "detect_output": "detected-buildpack-1" 469 }], 470 "state": "STAGED", 471 "created_at": "2017-08-16T00:18:24Z", 472 "links": { 473 "package": "https://api.com/v3/packages/some-package-guid" 474 } 475 }, 476 { 477 "guid": "some-guid-2", 478 "stack": "some-stack-2", 479 "buildpacks": [{ 480 "name": "some-buildpack-2", 481 "detect_output": "detected-buildpack-2" 482 }], 483 "state": "COPYING", 484 "created_at": "2017-08-16T00:19:05Z" 485 } 486 ] 487 }`, server.URL()) 488 response2 := `{ 489 "pagination": { 490 "next": null 491 }, 492 "resources": [ 493 { 494 "guid": "some-guid-3", 495 "stack": "some-stack-3", 496 "buildpacks": [{ 497 "name": "some-buildpack-3", 498 "detect_output": "detected-buildpack-3" 499 }], 500 "state": "FAILED", 501 "created_at": "2017-08-22T17:55:02Z" 502 } 503 ] 504 }` 505 server.AppendHandlers( 506 CombineHandlers( 507 VerifyRequest(http.MethodGet, "/v3/droplets", "app_guids=some-app-guid&per_page=2"), 508 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"warning-1"}}), 509 ), 510 ) 511 server.AppendHandlers( 512 CombineHandlers( 513 VerifyRequest(http.MethodGet, "/v3/droplets", "app_guids=some-app-guid&per_page=2&page=2"), 514 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"warning-2"}}), 515 ), 516 ) 517 }) 518 519 It("returns the droplets and all warnings", func() { 520 Expect(executeErr).ToNot(HaveOccurred()) 521 Expect(droplets).To(HaveLen(3)) 522 523 Expect(droplets[0]).To(Equal(Droplet{ 524 GUID: "some-guid-1", 525 Stack: "some-stack-1", 526 State: constant.DropletStaged, 527 Buildpacks: []DropletBuildpack{ 528 { 529 Name: "some-buildpack-1", 530 DetectOutput: "detected-buildpack-1", 531 }, 532 }, 533 CreatedAt: "2017-08-16T00:18:24Z", 534 })) 535 Expect(droplets[1]).To(Equal(Droplet{ 536 GUID: "some-guid-2", 537 Stack: "some-stack-2", 538 State: constant.DropletCopying, 539 Buildpacks: []DropletBuildpack{ 540 { 541 Name: "some-buildpack-2", 542 DetectOutput: "detected-buildpack-2", 543 }, 544 }, 545 CreatedAt: "2017-08-16T00:19:05Z", 546 })) 547 Expect(droplets[2]).To(Equal(Droplet{ 548 GUID: "some-guid-3", 549 Stack: "some-stack-3", 550 State: constant.DropletFailed, 551 Buildpacks: []DropletBuildpack{ 552 { 553 Name: "some-buildpack-3", 554 DetectOutput: "detected-buildpack-3", 555 }, 556 }, 557 CreatedAt: "2017-08-22T17:55:02Z", 558 })) 559 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 560 }) 561 }) 562 563 When("cloud controller returns an error", func() { 564 BeforeEach(func() { 565 response := `{ 566 "errors": [ 567 { 568 "code": 10010, 569 "detail": "App not found", 570 "title": "CF-ResourceNotFound" 571 } 572 ] 573 }` 574 server.AppendHandlers( 575 CombineHandlers( 576 VerifyRequest(http.MethodGet, "/v3/droplets", "app_guids=some-app-guid&per_page=2"), 577 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 578 ), 579 ) 580 }) 581 582 It("returns the error", func() { 583 Expect(executeErr).To(MatchError(ccerror.ApplicationNotFoundError{})) 584 Expect(warnings).To(ConsistOf("warning-1")) 585 }) 586 }) 587 }) 588 589 Describe("UploadDropletBits", func() { 590 var ( 591 dropletGUID string 592 dropletFile io.Reader 593 dropletFilePath string 594 dropletContent string 595 jobURL JobURL 596 warnings Warnings 597 executeErr error 598 ) 599 600 BeforeEach(func() { 601 dropletGUID = "some-droplet-guid" 602 dropletContent = "some-content" 603 dropletFile = strings.NewReader(dropletContent) 604 dropletFilePath = "some/fake-droplet.tgz" 605 }) 606 607 JustBeforeEach(func() { 608 jobURL, warnings, executeErr = client.UploadDropletBits(dropletGUID, dropletFilePath, dropletFile, int64(len(dropletContent))) 609 }) 610 611 When("the upload is successful", func() { 612 BeforeEach(func() { 613 response := `{ 614 "guid": "some-droplet-guid", 615 "state": "PROCESSING_UPLOAD" 616 }` 617 618 verifyHeaderAndBody := func(_ http.ResponseWriter, req *http.Request) { 619 contentType := req.Header.Get("Content-Type") 620 Expect(contentType).To(MatchRegexp("multipart/form-data; boundary=[\\w\\d]+")) 621 622 defer req.Body.Close() 623 requestReader := multipart.NewReader(req.Body, contentType[30:]) 624 625 dropletPart, err := requestReader.NextPart() 626 Expect(err).NotTo(HaveOccurred()) 627 628 Expect(dropletPart.FormName()).To(Equal("bits")) 629 Expect(dropletPart.FileName()).To(Equal("fake-droplet.tgz")) 630 631 defer dropletPart.Close() 632 partContents, err := ioutil.ReadAll(dropletPart) 633 Expect(err).ToNot(HaveOccurred()) 634 Expect(string(partContents)).To(Equal(dropletContent)) 635 } 636 637 server.AppendHandlers( 638 CombineHandlers( 639 VerifyRequest(http.MethodPost, "/v3/droplets/some-droplet-guid/upload"), 640 verifyHeaderAndBody, 641 RespondWith( 642 http.StatusAccepted, 643 response, 644 http.Header{ 645 "X-Cf-Warnings": {"this is a warning"}, 646 "Location": {"http://example.com/job-guid"}, 647 }, 648 ), 649 ), 650 ) 651 }) 652 653 It("returns the processing job URL and warnings", func() { 654 Expect(executeErr).ToNot(HaveOccurred()) 655 Expect(warnings).To(ConsistOf(Warnings{"this is a warning"})) 656 Expect(jobURL).To(Equal(JobURL("http://example.com/job-guid"))) 657 }) 658 }) 659 660 When("there is an error reading the buildpack", func() { 661 var ( 662 fakeReader *ccv3fakes.FakeReader 663 expectedErr error 664 ) 665 666 BeforeEach(func() { 667 expectedErr = errors.New("droplet read error") 668 fakeReader = new(ccv3fakes.FakeReader) 669 fakeReader.ReadReturns(0, expectedErr) 670 dropletFile = fakeReader 671 672 server.AppendHandlers( 673 VerifyRequest(http.MethodPost, "/v3/droplets/some-droplet-guid/upload"), 674 ) 675 }) 676 677 It("returns the error", func() { 678 Expect(executeErr).To(MatchError(expectedErr)) 679 }) 680 }) 681 682 When("the upload returns an error", func() { 683 BeforeEach(func() { 684 response := `{ 685 "errors": [{ 686 "detail": "The droplet could not be found: some-droplet-guid", 687 "title": "CF-ResourceNotFound", 688 "code": 10010 689 }] 690 }` 691 692 server.AppendHandlers( 693 CombineHandlers( 694 VerifyRequest(http.MethodPost, "/v3/droplets/some-droplet-guid/upload"), 695 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 696 ), 697 ) 698 }) 699 700 It("returns the error and warnings", func() { 701 Expect(executeErr).To(MatchError( 702 ccerror.ResourceNotFoundError{ 703 Message: "The droplet could not be found: some-droplet-guid", 704 }, 705 )) 706 Expect(warnings).To(ConsistOf(Warnings{"this is a warning"})) 707 }) 708 }) 709 710 When("cloud controller returns an error", func() { 711 BeforeEach(func() { 712 dropletGUID = "some-guid" 713 714 response := `{ 715 "errors": [ 716 { 717 "code": 10010, 718 "detail": "Droplet not found", 719 "title": "CF-ResourceNotFound" 720 } 721 ] 722 }` 723 server.AppendHandlers( 724 CombineHandlers( 725 VerifyRequest(http.MethodPost, "/v3/droplets/some-guid/upload"), 726 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1"}}), 727 ), 728 ) 729 }) 730 731 It("returns the error", func() { 732 Expect(executeErr).To(MatchError(ccerror.DropletNotFoundError{})) 733 Expect(warnings).To(ConsistOf("warning-1")) 734 }) 735 }) 736 737 When("a retryable error occurs", func() { 738 BeforeEach(func() { 739 wrapper := &wrapper.CustomWrapper{ 740 CustomMake: func(connection cloudcontroller.Connection, request *cloudcontroller.Request, response *cloudcontroller.Response) error { 741 defer GinkgoRecover() // Since this will be running in a thread 742 743 if strings.HasSuffix(request.URL.String(), "/v3/droplets/some-droplet-guid/upload") { 744 _, err := ioutil.ReadAll(request.Body) 745 Expect(err).ToNot(HaveOccurred()) 746 Expect(request.Body.Close()).ToNot(HaveOccurred()) 747 return request.ResetBody() 748 } 749 return connection.Make(request, response) 750 }, 751 } 752 753 client, _ = NewTestClient(Config{Wrappers: []ConnectionWrapper{wrapper}}) 754 }) 755 756 It("returns the PipeSeekError", func() { 757 Expect(executeErr).To(MatchError(ccerror.PipeSeekError{})) 758 }) 759 }) 760 761 When("an http error occurs mid-transfer", func() { 762 var expectedErr error 763 764 BeforeEach(func() { 765 expectedErr = errors.New("some read error") 766 767 wrapper := &wrapper.CustomWrapper{ 768 CustomMake: func(connection cloudcontroller.Connection, request *cloudcontroller.Request, response *cloudcontroller.Response) error { 769 defer GinkgoRecover() // Since this will be running in a thread 770 771 if strings.HasSuffix(request.URL.String(), "/v3/droplets/some-droplet-guid/upload") { 772 defer request.Body.Close() 773 readBytes, err := ioutil.ReadAll(request.Body) 774 Expect(err).ToNot(HaveOccurred()) 775 Expect(len(readBytes)).To(BeNumerically(">", len(dropletContent))) 776 return expectedErr 777 } 778 return connection.Make(request, response) 779 }, 780 } 781 782 client, _ = NewTestClient(Config{Wrappers: []ConnectionWrapper{wrapper}}) 783 }) 784 785 It("returns the http error", func() { 786 Expect(executeErr).To(MatchError(expectedErr)) 787 }) 788 }) 789 }) 790 })