github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/params/apierror.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package params 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/rpc" 12 ) 13 14 // Error is the type of error returned by any call to the state API 15 type Error struct { 16 Message string 17 Code string 18 } 19 20 func (e *Error) Error() string { 21 return e.Message 22 } 23 24 func (e *Error) ErrorCode() string { 25 return e.Code 26 } 27 28 var _ rpc.ErrorCoder = (*Error)(nil) 29 30 // GoString implements fmt.GoStringer. It means that a *Error shows its 31 // contents correctly when printed with %#v. 32 func (e Error) GoString() string { 33 return fmt.Sprintf("¶ms.Error{%q, %q}", e.Code, e.Message) 34 } 35 36 // The Code constants hold error codes for some kinds of error. 37 const ( 38 CodeNotFound = "not found" 39 CodeUnauthorized = "unauthorized access" 40 CodeCannotEnterScope = "cannot enter scope" 41 CodeCannotEnterScopeYet = "cannot enter scope yet" 42 CodeExcessiveContention = "excessive contention" 43 CodeUnitHasSubordinates = "unit has subordinates" 44 CodeNotAssigned = "not assigned" 45 CodeStopped = "stopped" 46 CodeDead = "dead" 47 CodeHasAssignedUnits = "machine has assigned units" 48 CodeMachineHasAttachedStorage = "machine has attached storage" 49 CodeNotProvisioned = "not provisioned" 50 CodeNoAddressSet = "no address set" 51 CodeTryAgain = "try again" 52 CodeNotImplemented = rpc.CodeNotImplemented 53 CodeAlreadyExists = "already exists" 54 CodeUpgradeInProgress = "upgrade in progress" 55 CodeActionNotAvailable = "action no longer available" 56 CodeOperationBlocked = "operation is blocked" 57 CodeLeadershipClaimDenied = "leadership claim denied" 58 ) 59 60 // ErrCode returns the error code associated with 61 // the given error, or the empty string if there 62 // is none. 63 func ErrCode(err error) string { 64 err = errors.Cause(err) 65 if err, _ := err.(rpc.ErrorCoder); err != nil { 66 return err.ErrorCode() 67 } 68 return "" 69 } 70 71 // ClientError maps errors returned from an RPC call into local errors with 72 // appropriate values. 73 func ClientError(err error) error { 74 rerr, ok := err.(*rpc.RequestError) 75 if !ok { 76 return err 77 } 78 // We use our own error type rather than rpc.ServerError 79 // because we don't want the code or the "server error" prefix 80 // within the error message. Also, it's best not to make clients 81 // know that we're using the rpc package. 82 return &Error{ 83 Message: rerr.Message, 84 Code: rerr.Code, 85 } 86 } 87 88 func IsCodeActionNotAvailable(err error) bool { 89 return ErrCode(err) == CodeActionNotAvailable 90 } 91 92 func IsCodeNotFound(err error) bool { 93 return ErrCode(err) == CodeNotFound 94 } 95 96 func IsCodeUnauthorized(err error) bool { 97 return ErrCode(err) == CodeUnauthorized 98 } 99 100 // IsCodeNotFoundOrCodeUnauthorized is used in API clients which, 101 // pre-API, used errors.IsNotFound; this is because an API client is 102 // not necessarily privileged to know about the existence or otherwise 103 // of a particular entity, and the server may hence convert NotFound 104 // to Unauthorized at its discretion. 105 func IsCodeNotFoundOrCodeUnauthorized(err error) bool { 106 return IsCodeNotFound(err) || IsCodeUnauthorized(err) 107 } 108 109 func IsCodeCannotEnterScope(err error) bool { 110 return ErrCode(err) == CodeCannotEnterScope 111 } 112 113 func IsCodeCannotEnterScopeYet(err error) bool { 114 return ErrCode(err) == CodeCannotEnterScopeYet 115 } 116 117 func IsCodeExcessiveContention(err error) bool { 118 return ErrCode(err) == CodeExcessiveContention 119 } 120 121 func IsCodeUnitHasSubordinates(err error) bool { 122 return ErrCode(err) == CodeUnitHasSubordinates 123 } 124 125 func IsCodeNotAssigned(err error) bool { 126 return ErrCode(err) == CodeNotAssigned 127 } 128 129 func IsCodeStopped(err error) bool { 130 return ErrCode(err) == CodeStopped 131 } 132 133 func IsCodeDead(err error) bool { 134 return ErrCode(err) == CodeDead 135 } 136 137 func IsCodeHasAssignedUnits(err error) bool { 138 return ErrCode(err) == CodeHasAssignedUnits 139 } 140 141 func IsCodeMachineHasAttachedStorage(err error) bool { 142 return ErrCode(err) == CodeMachineHasAttachedStorage 143 } 144 145 func IsCodeNotProvisioned(err error) bool { 146 return ErrCode(err) == CodeNotProvisioned 147 } 148 149 func IsCodeNoAddressSet(err error) bool { 150 return ErrCode(err) == CodeNoAddressSet 151 } 152 153 func IsCodeTryAgain(err error) bool { 154 return ErrCode(err) == CodeTryAgain 155 } 156 157 func IsCodeNotImplemented(err error) bool { 158 return ErrCode(err) == CodeNotImplemented 159 } 160 161 func IsCodeAlreadyExists(err error) bool { 162 return ErrCode(err) == CodeAlreadyExists 163 } 164 165 func IsCodeUpgradeInProgress(err error) bool { 166 return ErrCode(err) == CodeUpgradeInProgress 167 } 168 169 func IsCodeOperationBlocked(err error) bool { 170 return ErrCode(err) == CodeOperationBlocked 171 } 172 173 func IsCodeLeadershipClaimDenied(err error) bool { 174 return ErrCode(err) == CodeLeadershipClaimDenied 175 }