github.com/macb/etcd@v0.3.1-0.20140227003422-a60481c6b1a0/error/error.go (about) 1 /* 2 Copyright 2013 CoreOS Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package error 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "net/http" 23 ) 24 25 var errors map[int]string 26 27 const ( 28 EcodeKeyNotFound = 100 29 EcodeTestFailed = 101 30 EcodeNotFile = 102 31 EcodeNoMorePeer = 103 32 EcodeNotDir = 104 33 EcodeNodeExist = 105 34 EcodeKeyIsPreserved = 106 35 EcodeRootROnly = 107 36 EcodeDirNotEmpty = 108 37 38 EcodeValueRequired = 200 39 EcodePrevValueRequired = 201 40 EcodeTTLNaN = 202 41 EcodeIndexNaN = 203 42 EcodeValueOrTTLRequired = 204 43 EcodeTimeoutNaN = 205 44 EcodeNameRequired = 206 45 EcodeIndexOrValueRequired = 207 46 EcodeIndexValueMutex = 208 47 EcodeInvalidField = 209 48 49 EcodeRaftInternal = 300 50 EcodeLeaderElect = 301 51 52 EcodeWatcherCleared = 400 53 EcodeEventIndexCleared = 401 54 ) 55 56 func init() { 57 errors = make(map[int]string) 58 59 // command related errors 60 errors[EcodeKeyNotFound] = "Key not found" 61 errors[EcodeTestFailed] = "Compare failed" //test and set 62 errors[EcodeNotFile] = "Not a file" 63 errors[EcodeNoMorePeer] = "Reached the max number of peers in the cluster" 64 errors[EcodeNotDir] = "Not a directory" 65 errors[EcodeNodeExist] = "Key already exists" // create 66 errors[EcodeRootROnly] = "Root is read only" 67 errors[EcodeKeyIsPreserved] = "The prefix of given key is a keyword in etcd" 68 errors[EcodeDirNotEmpty] = "Directory not empty" 69 70 // Post form related errors 71 errors[EcodeValueRequired] = "Value is Required in POST form" 72 errors[EcodePrevValueRequired] = "PrevValue is Required in POST form" 73 errors[EcodeTTLNaN] = "The given TTL in POST form is not a number" 74 errors[EcodeIndexNaN] = "The given index in POST form is not a number" 75 errors[EcodeValueOrTTLRequired] = "Value or TTL is required in POST form" 76 errors[EcodeTimeoutNaN] = "The given timeout in POST form is not a number" 77 errors[EcodeNameRequired] = "Name is required in POST form" 78 errors[EcodeIndexOrValueRequired] = "Index or value is required" 79 errors[EcodeIndexValueMutex] = "Index and value cannot both be specified" 80 errors[EcodeInvalidField] = "Invalid field" 81 82 // raft related errors 83 errors[EcodeRaftInternal] = "Raft Internal Error" 84 errors[EcodeLeaderElect] = "During Leader Election" 85 86 // etcd related errors 87 errors[EcodeWatcherCleared] = "watcher is cleared due to etcd recovery" 88 errors[EcodeEventIndexCleared] = "The event in requested index is outdated and cleared" 89 90 } 91 92 type Error struct { 93 ErrorCode int `json:"errorCode"` 94 Message string `json:"message"` 95 Cause string `json:"cause,omitempty"` 96 Index uint64 `json:"index"` 97 } 98 99 func NewError(errorCode int, cause string, index uint64) *Error { 100 return &Error{ 101 ErrorCode: errorCode, 102 Message: errors[errorCode], 103 Cause: cause, 104 Index: index, 105 } 106 } 107 108 func Message(code int) string { 109 return errors[code] 110 } 111 112 // Only for error interface 113 func (e Error) Error() string { 114 return e.Message 115 } 116 117 func (e Error) toJsonString() string { 118 b, _ := json.Marshal(e) 119 return string(b) 120 } 121 122 func (e Error) Write(w http.ResponseWriter) { 123 w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index)) 124 // 3xx is raft internal error 125 status := http.StatusBadRequest 126 switch e.ErrorCode { 127 case EcodeKeyNotFound: 128 status = http.StatusNotFound 129 case EcodeNotFile, EcodeDirNotEmpty: 130 status = http.StatusForbidden 131 case EcodeTestFailed, EcodeNodeExist: 132 status = http.StatusPreconditionFailed 133 default: 134 if e.ErrorCode/100 == 3 { 135 status = http.StatusInternalServerError 136 } 137 } 138 http.Error(w, e.toJsonString(), status) 139 }