github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/worker/transport/garden_round_tripper_test.go (about) 1 package transport_test 2 3 import ( 4 "errors" 5 "net/http" 6 "net/url" 7 "time" 8 9 "github.com/pf-qiu/concourse/v6/atc/db/dbfakes" 10 "github.com/pf-qiu/concourse/v6/atc/worker/transport" 11 "github.com/pf-qiu/concourse/v6/atc/worker/transport/transportfakes" 12 "github.com/concourse/retryhttp/retryhttpfakes" 13 14 "github.com/pf-qiu/concourse/v6/atc/db" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 ) 18 19 var _ = Describe("GardenRoundTripper #RoundTrip", func() { 20 var ( 21 request http.Request 22 fakeDB *transportfakes.FakeTransportDB 23 fakeRoundTripper *retryhttpfakes.FakeRoundTripper 24 roundTripper http.RoundTripper 25 response *http.Response 26 err error 27 ) 28 29 BeforeEach(func() { 30 fakeDB = new(transportfakes.FakeTransportDB) 31 fakeRoundTripper = new(retryhttpfakes.FakeRoundTripper) 32 workerAddr := "some-worker-address" 33 roundTripper = transport.NewGardenRoundTripper("some-worker", &workerAddr, fakeDB, fakeRoundTripper) 34 requestUrl, err := url.Parse("http://1.2.3.4/something") 35 Expect(err).NotTo(HaveOccurred()) 36 37 request = http.Request{ 38 URL: requestUrl, 39 } 40 41 fakeRoundTripper.RoundTripReturns(&http.Response{StatusCode: http.StatusTeapot}, nil) 42 }) 43 44 JustBeforeEach(func() { 45 response, err = roundTripper.RoundTrip(&request) 46 }) 47 48 It("returns the response", func() { 49 Expect(err).NotTo(HaveOccurred()) 50 Expect(response).To(Equal(&http.Response{StatusCode: http.StatusTeapot})) 51 }) 52 53 It("sends the request with worker's garden address", func() { 54 Expect(fakeRoundTripper.RoundTripCallCount()).To(Equal(1)) 55 actualRequest := fakeRoundTripper.RoundTripArgsForCall(0) 56 Expect(actualRequest.URL.Host).To(Equal("some-worker-address")) 57 Expect(actualRequest.URL.Path).To(Equal("/something")) 58 }) 59 60 It("reuses the request cached host on subsequent calls", func() { 61 Expect(fakeDB.GetWorkerCallCount()).To(Equal(0)) 62 _, err := roundTripper.RoundTrip(&request) 63 Expect(err).NotTo(HaveOccurred()) 64 Expect(fakeDB.GetWorkerCallCount()).To(Equal(0)) 65 }) 66 67 Context("when inner roundtrip fails", func() { 68 BeforeEach(func() { 69 fakeRoundTripper.RoundTripReturns(nil, errors.New("some-error")) 70 71 address := "some-new-worker-address" 72 savedWorker := new(dbfakes.FakeWorker) 73 savedWorker.GardenAddrReturns(&address) 74 savedWorker.ExpiresAtReturns(time.Now().Add(123 * time.Minute)) 75 savedWorker.StateReturns(db.WorkerStateRunning) 76 77 fakeDB.GetWorkerReturns(savedWorker, true, nil) 78 }) 79 80 It("updates cached request host on subsequent call", func() { 81 Expect(err).To(HaveOccurred()) 82 Expect(err.Error()).To(ContainSubstring("some-error")) 83 84 Expect(fakeRoundTripper.RoundTripCallCount()).To(Equal(1)) 85 actualRequest := fakeRoundTripper.RoundTripArgsForCall(0) 86 Expect(actualRequest.URL.Host).To(Equal("some-worker-address")) 87 Expect(fakeDB.GetWorkerCallCount()).To(Equal(0)) 88 89 _, err := roundTripper.RoundTrip(&request) 90 Expect(err).To(HaveOccurred()) 91 92 Expect(fakeDB.GetWorkerCallCount()).To(Equal(1)) 93 Expect(fakeRoundTripper.RoundTripCallCount()).To(Equal(2)) 94 actualRequest = fakeRoundTripper.RoundTripArgsForCall(1) 95 Expect(actualRequest.URL.Host).To(Equal("some-new-worker-address")) 96 }) 97 98 Context("when the lookup of the worker in the db errors", func() { 99 var expectedErr error 100 BeforeEach(func() { 101 expectedErr = errors.New("some-db-error") 102 fakeDB.GetWorkerReturns(nil, true, expectedErr) 103 }) 104 105 It("throws an error", func() { 106 _, err := roundTripper.RoundTrip(&request) 107 Expect(err).To(HaveOccurred()) 108 Expect(err.Error()).To(ContainSubstring(expectedErr.Error())) 109 }) 110 }) 111 112 Context("when the worker is in the DB and the garden addr is empty", func() { 113 BeforeEach(func() { 114 runningWorker := new(dbfakes.FakeWorker) 115 runningWorker.StateReturns(db.WorkerStateStalled) 116 runningWorker.GardenAddrReturns(nil) 117 118 fakeDB.GetWorkerReturns(runningWorker, true, nil) 119 }) 120 121 It("throws a descriptive error", func() { 122 _, err := roundTripper.RoundTrip(&request) 123 Expect(err).To(MatchError("worker 'some-worker' is unreachable (state is 'stalled')")) 124 }) 125 }) 126 127 Context("when the worker is not found in the db", func() { 128 BeforeEach(func() { 129 fakeDB.GetWorkerReturns(nil, false, nil) 130 }) 131 132 It("throws an error", func() { 133 _, err := roundTripper.RoundTrip(&request) 134 Expect(err).To(HaveOccurred()) 135 Expect(err).To(Equal(transport.WorkerMissingError{WorkerName: "some-worker"})) 136 }) 137 }) 138 }) 139 })