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  }