github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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  	"github.com/juju/names"
    12  	"github.com/juju/txn"
    13  
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/state"
    16  )
    17  
    18  type notSupportedError struct {
    19  	tag       names.Tag
    20  	operation string
    21  }
    22  
    23  func (e *notSupportedError) Error() string {
    24  	return fmt.Sprintf("entity %q does not support %s", e.tag, e.operation)
    25  }
    26  
    27  func NotSupportedError(tag names.Tag, operation string) error {
    28  	return &notSupportedError{tag, operation}
    29  }
    30  
    31  type noAddressSetError struct {
    32  	unitTag     names.UnitTag
    33  	addressName string
    34  }
    35  
    36  func (e *noAddressSetError) Error() string {
    37  	return fmt.Sprintf("%q has no %s address set", e.unitTag, e.addressName)
    38  }
    39  
    40  func NoAddressSetError(unitTag names.UnitTag, addressName string) error {
    41  	return &noAddressSetError{unitTag, addressName}
    42  }
    43  
    44  func IsNoAddressSetError(err error) bool {
    45  	_, ok := err.(*noAddressSetError)
    46  	return ok
    47  }
    48  
    49  type unknownEnvironmentError struct {
    50  	uuid string
    51  }
    52  
    53  func (e *unknownEnvironmentError) Error() string {
    54  	return fmt.Sprintf("unknown environment: %q", e.uuid)
    55  }
    56  
    57  func UnknownEnvironmentError(uuid string) error {
    58  	return &unknownEnvironmentError{uuid: uuid}
    59  }
    60  
    61  func IsUnknownEnviromentError(err error) bool {
    62  	_, ok := err.(*unknownEnvironmentError)
    63  	return ok
    64  }
    65  
    66  var (
    67  	ErrBadId              = stderrors.New("id not found")
    68  	ErrBadCreds           = stderrors.New("invalid entity name or password")
    69  	ErrPerm               = stderrors.New("permission denied")
    70  	ErrNotLoggedIn        = stderrors.New("not logged in")
    71  	ErrUnknownWatcher     = stderrors.New("unknown watcher id")
    72  	ErrUnknownPinger      = stderrors.New("unknown pinger id")
    73  	ErrStoppedWatcher     = stderrors.New("watcher has been stopped")
    74  	ErrBadRequest         = stderrors.New("invalid request")
    75  	ErrTryAgain           = stderrors.New("try again")
    76  	ErrActionNotAvailable = stderrors.New("action no longer available")
    77  
    78  	ErrOperationBlocked = &params.Error{
    79  		Code:    params.CodeOperationBlocked,
    80  		Message: "The operation has been blocked.",
    81  	}
    82  )
    83  
    84  var singletonErrorCodes = map[error]string{
    85  	state.ErrCannotEnterScopeYet: params.CodeCannotEnterScopeYet,
    86  	state.ErrCannotEnterScope:    params.CodeCannotEnterScope,
    87  	state.ErrUnitHasSubordinates: params.CodeUnitHasSubordinates,
    88  	state.ErrDead:                params.CodeDead,
    89  	txn.ErrExcessiveContention:   params.CodeExcessiveContention,
    90  	ErrBadId:                     params.CodeNotFound,
    91  	ErrBadCreds:                  params.CodeUnauthorized,
    92  	ErrPerm:                      params.CodeUnauthorized,
    93  	ErrNotLoggedIn:               params.CodeUnauthorized,
    94  	ErrUnknownWatcher:            params.CodeNotFound,
    95  	ErrStoppedWatcher:            params.CodeStopped,
    96  	ErrTryAgain:                  params.CodeTryAgain,
    97  	ErrActionNotAvailable:        params.CodeActionNotAvailable,
    98  }
    99  
   100  func singletonCode(err error) (string, bool) {
   101  	// All error types may not be hashable; deal with
   102  	// that by catching the panic if we try to look up
   103  	// a non-hashable type.
   104  	defer func() {
   105  		recover()
   106  	}()
   107  	code, ok := singletonErrorCodes[err]
   108  	return code, ok
   109  }
   110  
   111  // ServerError returns an error suitable for returning to an API
   112  // client, with an error code suitable for various kinds of errors
   113  // generated in packages outside the API.
   114  func ServerError(err error) *params.Error {
   115  	if err == nil {
   116  		return nil
   117  	}
   118  	msg := err.Error()
   119  	// Skip past annotations when looking for the code.
   120  	err = errors.Cause(err)
   121  	code, ok := singletonCode(err)
   122  	switch {
   123  	case ok:
   124  	case errors.IsUnauthorized(err):
   125  		code = params.CodeUnauthorized
   126  	case errors.IsNotFound(err):
   127  		code = params.CodeNotFound
   128  	case errors.IsAlreadyExists(err):
   129  		code = params.CodeAlreadyExists
   130  	case state.IsNotAssigned(err):
   131  		code = params.CodeNotAssigned
   132  	case state.IsHasAssignedUnitsError(err):
   133  		code = params.CodeHasAssignedUnits
   134  	case IsNoAddressSetError(err):
   135  		code = params.CodeNoAddressSet
   136  	case errors.IsNotProvisioned(err):
   137  		code = params.CodeNotProvisioned
   138  	case state.IsUpgradeInProgressError(err):
   139  		code = params.CodeUpgradeInProgress
   140  	case IsUnknownEnviromentError(err):
   141  		code = params.CodeNotFound
   142  	default:
   143  		code = params.ErrCode(err)
   144  	}
   145  	return &params.Error{
   146  		Message: msg,
   147  		Code:    code,
   148  	}
   149  }