Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix sm response parsing #309

Merged
merged 12 commits into from
Jul 27, 2023
33 changes: 14 additions & 19 deletions client/sm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@ type Client interface {
// It should be used only in case there is no already implemented method for such an operation
Call(method string, smpath string, body io.Reader, q *Parameters) (*http.Response, error)
}

type ServiceManagerError struct {
Message string
Description string
StatusCode int
BrokerError *api.HTTPStatusCodeError `json:"broker_error,omitempty"`
}

func (e *ServiceManagerError) Error() string {
return e.Message
return e.Description
}

type serviceManagerClient struct {
Expand Down Expand Up @@ -312,7 +313,7 @@ func (client *serviceManagerClient) register(resource interface{}, url string, q
case http.StatusAccepted:
return response.Header.Get("Location"), nil
default:
return "", handleFailedResponse(response)
return "", handleResponseError(response)
}
}

Expand All @@ -331,7 +332,7 @@ func (client *serviceManagerClient) delete(url string, q *Parameters, user strin
case http.StatusAccepted:
return response.Header.Get("Location"), nil
default:
return "", handleFailedResponse(response)
return "", handleResponseError(response)
}
}

Expand All @@ -342,7 +343,7 @@ func (client *serviceManagerClient) get(result interface{}, url string, q *Param
}

if response.StatusCode != http.StatusOK {
return handleFailedResponse(response)
return handleResponseError(response)
}
return httputil.UnmarshalResponse(response, &result)
}
Expand All @@ -364,7 +365,7 @@ func (client *serviceManagerClient) update(resource interface{}, url string, id
case http.StatusAccepted:
return response.Header.Get("Location"), nil
default:
return "", handleFailedResponse(response)
return "", handleResponseError(response)
}
}

Expand All @@ -390,22 +391,14 @@ func (client *serviceManagerClient) executeShareInstanceRequest(shouldShare bool
response, err := client.callWithUser(http.MethodPatch, types.ServiceInstancesURL+"/"+id, buffer, nil, user)
if response.StatusCode != http.StatusOK {
if err == nil {
return handleFailedResponse(response)
return handleResponseError(response)
}
return httputil.UnmarshalResponse(response, err)
}

return nil
}

func handleFailedResponse(response *http.Response) error {
err := handleResponseError(response)
return &ServiceManagerError{
StatusCode: response.StatusCode,
Message: err.Error(),
}
}

func (client *serviceManagerClient) Call(method string, smpath string, body io.Reader, q *Parameters) (*http.Response, error) {
return client.callWithUser(method, smpath, body, q, "")
}
Expand Down Expand Up @@ -541,11 +534,13 @@ func handleResponseError(response *http.Response) error {
body = []byte(fmt.Sprintf("error reading response body: %s", err))
}

err = fmt.Errorf("StatusCode: %d Body: %s", response.StatusCode, body)
if response.Request != nil {
return fmt.Errorf("request %s %s failed: %s", response.Request.Method, response.Request.URL, err)
smError := &ServiceManagerError{
StatusCode: response.StatusCode,
Description: "",
}
return fmt.Errorf("request failed: %s", err)
_ = json.Unmarshal(body, &smError)

return smError
}

func bodyToBytes(closer io.ReadCloser) ([]byte, error) {
Expand Down
101 changes: 37 additions & 64 deletions client/sm/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ var _ = Describe("Client test", func() {
})
It("should handle status code != 200", func() {
_, err := client.ListInstances(params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusCreated)
})
})

Expand All @@ -86,8 +85,7 @@ var _ = Describe("Client test", func() {
})
It("should handle status code > 299", func() {
_, err := client.ListInstances(params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusBadRequest)
})
})
})
Expand Down Expand Up @@ -115,8 +113,7 @@ var _ = Describe("Client test", func() {
})
It("should return 404", func() {
_, err := client.GetInstanceByID(instance.ID, params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+instance.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusNotFound)
})
})

Expand All @@ -129,7 +126,7 @@ var _ = Describe("Client test", func() {
It("should handle status code != 200", func() {
_, err := client.GetInstanceByID(instance.ID, params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+instance.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusCreated)
})
})

