github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/api/cloudcontroller/cloud_controller_connection_test.go (about) 1 package cloudcontroller_test 2 3 import ( 4 "fmt" 5 "net/http" 6 "runtime" 7 "strings" 8 9 . "code.cloudfoundry.org/cli/api/cloudcontroller" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 . "github.com/onsi/gomega/ghttp" 14 ) 15 16 type DummyResponse struct { 17 Val1 string `json:"val1"` 18 Val2 int `json:"val2"` 19 Val3 interface{} `json:"val3,omitempty"` 20 } 21 22 var _ = Describe("Cloud Controller Connection", func() { 23 var connection *CloudControllerConnection 24 25 BeforeEach(func() { 26 connection = NewConnection(Config{SkipSSLValidation: true}) 27 }) 28 29 Describe("Make", func() { 30 Describe("Data Unmarshalling", func() { 31 var request *Request 32 33 BeforeEach(func() { 34 response := `{ 35 "val1":"2.59.0", 36 "val2":2, 37 "val3":1111111111111111111 38 }` 39 server.AppendHandlers( 40 CombineHandlers( 41 VerifyRequest(http.MethodGet, "/v2/foo", ""), 42 RespondWith(http.StatusOK, response), 43 ), 44 ) 45 46 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 47 Expect(err).ToNot(HaveOccurred()) 48 request = &Request{Request: req} 49 }) 50 51 When("passed a response with a result set", func() { 52 It("unmarshals the data into a struct", func() { 53 var body DummyResponse 54 response := Response{ 55 DecodeJSONResponseInto: &body, 56 } 57 58 err := connection.Make(request, &response) 59 Expect(err).NotTo(HaveOccurred()) 60 61 Expect(body.Val1).To(Equal("2.59.0")) 62 Expect(body.Val2).To(Equal(2)) 63 }) 64 65 It("keeps numbers unmarshalled to interfaces as interfaces", func() { 66 var body DummyResponse 67 response := Response{ 68 DecodeJSONResponseInto: &body, 69 } 70 71 err := connection.Make(request, &response) 72 Expect(err).NotTo(HaveOccurred()) 73 Expect(fmt.Sprint(body.Val3)).To(Equal("1111111111111111111")) 74 }) 75 }) 76 77 When("passed an empty response", func() { 78 It("skips the unmarshalling step", func() { 79 var response Response 80 err := connection.Make(request, &response) 81 Expect(err).NotTo(HaveOccurred()) 82 Expect(response.DecodeJSONResponseInto).To(BeNil()) 83 }) 84 }) 85 }) 86 87 Describe("HTTP Response", func() { 88 var request *Request 89 90 BeforeEach(func() { 91 response := `{}` 92 server.AppendHandlers( 93 CombineHandlers( 94 VerifyRequest(http.MethodGet, "/v2/foo", ""), 95 RespondWith(http.StatusOK, response), 96 ), 97 ) 98 99 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 100 Expect(err).ToNot(HaveOccurred()) 101 request = &Request{Request: req} 102 }) 103 104 It("returns the status", func() { 105 response := Response{} 106 107 err := connection.Make(request, &response) 108 Expect(err).NotTo(HaveOccurred()) 109 110 Expect(response.HTTPResponse.Status).To(Equal("200 OK")) 111 }) 112 }) 113 114 Describe("Response Headers", func() { 115 Describe("Location", func() { 116 BeforeEach(func() { 117 server.AppendHandlers( 118 CombineHandlers( 119 VerifyRequest(http.MethodGet, "/v2/foo"), 120 RespondWith(http.StatusAccepted, "{}", http.Header{"Location": {"/v2/some-location"}}), 121 ), 122 ) 123 }) 124 125 It("returns the location in the ResourceLocationURL", func() { 126 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 127 Expect(err).ToNot(HaveOccurred()) 128 request := &Request{Request: req} 129 130 var response Response 131 err = connection.Make(request, &response) 132 Expect(err).NotTo(HaveOccurred()) 133 134 Expect(server.ReceivedRequests()).To(HaveLen(1)) 135 Expect(response.ResourceLocationURL).To(Equal("/v2/some-location")) 136 }) 137 }) 138 Describe("X-Cf-Warnings", func() { 139 When("there are warnings", func() { 140 BeforeEach(func() { 141 server.AppendHandlers( 142 CombineHandlers( 143 VerifyRequest(http.MethodGet, "/v2/foo"), 144 RespondWith(http.StatusOK, "{}", http.Header{"X-Cf-Warnings": {"42,+Ed+McMann,+the+1942+doggers,a%2Cb"}}), 145 ), 146 ) 147 }) 148 149 It("returns them in Response", func() { 150 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 151 Expect(err).ToNot(HaveOccurred()) 152 request := &Request{Request: req} 153 154 var response Response 155 err = connection.Make(request, &response) 156 Expect(err).NotTo(HaveOccurred()) 157 158 Expect(server.ReceivedRequests()).To(HaveLen(1)) 159 160 warnings := response.Warnings 161 Expect(warnings).ToNot(BeNil()) 162 Expect(warnings).To(HaveLen(4)) 163 Expect(warnings).To(ContainElement("42")) 164 Expect(warnings).To(ContainElement("Ed McMann")) 165 Expect(warnings).To(ContainElement("the 1942 doggers")) 166 Expect(warnings).To(ContainElement("a,b")) 167 }) 168 }) 169 170 When("there are warnings using multi-value header", func() { 171 BeforeEach(func() { 172 server.AppendHandlers( 173 CombineHandlers( 174 VerifyRequest(http.MethodGet, "/v2/foo"), 175 RespondWith(http.StatusOK, "{}", http.Header{"X-Cf-Warnings": { 176 "42,+Ed+McMann,+the+1942+doggers,a%2Cb", 177 "something,simpler", 178 }}), 179 ), 180 ) 181 }) 182 183 It("returns them in Response", func() { 184 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 185 Expect(err).ToNot(HaveOccurred()) 186 request := &Request{Request: req} 187 188 var response Response 189 err = connection.Make(request, &response) 190 Expect(err).NotTo(HaveOccurred()) 191 192 Expect(server.ReceivedRequests()).To(HaveLen(1)) 193 194 warnings := response.Warnings 195 Expect(warnings).ToNot(BeNil()) 196 Expect(warnings).To(HaveLen(6)) 197 Expect(warnings).To(ContainElement("42")) 198 Expect(warnings).To(ContainElement("Ed McMann")) 199 Expect(warnings).To(ContainElement("the 1942 doggers")) 200 Expect(warnings).To(ContainElement("a,b")) 201 Expect(warnings).To(ContainElement("something")) 202 Expect(warnings).To(ContainElement("simpler")) 203 }) 204 }) 205 206 When("there are no warnings", func() { 207 BeforeEach(func() { 208 server.AppendHandlers( 209 CombineHandlers( 210 VerifyRequest(http.MethodGet, "/v2/foo"), 211 RespondWith(http.StatusOK, "{}"), 212 ), 213 ) 214 }) 215 216 It("returns them in Response", func() { 217 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 218 Expect(err).ToNot(HaveOccurred()) 219 request := &Request{Request: req} 220 221 var response Response 222 err = connection.Make(request, &response) 223 Expect(err).NotTo(HaveOccurred()) 224 225 Expect(response.Warnings).To(BeEmpty()) 226 Expect(server.ReceivedRequests()).To(HaveLen(1)) 227 }) 228 }) 229 }) 230 }) 231 232 Describe("Errors", func() { 233 When("the server does not exist", func() { 234 BeforeEach(func() { 235 connection = NewConnection(Config{}) 236 }) 237 238 It("returns a RequestError", func() { 239 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", "http://garbledyguk.com"), nil) 240 Expect(err).ToNot(HaveOccurred()) 241 request := &Request{Request: req} 242 243 var response Response 244 err = connection.Make(request, &response) 245 Expect(err).To(HaveOccurred()) 246 247 requestErr, ok := err.(ccerror.RequestError) 248 Expect(ok).To(BeTrue()) 249 Expect(requestErr.Error()).To(MatchRegexp(".*http://garbledyguk.com/v2/foo.*[nN]o such host")) 250 }) 251 }) 252 253 When("the server does not have a verified certificate", func() { 254 Context("skipSSLValidation is false", func() { 255 BeforeEach(func() { 256 server.AppendHandlers( 257 CombineHandlers( 258 VerifyRequest(http.MethodGet, "/v2/foo"), 259 ), 260 ) 261 262 connection = NewConnection(Config{}) 263 }) 264 265 It("returns a UnverifiedServerError", func() { 266 req, err := http.NewRequest(http.MethodGet, server.URL(), nil) 267 Expect(err).ToNot(HaveOccurred()) 268 request := &Request{Request: req} 269 270 var response Response 271 err = connection.Make(request, &response) 272 Expect(err).To(MatchError(ccerror.UnverifiedServerError{URL: server.URL()})) 273 }) 274 }) 275 }) 276 277 When("the server's certificate does not match the hostname", func() { 278 Context("skipSSLValidation is false", func() { 279 BeforeEach(func() { 280 if runtime.GOOS == "windows" { 281 Skip("ssl validation has a different order on windows, will not be returned properly") 282 } 283 server.AppendHandlers( 284 CombineHandlers( 285 VerifyRequest(http.MethodGet, "/"), 286 ), 287 ) 288 289 connection = NewConnection(Config{}) 290 }) 291 292 // loopback.cli.fun is a custom DNS record setup to point to 127.0.0.1 293 It("returns a SSLValidationHostnameError", func() { 294 altHostURL := strings.Replace(server.URL(), "127.0.0.1", "loopback.cli.fun", -1) 295 req, err := http.NewRequest(http.MethodGet, altHostURL, nil) 296 Expect(err).ToNot(HaveOccurred()) 297 request := &Request{Request: req} 298 299 var response Response 300 err = connection.Make(request, &response) 301 Expect(err).To(MatchError(ccerror.SSLValidationHostnameError{ 302 Message: "x509: certificate is valid for example.com, not loopback.cli.fun", 303 })) 304 }) 305 }) 306 }) 307 308 Describe("RawHTTPStatusError", func() { 309 var ccResponse string 310 BeforeEach(func() { 311 ccResponse = `{ 312 "code": 90004, 313 "description": "The service binding could not be found: some-guid", 314 "error_code": "CF-ServiceBindingNotFound" 315 }` 316 317 server.AppendHandlers( 318 CombineHandlers( 319 VerifyRequest(http.MethodGet, "/v2/foo"), 320 RespondWith(http.StatusNotFound, ccResponse, http.Header{"X-Vcap-Request-Id": {"6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f"}}), 321 ), 322 ) 323 }) 324 325 It("returns a CCRawResponse", func() { 326 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/foo", server.URL()), nil) 327 Expect(err).ToNot(HaveOccurred()) 328 request := &Request{Request: req} 329 330 var response Response 331 err = connection.Make(request, &response) 332 Expect(err).To(MatchError(ccerror.RawHTTPStatusError{ 333 StatusCode: http.StatusNotFound, 334 RawResponse: []byte(ccResponse), 335 RequestIDs: []string{"6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f"}, 336 })) 337 338 Expect(server.ReceivedRequests()).To(HaveLen(1)) 339 }) 340 }) 341 }) 342 }) 343 })