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