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  })