blob: 1244290c4a60063d30bee1df58e74140204be8c0 [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// Copyright 2015 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package v2error describes errors in etcd project. When any change happens,
16// Documentation/v2/errorcode.md needs to be updated correspondingly.
17// To be deprecated in favor of v3 APIs.
18package v2error
19
20import (
21 "encoding/json"
22 "fmt"
23 "net/http"
24)
25
26var errors = map[int]string{
27 // command related errors
28 EcodeKeyNotFound: "Key not found",
29 EcodeTestFailed: "Compare failed", //test and set
30 EcodeNotFile: "Not a file",
31 ecodeNoMorePeer: "Reached the max number of peers in the cluster",
32 EcodeNotDir: "Not a directory",
33 EcodeNodeExist: "Key already exists", // create
34 ecodeKeyIsPreserved: "The prefix of given key is a keyword in etcd",
35 EcodeRootROnly: "Root is read only",
36 EcodeDirNotEmpty: "Directory not empty",
37 ecodeExistingPeerAddr: "Peer address has existed",
38 EcodeUnauthorized: "The request requires user authentication",
39
40 // Post form related errors
41 ecodeValueRequired: "Value is Required in POST form",
42 EcodePrevValueRequired: "PrevValue is Required in POST form",
43 EcodeTTLNaN: "The given TTL in POST form is not a number",
44 EcodeIndexNaN: "The given index in POST form is not a number",
45 ecodeValueOrTTLRequired: "Value or TTL is required in POST form",
46 ecodeTimeoutNaN: "The given timeout in POST form is not a number",
47 ecodeNameRequired: "Name is required in POST form",
48 ecodeIndexOrValueRequired: "Index or value is required",
49 ecodeIndexValueMutex: "Index and value cannot both be specified",
50 EcodeInvalidField: "Invalid field",
51 EcodeInvalidForm: "Invalid POST form",
52 EcodeRefreshValue: "Value provided on refresh",
53 EcodeRefreshTTLRequired: "A TTL must be provided on refresh",
54
55 // raft related errors
56 EcodeRaftInternal: "Raft Internal Error",
57 EcodeLeaderElect: "During Leader Election",
58
59 // etcd related errors
60 EcodeWatcherCleared: "watcher is cleared due to etcd recovery",
61 EcodeEventIndexCleared: "The event in requested index is outdated and cleared",
62 ecodeStandbyInternal: "Standby Internal Error",
63 ecodeInvalidActiveSize: "Invalid active size",
64 ecodeInvalidRemoveDelay: "Standby remove delay",
65
66 // client related errors
67 ecodeClientInternal: "Client Internal Error",
68}
69
70var errorStatus = map[int]int{
71 EcodeKeyNotFound: http.StatusNotFound,
72 EcodeNotFile: http.StatusForbidden,
73 EcodeDirNotEmpty: http.StatusForbidden,
74 EcodeUnauthorized: http.StatusUnauthorized,
75 EcodeTestFailed: http.StatusPreconditionFailed,
76 EcodeNodeExist: http.StatusPreconditionFailed,
77 EcodeRaftInternal: http.StatusInternalServerError,
78 EcodeLeaderElect: http.StatusInternalServerError,
79}
80
81const (
82 EcodeKeyNotFound = 100
83 EcodeTestFailed = 101
84 EcodeNotFile = 102
85 ecodeNoMorePeer = 103
86 EcodeNotDir = 104
87 EcodeNodeExist = 105
88 ecodeKeyIsPreserved = 106
89 EcodeRootROnly = 107
90 EcodeDirNotEmpty = 108
91 ecodeExistingPeerAddr = 109
92 EcodeUnauthorized = 110
93
94 ecodeValueRequired = 200
95 EcodePrevValueRequired = 201
96 EcodeTTLNaN = 202
97 EcodeIndexNaN = 203
98 ecodeValueOrTTLRequired = 204
99 ecodeTimeoutNaN = 205
100 ecodeNameRequired = 206
101 ecodeIndexOrValueRequired = 207
102 ecodeIndexValueMutex = 208
103 EcodeInvalidField = 209
104 EcodeInvalidForm = 210
105 EcodeRefreshValue = 211
106 EcodeRefreshTTLRequired = 212
107
108 EcodeRaftInternal = 300
109 EcodeLeaderElect = 301
110
111 EcodeWatcherCleared = 400
112 EcodeEventIndexCleared = 401
113 ecodeStandbyInternal = 402
114 ecodeInvalidActiveSize = 403
115 ecodeInvalidRemoveDelay = 404
116
117 ecodeClientInternal = 500
118)
119
120type Error struct {
121 ErrorCode int `json:"errorCode"`
122 Message string `json:"message"`
123 Cause string `json:"cause,omitempty"`
124 Index uint64 `json:"index"`
125}
126
127func NewRequestError(errorCode int, cause string) *Error {
128 return NewError(errorCode, cause, 0)
129}
130
131func NewError(errorCode int, cause string, index uint64) *Error {
132 return &Error{
133 ErrorCode: errorCode,
134 Message: errors[errorCode],
135 Cause: cause,
136 Index: index,
137 }
138}
139
140// Error is for the error interface
141func (e Error) Error() string {
142 return e.Message + " (" + e.Cause + ")"
143}
144
145func (e Error) toJsonString() string {
146 b, _ := json.Marshal(e)
147 return string(b)
148}
149
150func (e Error) StatusCode() int {
151 status, ok := errorStatus[e.ErrorCode]
152 if !ok {
153 status = http.StatusBadRequest
154 }
155 return status
156}
157
158func (e Error) WriteTo(w http.ResponseWriter) error {
159 w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index))
160 w.Header().Set("Content-Type", "application/json")
161 w.WriteHeader(e.StatusCode())
162 _, err := w.Write([]byte(e.toJsonString() + "\n"))
163 return err
164}