github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/nomad/structs/errors.go (about) 1 package structs 2 3 import ( 4 "errors" 5 "fmt" 6 "strconv" 7 "strings" 8 ) 9 10 const ( 11 errNoLeader = "No cluster leader" 12 errNotReadyForConsistentReads = "Not ready to serve consistent reads" 13 errNoRegionPath = "No path to region" 14 errTokenNotFound = "ACL token not found" 15 errPermissionDenied = "Permission denied" 16 errNoNodeConn = "No path to node" 17 errUnknownMethod = "Unknown rpc method" 18 errUnknownNomadVersion = "Unable to determine Nomad version" 19 errNodeLacksRpc = "Node does not support RPC; requires 0.8 or later" 20 errMissingAllocID = "Missing allocation ID" 21 22 // Prefix based errors that are used to check if the error is of a given 23 // type. These errors should be created with the associated constructor. 24 ErrUnknownAllocationPrefix = "Unknown allocation" 25 ErrUnknownNodePrefix = "Unknown node" 26 ErrUnknownJobPrefix = "Unknown job" 27 ErrUnknownEvaluationPrefix = "Unknown evaluation" 28 ErrUnknownDeploymentPrefix = "Unknown deployment" 29 30 errRPCCodedErrorPrefix = "RPC Error:: " 31 32 errDeploymentTerminalNoCancel = "can't cancel terminal deployment" 33 errDeploymentTerminalNoFail = "can't fail terminal deployment" 34 errDeploymentTerminalNoPause = "can't pause terminal deployment" 35 errDeploymentTerminalNoPromote = "can't promote terminal deployment" 36 errDeploymentTerminalNoResume = "can't resume terminal deployment" 37 errDeploymentTerminalNoUnblock = "can't unblock terminal deployment" 38 errDeploymentTerminalNoRun = "can't run terminal deployment" 39 errDeploymentTerminalNoSetHealth = "can't set health of allocations for a terminal deployment" 40 errDeploymentRunningNoUnblock = "can't unblock running deployment" 41 ) 42 43 var ( 44 ErrNoLeader = errors.New(errNoLeader) 45 ErrNotReadyForConsistentReads = errors.New(errNotReadyForConsistentReads) 46 ErrNoRegionPath = errors.New(errNoRegionPath) 47 ErrTokenNotFound = errors.New(errTokenNotFound) 48 ErrPermissionDenied = errors.New(errPermissionDenied) 49 ErrNoNodeConn = errors.New(errNoNodeConn) 50 ErrUnknownMethod = errors.New(errUnknownMethod) 51 ErrUnknownNomadVersion = errors.New(errUnknownNomadVersion) 52 ErrNodeLacksRpc = errors.New(errNodeLacksRpc) 53 ErrMissingAllocID = errors.New(errMissingAllocID) 54 55 ErrUnknownNode = errors.New(ErrUnknownNodePrefix) 56 57 ErrDeploymentTerminalNoCancel = errors.New(errDeploymentTerminalNoCancel) 58 ErrDeploymentTerminalNoFail = errors.New(errDeploymentTerminalNoFail) 59 ErrDeploymentTerminalNoPause = errors.New(errDeploymentTerminalNoPause) 60 ErrDeploymentTerminalNoPromote = errors.New(errDeploymentTerminalNoPromote) 61 ErrDeploymentTerminalNoResume = errors.New(errDeploymentTerminalNoResume) 62 ErrDeploymentTerminalNoUnblock = errors.New(errDeploymentTerminalNoUnblock) 63 ErrDeploymentTerminalNoRun = errors.New(errDeploymentTerminalNoRun) 64 ErrDeploymentTerminalNoSetHealth = errors.New(errDeploymentTerminalNoSetHealth) 65 ErrDeploymentRunningNoUnblock = errors.New(errDeploymentRunningNoUnblock) 66 67 ErrCSIClientRPCIgnorable = errors.New("CSI client error (ignorable)") 68 ErrCSIClientRPCRetryable = errors.New("CSI client error (retryable)") 69 ) 70 71 // IsErrNoLeader returns whether the error is due to there being no leader. 72 func IsErrNoLeader(err error) bool { 73 return err != nil && strings.Contains(err.Error(), errNoLeader) 74 } 75 76 // IsErrNoRegionPath returns whether the error is due to there being no path to 77 // the given region. 78 func IsErrNoRegionPath(err error) bool { 79 return err != nil && strings.Contains(err.Error(), errNoRegionPath) 80 } 81 82 // IsErrTokenNotFound returns whether the error is due to the passed token not 83 // being resolvable. 84 func IsErrTokenNotFound(err error) bool { 85 return err != nil && strings.Contains(err.Error(), errTokenNotFound) 86 } 87 88 // IsErrPermissionDenied returns whether the error is due to the operation not 89 // being allowed due to lack of permissions. 90 func IsErrPermissionDenied(err error) bool { 91 return err != nil && strings.Contains(err.Error(), errPermissionDenied) 92 } 93 94 // IsErrNoNodeConn returns whether the error is due to there being no path to 95 // the given node. 96 func IsErrNoNodeConn(err error) bool { 97 return err != nil && strings.Contains(err.Error(), errNoNodeConn) 98 } 99 100 // IsErrUnknownMethod returns whether the error is due to the operation not 101 // being allowed due to lack of permissions. 102 func IsErrUnknownMethod(err error) bool { 103 return err != nil && strings.Contains(err.Error(), errUnknownMethod) 104 } 105 106 func IsErrRPCCoded(err error) bool { 107 return err != nil && strings.HasPrefix(err.Error(), errRPCCodedErrorPrefix) 108 } 109 110 // NewErrUnknownAllocation returns a new error caused by the allocation being 111 // unknown. 112 func NewErrUnknownAllocation(allocID string) error { 113 return fmt.Errorf("%s %q", ErrUnknownAllocationPrefix, allocID) 114 } 115 116 // NewErrUnknownNode returns a new error caused by the node being unknown. 117 func NewErrUnknownNode(nodeID string) error { 118 return fmt.Errorf("%s %q", ErrUnknownNodePrefix, nodeID) 119 } 120 121 // NewErrUnknownJob returns a new error caused by the job being unknown. 122 func NewErrUnknownJob(jobID string) error { 123 return fmt.Errorf("%s %q", ErrUnknownJobPrefix, jobID) 124 } 125 126 // NewErrUnknownEvaluation returns a new error caused by the evaluation being 127 // unknown. 128 func NewErrUnknownEvaluation(evaluationID string) error { 129 return fmt.Errorf("%s %q", ErrUnknownEvaluationPrefix, evaluationID) 130 } 131 132 // NewErrUnknownDeployment returns a new error caused by the deployment being 133 // unknown. 134 func NewErrUnknownDeployment(deploymentID string) error { 135 return fmt.Errorf("%s %q", ErrUnknownDeploymentPrefix, deploymentID) 136 } 137 138 // IsErrUnknownAllocation returns whether the error is due to an unknown 139 // allocation. 140 func IsErrUnknownAllocation(err error) bool { 141 return err != nil && strings.Contains(err.Error(), ErrUnknownAllocationPrefix) 142 } 143 144 // IsErrUnknownNode returns whether the error is due to an unknown 145 // node. 146 func IsErrUnknownNode(err error) bool { 147 return err != nil && strings.Contains(err.Error(), ErrUnknownNodePrefix) 148 } 149 150 // IsErrUnknownJob returns whether the error is due to an unknown 151 // job. 152 func IsErrUnknownJob(err error) bool { 153 return err != nil && strings.Contains(err.Error(), ErrUnknownJobPrefix) 154 } 155 156 // IsErrUnknownEvaluation returns whether the error is due to an unknown 157 // evaluation. 158 func IsErrUnknownEvaluation(err error) bool { 159 return err != nil && strings.Contains(err.Error(), ErrUnknownEvaluationPrefix) 160 } 161 162 // IsErrUnknownDeployment returns whether the error is due to an unknown 163 // deployment. 164 func IsErrUnknownDeployment(err error) bool { 165 return err != nil && strings.Contains(err.Error(), ErrUnknownDeploymentPrefix) 166 } 167 168 // IsErrUnknownNomadVersion returns whether the error is due to Nomad being 169 // unable to determine the version of a node. 170 func IsErrUnknownNomadVersion(err error) bool { 171 return err != nil && strings.Contains(err.Error(), errUnknownNomadVersion) 172 } 173 174 // IsErrNodeLacksRpc returns whether error is due to a Nomad server being 175 // unable to connect to a client node because the client is too old (pre-v0.8). 176 func IsErrNodeLacksRpc(err error) bool { 177 return err != nil && strings.Contains(err.Error(), errNodeLacksRpc) 178 } 179 180 // NewErrRPCCoded wraps an RPC error with a code to be converted to HTTP status 181 // code 182 func NewErrRPCCoded(code int, msg string) error { 183 return fmt.Errorf("%s%d,%s", errRPCCodedErrorPrefix, code, msg) 184 } 185 186 // NewErrRPCCoded wraps an RPC error with a code to be converted to HTTP status 187 // code 188 func NewErrRPCCodedf(code int, format string, args ...interface{}) error { 189 msg := fmt.Sprintf(format, args...) 190 return fmt.Errorf("%s%d,%s", errRPCCodedErrorPrefix, code, msg) 191 } 192 193 // CodeFromRPCCodedErr returns the code and message of error if it's an RPC error 194 // created through NewErrRPCCoded function. Returns `ok` false if error is not 195 // an rpc error 196 func CodeFromRPCCodedErr(err error) (code int, msg string, ok bool) { 197 if err == nil || !strings.HasPrefix(err.Error(), errRPCCodedErrorPrefix) { 198 return 0, "", false 199 } 200 201 headerLen := len(errRPCCodedErrorPrefix) 202 parts := strings.SplitN(err.Error()[headerLen:], ",", 2) 203 if len(parts) != 2 { 204 return 0, "", false 205 } 206 207 code, err = strconv.Atoi(parts[0]) 208 if err != nil { 209 return 0, "", false 210 } 211 212 return code, parts[1], true 213 }