github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/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  	"launchpad.net/juju-core/errors"
    11  	"launchpad.net/juju-core/state"
    12  	"launchpad.net/juju-core/state/api/params"
    13  )
    14  
    15  type notSupportedError struct {
    16  	entity    string
    17  	operation string
    18  }
    19  
    20  func (e *notSupportedError) Error() string {
    21  	return fmt.Sprintf("entity %q does not support %s", e.entity, e.operation)
    22  }
    23  
    24  func NotSupportedError(entity, operation string) error {
    25  	return &notSupportedError{entity, operation}
    26  }
    27  
    28  type noAddressSetError struct {
    29  	unitTag     string
    30  	addressName string
    31  }
    32  
    33  func (e *noAddressSetError) Error() string {
    34  	return fmt.Sprintf("%q has no %s address set", e.unitTag, e.addressName)
    35  }
    36  
    37  func NoAddressSetError(unitTag, addressName string) error {
    38  	return &noAddressSetError{unitTag, addressName}
    39  }
    40  
    41  func IsNoAddressSetError(err error) bool {
    42  	_, ok := err.(*noAddressSetError)
    43  	return ok
    44  }
    45  
    46  var (
    47  	ErrBadId          = stderrors.New("id not found")
    48  	ErrBadCreds       = stderrors.New("invalid entity name or password")
    49  	ErrPerm           = stderrors.New("permission denied")
    50  	ErrNotLoggedIn    = stderrors.New("not logged in")
    51  	ErrUnknownWatcher = stderrors.New("unknown watcher id")
    52  	ErrUnknownPinger  = stderrors.New("unknown pinger id")
    53  	ErrStoppedWatcher = stderrors.New("watcher has been stopped")
    54  	ErrBadRequest     = stderrors.New("invalid request")
    55  )
    56  
    57  var singletonErrorCodes = map[error]string{
    58  	state.ErrCannotEnterScopeYet: params.CodeCannotEnterScopeYet,
    59  	state.ErrCannotEnterScope:    params.CodeCannotEnterScope,
    60  	state.ErrExcessiveContention: params.CodeExcessiveContention,
    61  	state.ErrUnitHasSubordinates: params.CodeUnitHasSubordinates,
    62  	ErrBadId:                     params.CodeNotFound,
    63  	ErrBadCreds:                  params.CodeUnauthorized,
    64  	ErrPerm:                      params.CodeUnauthorized,
    65  	ErrNotLoggedIn:               params.CodeUnauthorized,
    66  	ErrUnknownWatcher:            params.CodeNotFound,
    67  	ErrStoppedWatcher:            params.CodeStopped,
    68  }
    69  
    70  func singletonCode(err error) (string, bool) {
    71  	// All error types may not be hashable; deal with
    72  	// that by catching the panic if we try to look up
    73  	// a non-hashable type.
    74  	defer func() {
    75  		recover()
    76  	}()
    77  	code, ok := singletonErrorCodes[err]
    78  	return code, ok
    79  }
    80  
    81  // ServerError returns an error suitable for returning to an API
    82  // client, with an error code suitable for various kinds of errors
    83  // generated in packages outside the API.
    84  func ServerError(err error) *params.Error {
    85  	if err == nil {
    86  		return nil
    87  	}
    88  	code, ok := singletonCode(err)
    89  	switch {
    90  	case ok:
    91  	case errors.IsUnauthorizedError(err):
    92  		code = params.CodeUnauthorized
    93  	case errors.IsNotFoundError(err):
    94  		code = params.CodeNotFound
    95  	case state.IsNotAssigned(err):
    96  		code = params.CodeNotAssigned
    97  	case state.IsHasAssignedUnitsError(err):
    98  		code = params.CodeHasAssignedUnits
    99  	case IsNoAddressSetError(err):
   100  		code = params.CodeNoAddressSet
   101  	case state.IsNotProvisionedError(err):
   102  		code = params.CodeNotProvisioned
   103  	default:
   104  		code = params.ErrCode(err)
   105  	}
   106  	return &params.Error{
   107  		Message: err.Error(),
   108  		Code:    code,
   109  	}
   110  }