github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/apiserver/common/errors.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common
     5  
     6  import (
     7  	stderrors "errors"
     8  	"fmt"
     9  
    10  	"github.com/juju/errors"
    11  
    12  	"github.com/juju/juju/state"
    13  	"github.com/juju/juju/state/api/params"
    14  )
    15  
    16  type notSupportedError struct {
    17  	entity    string
    18  	operation string
    19  }
    20  
    21  func (e *notSupportedError) Error() string {
    22  	return fmt.Sprintf("entity %q does not support %s", e.entity, e.operation)
    23  }
    24  
    25  func NotSupportedError(entity, operation string) error {
    26  	return &notSupportedError{entity, operation}
    27  }
    28  
    29  type noAddressSetError struct {
    30  	unitTag     string
    31  	addressName string
    32  }
    33  
    34  func (e *noAddressSetError) Error() string {
    35  	return fmt.Sprintf("%q has no %s address set", e.unitTag, e.addressName)
    36  }
    37  
    38  func NoAddressSetError(unitTag, addressName string) error {
    39  	return &noAddressSetError{unitTag, addressName}
    40  }
    41  
    42  func IsNoAddressSetError(err error) bool {
    43  	_, ok := err.(*noAddressSetError)
    44  	return ok
    45  }
    46  
    47  type unknownEnvironmentError struct {
    48  	uuid string
    49  }
    50  
    51  func (e *unknownEnvironmentError) Error() string {
    52  	return fmt.Sprintf("unknown environment: %q", e.uuid)
    53  }
    54  
    55  func UnknownEnvironmentError(uuid string) error {
    56  	return &unknownEnvironmentError{uuid: uuid}
    57  }
    58  
    59  func IsUnknownEnviromentError(err error) bool {
    60  	_, ok := err.(*unknownEnvironmentError)
    61  	return ok
    62  }
    63  
    64  var (
    65  	ErrBadId          = stderrors.New("id not found")
    66  	ErrBadCreds       = stderrors.New("invalid entity name or password")
    67  	ErrPerm           = stderrors.New("permission denied")
    68  	ErrNotLoggedIn    = stderrors.New("not logged in")
    69  	ErrUnknownWatcher = stderrors.New("unknown watcher id")
    70  	ErrUnknownPinger  = stderrors.New("unknown pinger id")
    71  	ErrStoppedWatcher = stderrors.New("watcher has been stopped")
    72  	ErrBadRequest     = stderrors.New("invalid request")
    73  	ErrTryAgain       = stderrors.New("try again")
    74  )
    75  
    76  var singletonErrorCodes = map[error]string{
    77  	state.ErrCannotEnterScopeYet: params.CodeCannotEnterScopeYet,
    78  	state.ErrCannotEnterScope:    params.CodeCannotEnterScope,
    79  	state.ErrExcessiveContention: params.CodeExcessiveContention,
    80  	state.ErrUnitHasSubordinates: params.CodeUnitHasSubordinates,
    81  	ErrBadId:                     params.CodeNotFound,
    82  	ErrBadCreds:                  params.CodeUnauthorized,
    83  	ErrPerm:                      params.CodeUnauthorized,
    84  	ErrNotLoggedIn:               params.CodeUnauthorized,
    85  	ErrUnknownWatcher:            params.CodeNotFound,
    86  	ErrStoppedWatcher:            params.CodeStopped,
    87  	ErrTryAgain:                  params.CodeTryAgain,
    88  }
    89  
    90  func singletonCode(err error) (string, bool) {
    91  	// All error types may not be hashable; deal with
    92  	// that by catching the panic if we try to look up
    93  	// a non-hashable type.
    94  	defer func() {
    95  		recover()
    96  	}()
    97  	code, ok := singletonErrorCodes[err]
    98  	return code, ok
    99  }
   100  
   101  // ServerError returns an error suitable for returning to an API
   102  // client, with an error code suitable for various kinds of errors
   103  // generated in packages outside the API.
   104  func ServerError(err error) *params.Error {
   105  	if err == nil {
   106  		return nil
   107  	}
   108  	code, ok := singletonCode(err)
   109  	switch {
   110  	case ok:
   111  	case errors.IsUnauthorized(err):
   112  		code = params.CodeUnauthorized
   113  	case errors.IsNotFound(err):
   114  		code = params.CodeNotFound
   115  	case errors.IsAlreadyExists(err):
   116  		code = params.CodeAlreadyExists
   117  	case state.IsNotAssigned(err):
   118  		code = params.CodeNotAssigned
   119  	case state.IsHasAssignedUnitsError(err):
   120  		code = params.CodeHasAssignedUnits
   121  	case IsNoAddressSetError(err):
   122  		code = params.CodeNoAddressSet
   123  	case state.IsNotProvisionedError(err):
   124  		code = params.CodeNotProvisioned
   125  	case IsUnknownEnviromentError(err):
   126  		code = params.CodeNotFound
   127  	default:
   128  		code = params.ErrCode(err)
   129  	}
   130  	return &params.Error{
   131  		Message: err.Error(),
   132  		Code:    code,
   133  	}
   134  }