github.com/willmadison/cli@v6.40.1-0.20181018160101-29d5937903ff+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 20 client *Client 21 ) 22 23 Describe("Make", func() { 24 BeforeEach(func() { 25 serverResponse = `{ 26 "code": 777, 27 "description": "SomeCC Error Message", 28 "error_code": "CF-SomeError" 29 }` 30 31 client = NewTestClient() 32 }) 33 34 JustBeforeEach(func() { 35 server.AppendHandlers( 36 CombineHandlers( 37 VerifyRequest(http.MethodGet, "/v2/apps"), 38 RespondWith(serverResponseCode, serverResponse, http.Header{ 39 "X-Vcap-Request-Id": { 40 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 41 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 42 }, 43 }, 44 ), 45 ), 46 ) 47 }) 48 49 When("we can't unmarshal the response successfully", func() { 50 BeforeEach(func() { 51 serverResponse = "I am not unmarshallable" 52 serverResponseCode = http.StatusNotFound 53 }) 54 55 It("returns an unknown http source error", func() { 56 _, _, err := client.GetApplications() 57 Expect(err).To(MatchError(ccerror.UnknownHTTPSourceError{StatusCode: serverResponseCode, RawResponse: []byte(serverResponse)})) 58 }) 59 }) 60 61 When("the error is from the cloud controller", func() { 62 When("the error is a 4XX error", func() { 63 Context("(400) Bad Request", func() { 64 BeforeEach(func() { 65 serverResponseCode = http.StatusBadRequest 66 }) 67 68 Context("generic 400", func() { 69 BeforeEach(func() { 70 serverResponse = `{ 71 "description": "bad request", 72 "error_code": "CF-BadRequest" 73 }` 74 }) 75 76 It("returns a BadRequestError", func() { 77 _, _, err := client.GetApplications() 78 Expect(err).To(MatchError(ccerror.BadRequestError{ 79 Message: "bad request", 80 })) 81 }) 82 }) 83 84 When("a not staged error is encountered", func() { 85 BeforeEach(func() { 86 serverResponse = `{ 87 "description": "App has not finished staging", 88 "error_code": "CF-NotStaged" 89 }` 90 }) 91 92 It("returns a NotStagedError", func() { 93 _, _, err := client.GetApplications() 94 Expect(err).To(MatchError(ccerror.NotStagedError{ 95 Message: "App has not finished staging", 96 })) 97 }) 98 }) 99 100 When("an instances error is encountered", func() { 101 BeforeEach(func() { 102 serverResponse = `{ 103 "description": "instances went bananas", 104 "error_code": "CF-InstancesError" 105 }` 106 }) 107 108 It("returns an InstancesError", func() { 109 _, _, err := client.GetApplications() 110 Expect(err).To(MatchError(ccerror.InstancesError{ 111 Message: "instances went bananas", 112 })) 113 }) 114 }) 115 116 When("creating a relation that is invalid", func() { 117 BeforeEach(func() { 118 serverResponse = `{ 119 "code": 1002, 120 "description": "The requested app relation is invalid: the app and route must belong to the same space", 121 "error_code": "CF-InvalidRelation" 122 }` 123 }) 124 125 It("returns an InvalidRelationError", func() { 126 _, _, err := client.GetApplications() 127 Expect(err).To(MatchError(ccerror.InvalidRelationError{ 128 Message: "The requested app relation is invalid: the app and route must belong to the same space", 129 })) 130 }) 131 }) 132 133 Context("getting stats for a stopped app", func() { 134 BeforeEach(func() { 135 serverResponse = `{ 136 "code": 200003, 137 "description": "Could not fetch stats for stopped app: some-app", 138 "error_code": "CF-AppStoppedStatsError" 139 }` 140 }) 141 142 It("returns an AppStoppedStatsError", func() { 143 _, _, err := client.GetApplications() 144 Expect(err).To(MatchError(ccerror.ApplicationStoppedStatsError{ 145 Message: "Could not fetch stats for stopped app: some-app", 146 })) 147 }) 148 }) 149 150 When("creating a buildpack with nil stack that already exists", func() { 151 BeforeEach(func() { 152 serverResponse = `{ 153 "description": "Buildpack is invalid: stack unique", 154 "error_code": "CF-BuildpackInvalid", 155 "code": 290003 156 }` 157 }) 158 159 It("returns an BuildpackAlreadyExistsWithoutStackError", func() { 160 _, _, err := client.GetApplications() 161 Expect(err).To(MatchError(ccerror.BuildpackAlreadyExistsWithoutStackError{ 162 Message: "Buildpack is invalid: stack unique", 163 })) 164 }) 165 }) 166 167 When("creating a buildpack causes a name collision", func() { 168 BeforeEach(func() { 169 serverResponse = `{ 170 "code": 290001, 171 "description": "The buildpack name is already in use: foo", 172 "error_code": "CF-BuildpackNameTaken" 173 }` 174 }) 175 176 It("returns an BuildpackNameTakenError", func() { 177 _, _, err := client.GetApplications() 178 Expect(err).To(MatchError(ccerror.BuildpackNameTakenError{ 179 Message: "The buildpack name is already in use: foo", 180 })) 181 }) 182 }) 183 184 When("creating an organization fails because the name is taken", func() { 185 BeforeEach(func() { 186 serverResponse = `{ 187 "code": 30002, 188 "description": "The organization name is taken: potato", 189 "error_code": "CF-OrganizationNameTaken" 190 }` 191 }) 192 193 It("returns a OrganizationNameTakenError", func() { 194 _, _, err := client.GetApplications() 195 Expect(err).To(MatchError(ccerror.OrganizationNameTakenError{ 196 Message: "The organization name is taken: potato", 197 })) 198 }) 199 }) 200 201 When("creating a space fails because the name is taken", func() { 202 BeforeEach(func() { 203 serverResponse = `{ 204 "code": 40002, 205 "description": "The app space name is taken: potato", 206 "error_code": "CF-SpaceNameTaken" 207 }` 208 }) 209 210 It("returns a SpaceNameTakenError", func() { 211 _, _, err := client.GetApplications() 212 if e, ok := err.(ccerror.UnknownHTTPSourceError); ok { 213 fmt.Printf("TV %s", string(e.RawResponse)) 214 } 215 Expect(err).To(MatchError(ccerror.SpaceNameTakenError{ 216 Message: "The app space name is taken: potato", 217 })) 218 }) 219 }) 220 }) 221 222 Context("(401) Unauthorized", func() { 223 BeforeEach(func() { 224 serverResponseCode = http.StatusUnauthorized 225 }) 226 227 Context("generic 401", func() { 228 It("returns a UnauthorizedError", func() { 229 _, _, err := client.GetApplications() 230 Expect(err).To(MatchError(ccerror.UnauthorizedError{Message: "SomeCC Error Message"})) 231 }) 232 }) 233 234 Context("invalid token", func() { 235 BeforeEach(func() { 236 serverResponse = `{ 237 "code": 1000, 238 "description": "Invalid Auth Token", 239 "error_code": "CF-InvalidAuthToken" 240 }` 241 }) 242 243 It("returns an InvalidAuthTokenError", func() { 244 _, _, err := client.GetApplications() 245 Expect(err).To(MatchError(ccerror.InvalidAuthTokenError{Message: "Invalid Auth Token"})) 246 }) 247 }) 248 }) 249 250 Context("(403) Forbidden", func() { 251 BeforeEach(func() { 252 serverResponseCode = http.StatusForbidden 253 }) 254 255 It("returns a ForbiddenError", func() { 256 _, _, err := client.GetApplications() 257 Expect(err).To(MatchError(ccerror.ForbiddenError{Message: "SomeCC Error Message"})) 258 }) 259 }) 260 261 Context("(404) Not Found", func() { 262 BeforeEach(func() { 263 serverResponseCode = http.StatusNotFound 264 }) 265 266 When("the error is a json response from the cloud controller", func() { 267 It("returns a ResourceNotFoundError", func() { 268 _, _, err := client.GetApplications() 269 Expect(err).To(MatchError(ccerror.ResourceNotFoundError{Message: "SomeCC Error Message"})) 270 }) 271 }) 272 }) 273 274 Context("(422) Unprocessable Entity", func() { 275 BeforeEach(func() { 276 serverResponseCode = http.StatusUnprocessableEntity 277 }) 278 279 Context("generic Unprocessable entity", func() { 280 It("returns a UnprocessableEntityError", func() { 281 _, _, err := client.GetApplications() 282 Expect(err).To(MatchError(ccerror.UnprocessableEntityError{Message: "SomeCC Error Message"})) 283 }) 284 }) 285 286 When("creating a buildpack causes a name and stack collision", func() { 287 BeforeEach(func() { 288 serverResponse = `{ 289 "code": 290000, 290 "description": "The buildpack name foo is already in use for the stack bar", 291 "error_code": "CF-BuildpackNameStackTaken" 292 }` 293 }) 294 295 It("returns an BuildpackAlreadyExistsForStackError", func() { 296 _, _, err := client.GetApplications() 297 Expect(err).To(MatchError(ccerror.BuildpackAlreadyExistsForStackError{ 298 Message: "The buildpack name foo is already in use for the stack bar", 299 })) 300 }) 301 }) 302 303 }) 304 305 Context("unhandled Error Codes", func() { 306 BeforeEach(func() { 307 serverResponseCode = http.StatusTeapot 308 }) 309 310 It("returns an UnexpectedResponseError", func() { 311 _, _, err := client.GetApplications() 312 Expect(err).To(MatchError(ccerror.V2UnexpectedResponseError{ 313 ResponseCode: http.StatusTeapot, 314 V2ErrorResponse: ccerror.V2ErrorResponse{ 315 Code: 777, 316 Description: "SomeCC Error Message", 317 ErrorCode: "CF-SomeError", 318 }, 319 RequestIDs: []string{ 320 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 321 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 322 }, 323 })) 324 }) 325 }) 326 }) 327 328 When("the error is a 5XX error", func() { 329 BeforeEach(func() { 330 serverResponseCode = http.StatusBadGateway 331 serverResponse = "I am some text" 332 }) 333 334 It("returns a V2UnexpectedResponseError with no json", func() { 335 _, _, err := client.GetApplications() 336 Expect(err).To(MatchError(ccerror.V2UnexpectedResponseError{ 337 ResponseCode: http.StatusBadGateway, 338 V2ErrorResponse: ccerror.V2ErrorResponse{ 339 Description: serverResponse, 340 }, 341 RequestIDs: []string{ 342 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95", 343 "6e0b4379-f5f7-4b2b-56b0-9ab7e96eed95::7445d9db-c31e-410d-8dc5-9f79ec3fc26f", 344 }, 345 })) 346 }) 347 }) 348 }) 349 }) 350 })