github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/api/cloudcontroller/ccv2/errors_test.go (about) 1 package ccv2_test 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 8 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2" 9 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 . "github.com/onsi/gomega/ghttp" 13 ) 14 15 var _ = Describe("Error Wrapper", func() { 16 var ( 17 serverResponse string 18 serverResponseCode int 19 executeErr error 20 21 client *Client 22 ) 23 24 Describe("Make", func() { 25 BeforeEach(func() { 26 serverResponse = `{ 27 "code": 777, 28 "description": "SomeCC Error Message", 29 "error_code": "CF-SomeError" 30 }` 31 32 client = NewTestClient() 33 }) 34 35 JustBeforeEach(func() { 36 server.AppendHandlers( 37 CombineHandlers( 38 VerifyRequest(http.MethodGet, "/v2/apps"), 39 RespondWith(serverResponseCode, serverResponse, http.Header{ 40 "X-Vcap-Request-Id": { 41 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 42 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 43 }, 44 }, 45 ), 46 ), 47 ) 48 49 // Make a request to a CC endpoint - we stub the response, so the actual endpoint isn't relevant 50 _, _, executeErr = client.GetApplications() 51 }) 52 53 When("we can't unmarshal the response successfully", func() { 54 BeforeEach(func() { 55 serverResponse = "I am not unmarshallable" 56 }) 57 58 When("response code is 4XX", func() { 59 BeforeEach(func() { 60 serverResponseCode = http.StatusNotFound 61 }) 62 63 It("returns an unknown http source error", func() { 64 Expect(executeErr).To(MatchError(ccerror.UnknownHTTPSourceError{StatusCode: serverResponseCode, RawResponse: []byte(serverResponse)})) 65 }) 66 }) 67 68 When("response code is 5XX", func() { 69 BeforeEach(func() { 70 serverResponseCode = http.StatusBadGateway 71 }) 72 73 It("returns an unknown http source error", func() { 74 Expect(executeErr).To(MatchError(ccerror.UnknownHTTPSourceError{StatusCode: serverResponseCode, RawResponse: []byte(serverResponse)})) 75 }) 76 }) 77 }) 78 79 When("the error is from the cloud controller", func() { 80 When("the error is a 4XX error", func() { 81 Context("(400) Bad Request", func() { 82 BeforeEach(func() { 83 serverResponseCode = http.StatusBadRequest 84 }) 85 86 Context("generic 400", func() { 87 BeforeEach(func() { 88 serverResponse = `{ 89 "description": "bad request", 90 "error_code": "CF-BadRequest" 91 }` 92 }) 93 94 It("returns a BadRequestError", func() { 95 Expect(executeErr).To(MatchError(ccerror.BadRequestError{ 96 Message: "bad request", 97 })) 98 }) 99 }) 100 101 When("a not staged error is encountered", func() { 102 BeforeEach(func() { 103 serverResponse = `{ 104 "description": "App has not finished staging", 105 "error_code": "CF-NotStaged" 106 }` 107 }) 108 109 It("returns a NotStagedError", func() { 110 Expect(executeErr).To(MatchError(ccerror.NotStagedError{ 111 Message: "App has not finished staging", 112 })) 113 }) 114 }) 115 116 When("an instances error is encountered", func() { 117 BeforeEach(func() { 118 serverResponse = `{ 119 "description": "instances went bananas", 120 "error_code": "CF-InstancesError" 121 }` 122 }) 123 124 It("returns an InstancesError", func() { 125 Expect(executeErr).To(MatchError(ccerror.InstancesError{ 126 Message: "instances went bananas", 127 })) 128 }) 129 }) 130 131 When("creating a relation that is invalid", func() { 132 BeforeEach(func() { 133 serverResponse = `{ 134 "code": 1002, 135 "description": "The requested app relation is invalid: the app and route must belong to the same space", 136 "error_code": "CF-InvalidRelation" 137 }` 138 }) 139 140 It("returns an InvalidRelationError", func() { 141 Expect(executeErr).To(MatchError(ccerror.InvalidRelationError{ 142 Message: "The requested app relation is invalid: the app and route must belong to the same space", 143 })) 144 }) 145 }) 146 147 Context("getting stats for a stopped app", func() { 148 BeforeEach(func() { 149 serverResponse = `{ 150 "code": 200003, 151 "description": "Could not fetch stats for stopped app: some-app", 152 "error_code": "CF-AppStoppedStatsError" 153 }` 154 }) 155 156 It("returns an AppStoppedStatsError", func() { 157 Expect(executeErr).To(MatchError(ccerror.ApplicationStoppedStatsError{ 158 Message: "Could not fetch stats for stopped app: some-app", 159 })) 160 }) 161 }) 162 163 When("creating an invalid buildpack", func() { 164 BeforeEach(func() { 165 serverResponse = `{ 166 "description": "Buildpack is invalid: goofy is a dog", 167 "error_code": "CF-BuildpackInvalid", 168 "code": 290003 169 }` 170 }) 171 172 It("returns an BuildpackInvalidError", func() { 173 Expect(executeErr).To(MatchError(ccerror.BuildpackInvalidError{ 174 Message: "Buildpack is invalid: goofy is a dog", 175 })) 176 }) 177 }) 178 179 When("creating a buildpack causes a name collision", func() { 180 BeforeEach(func() { 181 serverResponse = `{ 182 "code": 290001, 183 "description": "The buildpack name is already in use: foo", 184 "error_code": "CF-BuildpackNameTaken" 185 }` 186 }) 187 188 It("returns an BuildpackNameTakenError", func() { 189 Expect(executeErr).To(MatchError(ccerror.BuildpackNameTakenError{ 190 Message: "The buildpack name is already in use: foo", 191 })) 192 }) 193 }) 194 195 When("creating an organization fails because the name is taken", func() { 196 BeforeEach(func() { 197 serverResponse = `{ 198 "code": 30002, 199 "description": "The organization name is taken: potato", 200 "error_code": "CF-OrganizationNameTaken" 201 }` 202 }) 203 204 It("returns a OrganizationNameTakenError", func() { 205 Expect(executeErr).To(MatchError(ccerror.OrganizationNameTakenError{})) 206 }) 207 }) 208 209 When("creating a space fails because the name is taken", func() { 210 BeforeEach(func() { 211 serverResponse = `{ 212 "code": 40002, 213 "description": "The app space name is taken: potato", 214 "error_code": "CF-SpaceNameTaken" 215 }` 216 }) 217 218 It("returns a SpaceNameTakenError", func() { 219 if e, ok := executeErr.(ccerror.UnknownHTTPSourceError); ok { 220 fmt.Printf("TV %s", string(e.RawResponse)) 221 } 222 Expect(executeErr).To(MatchError(ccerror.SpaceNameTakenError{ 223 Message: "The app space name is taken: potato", 224 })) 225 }) 226 }) 227 228 When("creating a service instance fails because the name is taken", func() { 229 BeforeEach(func() { 230 serverResponse = `{ 231 "code": 40002, 232 "description": "Service instance name is taken: potato", 233 "error_code": "CF-ServiceInstanceNameTaken" 234 }` 235 }) 236 237 It("returns a ServiceInstanceNameTakenError", func() { 238 Expect(executeErr).To(MatchError(ccerror.ServiceInstanceNameTakenError{ 239 Message: "Service instance name is taken: potato", 240 })) 241 }) 242 }) 243 244 When("creating a service plan visibility fails because it already exists", func() { 245 BeforeEach(func() { 246 serverResponse = `{ 247 "code": 40002, 248 "description": "Service plan visibility already exists", 249 "error_code": "CF-ServicePlanVisibilityAlreadyExists" 250 }` 251 }) 252 253 It("returns a ServicePlanVisibilityExistsError", func() { 254 Expect(executeErr).To(MatchError(ccerror.ServicePlanVisibilityExistsError{ 255 Message: "Service plan visibility already exists", 256 })) 257 }) 258 }) 259 }) 260 261 Context("(401) Unauthorized", func() { 262 BeforeEach(func() { 263 serverResponseCode = http.StatusUnauthorized 264 }) 265 266 Context("generic 401", func() { 267 It("returns a UnauthorizedError", func() { 268 Expect(executeErr).To(MatchError(ccerror.UnauthorizedError{Message: "SomeCC Error Message"})) 269 }) 270 }) 271 272 Context("invalid token", func() { 273 BeforeEach(func() { 274 serverResponse = `{ 275 "code": 1000, 276 "description": "Invalid Auth Token", 277 "error_code": "CF-InvalidAuthToken" 278 }` 279 }) 280 281 It("returns an InvalidAuthTokenError", func() { 282 Expect(executeErr).To(MatchError(ccerror.InvalidAuthTokenError{Message: "Invalid Auth Token"})) 283 }) 284 }) 285 }) 286 287 Context("(403) Forbidden", func() { 288 BeforeEach(func() { 289 serverResponseCode = http.StatusForbidden 290 }) 291 292 It("returns a ForbiddenError", func() { 293 Expect(executeErr).To(MatchError(ccerror.ForbiddenError{Message: "SomeCC Error Message"})) 294 }) 295 }) 296 297 Context("(404) Not Found", func() { 298 BeforeEach(func() { 299 serverResponseCode = http.StatusNotFound 300 }) 301 302 When("the error is a json response from the cloud controller", func() { 303 It("returns a ResourceNotFoundError", func() { 304 Expect(executeErr).To(MatchError(ccerror.ResourceNotFoundError{Message: "SomeCC Error Message"})) 305 }) 306 }) 307 }) 308 309 Context("(422) Unprocessable Entity", func() { 310 BeforeEach(func() { 311 serverResponseCode = http.StatusUnprocessableEntity 312 }) 313 314 Context("generic Unprocessable entity", func() { 315 It("returns a UnprocessableEntityError", func() { 316 Expect(executeErr).To(MatchError(ccerror.UnprocessableEntityError{Message: "SomeCC Error Message"})) 317 }) 318 }) 319 320 When("creating a buildpack causes a name and stack collision", func() { 321 BeforeEach(func() { 322 serverResponse = `{ 323 "code": 290000, 324 "description": "The buildpack name foo is already in use for the stack bar", 325 "error_code": "CF-BuildpackNameStackTaken" 326 }` 327 }) 328 329 It("returns an BuildpackAlreadyExistsForStackError", func() { 330 Expect(executeErr).To(MatchError(ccerror.BuildpackAlreadyExistsForStackError{ 331 Message: "The buildpack name foo is already in use for the stack bar", 332 })) 333 }) 334 }) 335 336 }) 337 338 Context("unhandled Error Codes", func() { 339 BeforeEach(func() { 340 serverResponseCode = http.StatusTeapot 341 }) 342 343 It("returns an UnexpectedResponseError", func() { 344 Expect(executeErr).To(MatchError(ccerror.V2UnexpectedResponseError{ 345 ResponseCode: http.StatusTeapot, 346 V2ErrorResponse: ccerror.V2ErrorResponse{ 347 Code: 777, 348 Description: "SomeCC Error Message", 349 ErrorCode: "CF-SomeError", 350 }, 351 RequestIDs: []string{ 352 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 353 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 354 }, 355 })) 356 }) 357 }) 358 }) 359 360 When("the error is a 5XX error", func() { 361 BeforeEach(func() { 362 serverResponseCode = http.StatusInternalServerError 363 serverResponse = "{}" 364 }) 365 366 Context("(502) Bad Gateway", func() { 367 BeforeEach(func() { 368 serverResponseCode = http.StatusBadGateway 369 }) 370 371 When("the service broker catalog is invalid", func() { 372 BeforeEach(func() { 373 serverResponse = `{ 374 "description": "Service broker catalog is invalid: \nService overview-service\n Service dashboard client id must be unique\n", 375 "error_code": "CF-ServiceBrokerCatalogInvalid", 376 "code": 270012 377 }` 378 }) 379 380 It("returns a ServiceBrokerCatalogInvalidError", func() { 381 Expect(executeErr).To(MatchError(ccerror.ServiceBrokerCatalogInvalidError{ 382 Message: "Service broker catalog is invalid: \nService overview-service\n Service dashboard client id must be unique\n", 383 })) 384 }) 385 }) 386 387 When("the service broker rejected the request", func() { 388 BeforeEach(func() { 389 serverResponse = `{ 390 "description": "The service broker rejected the request to https://broker.example.com/v2/service_instances/1a3794e9-7ddf-4cae-b66a-6a0453c85a3e?accepts_incomplete=true. Status Code: 400 Bad Request, Body: instance requires property \"name\"", 391 "error_code": "CF-ServiceBrokerRequestRejected", 392 "code": 10001 393 }` 394 }) 395 396 It("returns a ServiceBrokerRequestRejectedError", func() { 397 Expect(executeErr).To(MatchError(ccerror.ServiceBrokerRequestRejectedError{ 398 Message: `The service broker rejected the request to https://broker.example.com/v2/service_instances/1a3794e9-7ddf-4cae-b66a-6a0453c85a3e?accepts_incomplete=true. Status Code: 400 Bad Request, Body: instance requires property "name"`, 399 })) 400 }) 401 }) 402 403 When("the service broker responded with bad response", func() { 404 BeforeEach(func() { 405 serverResponse = `{ 406 "description": "Service broker error", 407 "error_code": "CF-ServiceBrokerBadResponse", 408 "code": 10001, 409 "http": { 410 "uri": "https://broker.url/v2/service_instances/593fe03a-3eda-4a53-93ed-aa30f309b120?accepts_incomplete=true", 411 "method": "PUT", 412 "status": 500 413 } 414 }` 415 }) 416 417 It("returns a ServiceBrokerBadResponseError", func() { 418 Expect(executeErr).To(MatchError(ccerror.ServiceBrokerBadResponseError{ 419 Message: `Service broker error`, 420 })) 421 }) 422 }) 423 424 When("the error_code is unknown", func() { 425 It("returns a V2UnexpectedResponseError with no json", func() { 426 Expect(executeErr).To(MatchError(ccerror.V2UnexpectedResponseError{ 427 ResponseCode: http.StatusBadGateway, 428 V2ErrorResponse: ccerror.V2ErrorResponse{ 429 Description: serverResponse, 430 }, 431 RequestIDs: []string{ 432 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 433 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 434 }, 435 })) 436 }) 437 }) 438 }) 439 440 Context("unhandled error codes", func() { 441 It("returns a V2UnexpectedResponseError with no json", func() { 442 Expect(executeErr).To(MatchError(ccerror.V2UnexpectedResponseError{ 443 ResponseCode: http.StatusInternalServerError, 444 V2ErrorResponse: ccerror.V2ErrorResponse{ 445 Description: serverResponse, 446 }, 447 RequestIDs: []string{ 448 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 449 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 450 }, 451 })) 452 }) 453 }) 454 }) 455 }) 456 }) 457 })