github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/api/cloudcontroller/ccv2/errors.go (about)

     1  package ccv2
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     9  )
    10  
    11  // errorWrapper is the wrapper that converts responses with 4xx and 5xx status
    12  // codes to an error.
    13  type errorWrapper struct {
    14  	connection cloudcontroller.Connection
    15  }
    16  
    17  func newErrorWrapper() *errorWrapper {
    18  	return new(errorWrapper)
    19  }
    20  
    21  // Wrap wraps a Cloud Controller connection in this error handling wrapper.
    22  func (e *errorWrapper) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection {
    23  	e.connection = innerconnection
    24  	return e
    25  }
    26  
    27  // Make converts RawHTTPStatusError, which represents responses with 4xx and
    28  // 5xx status codes, to specific errors.
    29  func (e *errorWrapper) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error {
    30  	err := e.connection.Make(request, passedResponse)
    31  
    32  	if rawHTTPStatusErr, ok := err.(ccerror.RawHTTPStatusError); ok {
    33  		return convert(rawHTTPStatusErr)
    34  	}
    35  	return err
    36  }
    37  
    38  func convert(rawHTTPStatusErr ccerror.RawHTTPStatusError) error {
    39  	// Try to unmarshal the raw error into a CC error. If unmarshaling fails,
    40  	// return the raw error.
    41  	var errorResponse ccerror.V2ErrorResponse
    42  	err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse)
    43  	if err != nil {
    44  		if rawHTTPStatusErr.StatusCode == http.StatusNotFound {
    45  			return ccerror.NotFoundError{Message: string(rawHTTPStatusErr.RawResponse)}
    46  		}
    47  		return rawHTTPStatusErr
    48  	}
    49  
    50  	switch rawHTTPStatusErr.StatusCode {
    51  	case http.StatusBadRequest: // 400
    52  		return handleBadRequest(errorResponse)
    53  	case http.StatusUnauthorized: // 401
    54  		return handleUnauthorized(errorResponse)
    55  	case http.StatusForbidden: // 403
    56  		return ccerror.ForbiddenError{Message: errorResponse.Description}
    57  	case http.StatusNotFound: // 404
    58  		return ccerror.ResourceNotFoundError{Message: errorResponse.Description}
    59  	case http.StatusUnprocessableEntity: // 422
    60  		return ccerror.UnprocessableEntityError{Message: errorResponse.Description}
    61  	default:
    62  		return ccerror.V2UnexpectedResponseError{
    63  			V2ErrorResponse: errorResponse,
    64  			RequestIDs:      rawHTTPStatusErr.RequestIDs,
    65  			ResponseCode:    rawHTTPStatusErr.StatusCode,
    66  		}
    67  	}
    68  }
    69  
    70  func handleBadRequest(errorResponse ccerror.V2ErrorResponse) error {
    71  	switch errorResponse.ErrorCode {
    72  	case "CF-AppStoppedStatsError":
    73  		return ccerror.ApplicationStoppedStatsError{Message: errorResponse.Description}
    74  	case "CF-InstancesError":
    75  		return ccerror.InstancesError{Message: errorResponse.Description}
    76  	case "CF-InvalidRelation":
    77  		return ccerror.InvalidRelationError{Message: errorResponse.Description}
    78  	case "CF-NotStaged":
    79  		return ccerror.NotStagedError{Message: errorResponse.Description}
    80  	case "CF-ServiceBindingAppServiceTaken":
    81  		return ccerror.ServiceBindingTakenError{Message: errorResponse.Description}
    82  	default:
    83  		return ccerror.BadRequestError{Message: errorResponse.Description}
    84  	}
    85  }
    86  
    87  func handleUnauthorized(errorResponse ccerror.V2ErrorResponse) error {
    88  	if errorResponse.ErrorCode == "CF-InvalidAuthToken" {
    89  		return ccerror.InvalidAuthTokenError{Message: errorResponse.Description}
    90  	}
    91  
    92  	return ccerror.UnauthorizedError{Message: errorResponse.Description}
    93  }