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