github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/api/cloudcontroller/ccv3/errors_test.go (about) 1 package ccv3_test 2 3 import ( 4 "net/http" 5 6 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 7 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 8 9 . "github.com/onsi/ginkgo" 10 . "github.com/onsi/gomega" 11 . "github.com/onsi/gomega/ghttp" 12 ) 13 14 var _ = Describe("Error Wrapper", func() { 15 var client *Client 16 17 BeforeEach(func() { 18 client = NewTestClient() 19 }) 20 21 Describe("Make", func() { 22 var ( 23 serverResponse string 24 serverResponseCode int 25 makeError error 26 ) 27 28 BeforeEach(func() { 29 serverResponse = ` 30 { 31 "errors": [ 32 { 33 "code": 777, 34 "detail": "SomeCC Error Message", 35 "title": "CF-SomeError" 36 } 37 ] 38 }` 39 40 }) 41 42 JustBeforeEach(func() { 43 server.AppendHandlers( 44 CombineHandlers( 45 VerifyRequest(http.MethodGet, "/v3/apps"), 46 RespondWith(serverResponseCode, serverResponse, http.Header{ 47 "X-Vcap-Request-Id": { 48 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 49 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 50 }, 51 }, 52 ), 53 ), 54 ) 55 56 _, _, makeError = client.GetApplications(nil) 57 }) 58 59 Context("when the error is not from the cloud controller", func() { 60 Context("and the raw status is 404", func() { 61 BeforeEach(func() { 62 serverResponseCode = http.StatusNotFound 63 serverResponse = "some not found message" 64 }) 65 It("returns a NotFoundError", func() { 66 Expect(makeError).To(MatchError(ccerror.NotFoundError{Message: serverResponse})) 67 }) 68 }) 69 70 Context("and the raw status is another error", func() { 71 BeforeEach(func() { 72 serverResponseCode = http.StatusTeapot 73 serverResponse = "418 I'm a teapot: Requested route ('some-url.com') does not exist." 74 }) 75 It("returns a RawHTTPStatusError", func() { 76 Expect(makeError).To(MatchError(ccerror.RawHTTPStatusError{ 77 StatusCode: http.StatusTeapot, 78 RawResponse: []byte(serverResponse), 79 RequestIDs: []string{ 80 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 81 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 82 }, 83 })) 84 }) 85 }) 86 }) 87 88 Context("when the error is from the cloud controller", func() { 89 Context("when an empty list of errors is returned", func() { 90 BeforeEach(func() { 91 serverResponseCode = http.StatusUnauthorized 92 serverResponse = `{ "errors": [] }` 93 }) 94 95 It("returns an UnexpectedResponseError", func() { 96 Expect(makeError).To(MatchError(ccerror.V3UnexpectedResponseError{ 97 ResponseCode: http.StatusUnauthorized, 98 V3ErrorResponse: ccerror.V3ErrorResponse{Errors: []ccerror.V3Error{}}, 99 })) 100 }) 101 }) 102 103 Context("(401) Unauthorized", func() { 104 BeforeEach(func() { 105 serverResponseCode = http.StatusUnauthorized 106 }) 107 108 Context("generic 401", func() { 109 It("returns a UnauthorizedError", func() { 110 Expect(makeError).To(MatchError(ccerror.UnauthorizedError{Message: "SomeCC Error Message"})) 111 }) 112 }) 113 114 Context("invalid token", func() { 115 BeforeEach(func() { 116 serverResponse = `{ 117 "errors": [ 118 { 119 "code": 1000, 120 "detail": "Invalid Auth Token", 121 "title": "CF-InvalidAuthToken" 122 } 123 ] 124 }` 125 }) 126 127 It("returns an InvalidAuthTokenError", func() { 128 Expect(makeError).To(MatchError(ccerror.InvalidAuthTokenError{Message: "Invalid Auth Token"})) 129 }) 130 }) 131 }) 132 133 Context("(403) Forbidden", func() { 134 BeforeEach(func() { 135 serverResponseCode = http.StatusForbidden 136 }) 137 138 It("returns a ForbiddenError", func() { 139 Expect(makeError).To(MatchError(ccerror.ForbiddenError{Message: "SomeCC Error Message"})) 140 }) 141 }) 142 143 Context("(404) Not Found", func() { 144 BeforeEach(func() { 145 serverResponseCode = http.StatusNotFound 146 }) 147 148 Context("when a process is not found", func() { 149 BeforeEach(func() { 150 serverResponse = ` 151 { 152 "errors": [ 153 { 154 "code": 10010, 155 "detail": "Process not found", 156 "title": "CF-ResourceNotFound" 157 } 158 ] 159 }` 160 }) 161 162 It("returns a ProcessNotFoundError", func() { 163 Expect(makeError).To(MatchError(ccerror.ProcessNotFoundError{})) 164 }) 165 }) 166 167 Context("when an instance is not found", func() { 168 BeforeEach(func() { 169 serverResponse = ` 170 { 171 "errors": [ 172 { 173 "code": 10010, 174 "detail": "Instance not found", 175 "title": "CF-ResourceNotFound" 176 } 177 ] 178 }` 179 }) 180 181 It("returns an InstanceNotFoundError", func() { 182 Expect(makeError).To(MatchError(ccerror.InstanceNotFoundError{})) 183 }) 184 }) 185 186 Context("when an application is not found", func() { 187 BeforeEach(func() { 188 serverResponse = ` 189 { 190 "errors": [ 191 { 192 "code": 10010, 193 "detail": "App not found", 194 "title": "CF-ResourceNotFound" 195 } 196 ] 197 }` 198 }) 199 200 It("returns an AppNotFoundError", func() { 201 Expect(makeError).To(MatchError(ccerror.ApplicationNotFoundError{})) 202 }) 203 }) 204 205 Context("when a droplet is not found", func() { 206 BeforeEach(func() { 207 serverResponse = ` 208 { 209 "errors": [ 210 { 211 "code": 10010, 212 "detail": "Droplet not found", 213 "title": "CF-ResourceNotFound" 214 } 215 ] 216 }` 217 }) 218 219 It("returns a DropletNotFoundError", func() { 220 Expect(makeError).To(MatchError(ccerror.DropletNotFoundError{})) 221 }) 222 }) 223 224 Context("generic not found", func() { 225 226 It("returns a ResourceNotFoundError", func() { 227 Expect(makeError).To(MatchError(ccerror.ResourceNotFoundError{Message: "SomeCC Error Message"})) 228 }) 229 }) 230 }) 231 232 Context("(422) Unprocessable Entity", func() { 233 BeforeEach(func() { 234 serverResponseCode = http.StatusUnprocessableEntity 235 serverResponse = ` 236 { 237 "errors": [ 238 { 239 "code": 10008, 240 "detail": "SomeCC Error Message", 241 "title": "CF-UnprocessableEntity" 242 } 243 ] 244 }` 245 }) 246 247 Context("when the name isn't unique to space", func() { 248 BeforeEach(func() { 249 serverResponse = ` 250 { 251 "errors": [ 252 { 253 "code": 10008, 254 "detail": "name must be unique in space", 255 "title": "CF-UnprocessableEntity" 256 } 257 ] 258 }` 259 }) 260 261 It("returns a NameNotUniqueInSpaceError", func() { 262 Expect(makeError).To(MatchError(ccerror.NameNotUniqueInSpaceError{})) 263 }) 264 }) 265 266 Context("when the buildpack is invalid", func() { 267 BeforeEach(func() { 268 serverResponse = ` 269 { 270 "errors": [ 271 { 272 "code": 10008, 273 "detail": "Buildpack must be an existing admin buildpack or a valid git URI", 274 "title": "CF-UnprocessableEntity" 275 } 276 ] 277 }` 278 }) 279 280 It("returns an InvalidBuildpackError", func() { 281 Expect(makeError).To(MatchError(ccerror.InvalidBuildpackError{})) 282 }) 283 }) 284 285 Context("when the detail describes something else", func() { 286 It("returns a UnprocessableEntityError", func() { 287 Expect(makeError).To(MatchError(ccerror.UnprocessableEntityError{Message: "SomeCC Error Message"})) 288 }) 289 }) 290 }) 291 292 Context("(503) Service Unavailable", func() { 293 BeforeEach(func() { 294 serverResponseCode = http.StatusServiceUnavailable 295 }) 296 297 It("returns a ServiceUnavailableError", func() { 298 Expect(makeError).To(MatchError(ccerror.ServiceUnavailableError{Message: "SomeCC Error Message"})) 299 }) 300 301 Context("when the title is 'CF-TaskWorkersUnavailable'", func() { 302 BeforeEach(func() { 303 serverResponse = `{ 304 "errors": [ 305 { 306 "code": 170020, 307 "detail": "Task workers are unavailable: Failed to open TCP connection to nsync.service.cf.internal:8787 (getaddrinfo: Name or service not known)", 308 "title": "CF-TaskWorkersUnavailable" 309 } 310 ] 311 }` 312 }) 313 314 It("returns a TaskWorkersUnavailableError", func() { 315 Expect(makeError).To(MatchError(ccerror.TaskWorkersUnavailableError{Message: "Task workers are unavailable: Failed to open TCP connection to nsync.service.cf.internal:8787 (getaddrinfo: Name or service not known)"})) 316 }) 317 }) 318 }) 319 320 Context("Unhandled Error Codes", func() { 321 BeforeEach(func() { 322 serverResponseCode = http.StatusTeapot 323 }) 324 325 It("returns an UnexpectedResponseError", func() { 326 Expect(makeError).To(MatchError(ccerror.V3UnexpectedResponseError{ 327 ResponseCode: http.StatusTeapot, 328 V3ErrorResponse: ccerror.V3ErrorResponse{ 329 Errors: []ccerror.V3Error{ 330 { 331 Code: 777, 332 Detail: "SomeCC Error Message", 333 Title: "CF-SomeError", 334 }, 335 }, 336 }, 337 RequestIDs: []string{ 338 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 339 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 340 }, 341 })) 342 }) 343 }) 344 }) 345 }) 346 })