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 ¬SupportedError{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 = ¶ms.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 ¶ms.Error{ 146 Message: msg, 147 Code: code, 148 } 149 }