Expand All @@ -142,9 +139,7 @@ var _ = Describe("Client test", func() {

It("should handle status code > 299", func() {
_, err := client.GetInstanceByID(instance.ID, params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+instance.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)

expectErrorToContainSubstringAndStatusCode(err, "", http.StatusBadRequest)
})
})
})
Expand Down Expand Up @@ -309,39 +304,33 @@ var _ = Describe("Client test", func() {
})
It("should return error with status code", func() {
res, err := client.Provision(instance, serviceName, planName, params, "test-user", "")

Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusOK)
Expect(res).To(BeNil())
})
})

Context("And status code is unsuccessful", func() {
BeforeEach(func() {
responseBody := []byte(`{ "description": "description", "error": "error"}`)
responseBody := []byte(`{ "description": "description"}`)
handlerDetails[0] = HandlerDetails{Method: http.MethodPost, Path: types.ServiceInstancesURL, ResponseBody: responseBody, ResponseStatusCode: http.StatusBadRequest}

})
It("should return error with url and description", func() {
res, err := client.Provision(instance, serviceName, planName, params, "test-user", "")

Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "description", http.StatusBadRequest)
Expect(res).To(BeNil())
})
})

Context("And invalid response body", func() {
BeforeEach(func() {
responseBody := []byte(`{ "description": description", "error": "error"}`)
responseBody := []byte(`{ "description": description" }`)
handlerDetails[0] = HandlerDetails{Method: http.MethodPost, Path: types.ServiceInstancesURL, ResponseBody: responseBody, ResponseStatusCode: http.StatusBadRequest}

})
It("should return error without url and description if invalid response body", func() {
res, err := client.Provision(instance, serviceName, planName, params, "test-user", "")

Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusBadRequest)
Expect(res).To(BeNil())
})
})
Expand Down Expand Up @@ -390,9 +379,8 @@ var _ = Describe("Client test", func() {
})
It("should handle error", func() {
location, err := client.Deprovision(instance.ID, params, "test-user")
Expect(err).Should(HaveOccurred())
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusCreated)
Expect(location).Should(BeEmpty())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+instance.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
})
})

Expand Down Expand Up @@ -496,44 +484,37 @@ var _ = Describe("Client test", func() {
})
It("should return error with status code", func() {
responseInstance, location, err := client.UpdateInstance(instance.ID, instance, serviceName, planName, params, "test-user", "")

Expect(err).Should(HaveOccurred())
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusTeapot)
Expect(location).Should(BeEmpty())
verifyErrorMsg(err.Error(), handlerDetails[2].Path, handlerDetails[2].ResponseBody, handlerDetails[2].ResponseStatusCode)
Expect(responseInstance).To(BeNil())
})
})

Context("And status code is unsuccessful", func() {
BeforeEach(func() {
responseBody := []byte(`{ "description": "description", "error": "error"}`)
responseBody := []byte(`{ "description": "description"}`)
handlerDetails = append(handlerDetails,
HandlerDetails{Method: http.MethodPatch, Path: types.ServiceInstancesURL + "/" + instance.ID, ResponseBody: responseBody, ResponseStatusCode: http.StatusBadRequest})
})
It("should return error with url and description", func() {
responseInstance, location, err := client.UpdateInstance(instance.ID, instance, serviceName, planName, params, "test-user", "")

Expect(err).Should(HaveOccurred())
expectErrorToContainSubstringAndStatusCode(err, "description", http.StatusBadRequest)
Expect(location).Should(BeEmpty())
verifyErrorMsg(err.Error(), handlerDetails[2].Path, handlerDetails[2].ResponseBody, handlerDetails[2].ResponseStatusCode)
Expect(responseInstance).To(BeNil())
})
})

Context("And invalid response body", func() {
BeforeEach(func() {
responseBody := []byte(`{ "description": description", "error": "error"}`)
responseBody := []byte(`{ "description": "description"}`)
handlerDetails = append(handlerDetails,
HandlerDetails{Method: http.MethodPatch, Path: types.ServiceInstancesURL + "/" + instance.ID, ResponseBody: responseBody, ResponseStatusCode: http.StatusBadRequest})
})
It("should return error without url and description if invalid response body", func() {
responseInstance, location, err := client.UpdateInstance(instance.ID, instance, serviceName, planName, params, "test-user", "")

Expect(err).Should(HaveOccurred())
Expect(location).Should(BeEmpty())

verifyErrorMsg(err.Error(), handlerDetails[2].Path, handlerDetails[2].ResponseBody, handlerDetails[2].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "description", http.StatusBadRequest)
Expect(responseInstance).To(BeNil())
Expect(location).Should(BeEmpty())
})
})

