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 ¬SupportedError{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 ¶ms.Error{ 131 Message: err.Error(), 132 Code: code, 133 } 134 }