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