Expand Down Expand Up @@ -619,8 +600,7 @@ var _ = Describe("Client test", func() {
})
It("should handle status code != 200", func() {
_, err := client.ListBindings(params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusCreated)
})
})

Expand All @@ -632,8 +612,7 @@ var _ = Describe("Client test", func() {
})
It("should handle status code > 299", func() {
_, err := client.ListBindings(params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusBadRequest)
})
})
})
Expand Down Expand Up @@ -661,8 +640,7 @@ var _ = Describe("Client test", func() {
})
It("should return 404", func() {
_, err := client.GetBindingByID(binding.ID, params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+binding.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusNotFound)
})
})

Expand All @@ -674,8 +652,7 @@ var _ = Describe("Client test", func() {
})
It("should handle status code != 200", func() {
_, err := client.GetBindingByID(binding.ID, params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+binding.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusCreated)
})
})

Expand All @@ -687,8 +664,7 @@ var _ = Describe("Client test", func() {
})
It("should handle status code > 299", func() {
_, err := client.GetBindingByID(binding.ID, params)
Expect(err).Should(HaveOccurred())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+binding.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusBadRequest)

})
})
Expand Down Expand Up @@ -758,46 +734,39 @@ var _ = Describe("Client test", func() {
})
It("should return error with status code", func() {
responseBinding, location, err := client.Bind(binding, params, "test-user")

Expect(err).Should(HaveOccurred())
Expect(location).Should(BeEmpty())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusOK)
Expect(responseBinding).To(BeNil())
Expect(location).Should(BeEmpty())
})
})

Context("And status code is unsuccessful", func() {
BeforeEach(func() {
responseBody := []byte(`{ "description": "description", "error": "error"}`)
responseBody := []byte(`{ "description": "description"}`)
handlerDetails = []HandlerDetails{
{Method: http.MethodPost, Path: types.ServiceBindingsURL, ResponseBody: responseBody, ResponseStatusCode: http.StatusBadRequest},
}
})
It("should return error with url and description", func() {
responseBinding, location, err := client.Bind(binding, params, "test-user")

Expect(err).Should(HaveOccurred())
Expect(location).Should(BeEmpty())
verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "description", http.StatusBadRequest)
Expect(responseBinding).To(BeNil())
Expect(location).Should(BeEmpty())
})
})

Context("And invalid response body", func() {
BeforeEach(func() {
responseBody := []byte(`{ "description": description", "error": "error"}`)
responseBody := []byte(`{ "description": description" }`)
handlerDetails = []HandlerDetails{
{Method: http.MethodPost, Path: types.ServiceBindingsURL, ResponseBody: responseBody, ResponseStatusCode: http.StatusBadRequest},
}
})
It("should return error without url and description if invalid response body", func() {
responseBinding, location, err := client.Bind(binding, params, "test-user")

Expect(err).Should(HaveOccurred())
Expect(location).Should(BeEmpty())

verifyErrorMsg(err.Error(), handlerDetails[0].Path, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusBadRequest)
Expect(responseBinding).To(BeNil())
Expect(location).Should(BeEmpty())
})
})

Expand Down Expand Up @@ -940,9 +909,8 @@ TSTAhYWEQVZqRKYQMYGHpNlU
})
It("should handle error", func() {
location, err := client.Unbind(binding.ID, params, "test-user")
Expect(err).Should(HaveOccurred())
expectErrorToContainSubstringAndStatusCode(err, "", http.StatusCreated)
Expect(location).Should(BeEmpty())
verifyErrorMsg(err.Error(), handlerDetails[0].Path+binding.ID, handlerDetails[0].ResponseBody, handlerDetails[0].ResponseStatusCode)
})
})

Expand Down Expand Up @@ -1004,5 +972,10 @@ TSTAhYWEQVZqRKYQMYGHpNlU
Expect(result).To(Equal(operation))
})
})

})

func expectErrorToContainSubstringAndStatusCode(err error, substring string, statusCode int) {
Expect(err).Should(HaveOccurred())
Expect(err.Error()).To(ContainSubstring(substring))
Expect(err.(*ServiceManagerError).StatusCode).To(Equal(statusCode))
}
Loading
Loading