go.ligato.io/vpp-agent/v3@v3.5.0/plugins/kvscheduler/api/errors.go (about)

     1  // Copyright (c) 2018 Cisco and/or its affiliates.
     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 api
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	"github.com/pkg/errors"
    22  	"google.golang.org/protobuf/proto"
    23  )
    24  
    25  var (
    26  	// ErrCombinedDownstreamResyncWithChange is returned when transaction combines downstream-resync with data changes.
    27  	ErrCombinedDownstreamResyncWithChange = errors.New("downstream resync combined with data changes in one transaction")
    28  
    29  	// ErrRevertNotSupportedWithResync is returned when transaction combines resync with revert.
    30  	ErrRevertNotSupportedWithResync = errors.New("it is not supported to combine resync with revert")
    31  
    32  	// ErrClosedScheduler is returned when scheduler is closed during transaction execution.
    33  	ErrClosedScheduler = errors.New("scheduler was closed")
    34  
    35  	// ErrTxnWaitCanceled is returned when waiting for result of blocking transaction is canceled.
    36  	ErrTxnWaitCanceled = errors.New("waiting for result of blocking transaction was canceled")
    37  
    38  	// ErrTxnQueueFull is returned when the queue of pending transactions is full.
    39  	ErrTxnQueueFull = errors.New("transaction queue is full")
    40  
    41  	// ErrUnimplementedCreate is returned when NB transaction attempts to Create value
    42  	// for which there is a descriptor, but Create operation is not implemented.
    43  	ErrUnimplementedCreate = errors.New("operation Create is not implemented")
    44  
    45  	// ErrUnimplementedDelete is returned when NB transaction attempts to Delete value
    46  	// for which there is a descriptor, but Delete operation is not implemented.
    47  	ErrUnimplementedDelete = errors.New("operation Delete is not implemented")
    48  
    49  	// ErrDescriptorExists is returned when the same descriptor is registered
    50  	// more than once.
    51  	ErrDescriptorExists = errors.New("descriptor already exist")
    52  
    53  	// ErrEscapedNetNs is returned when a descriptor changes the Linux network
    54  	// namespace but forgets to revert the change back before returning from the
    55  	// operation back to the scheduler.
    56  	ErrEscapedNetNs = errors.New("operation didn't preserve the original network namespace")
    57  )
    58  
    59  // ErrInvalidValueType is returned to scheduler by auto-generated descriptor adapter
    60  // when value does not match expected type.
    61  func ErrInvalidValueType(key string, value proto.Message) error {
    62  	if key == "" {
    63  		return errors.Errorf("value (%v) has invalid type", value)
    64  	}
    65  	return errors.Errorf("value (%v) has invalid type for key: %s", value, key)
    66  }
    67  
    68  // ErrInvalidMetadataType is returned to scheduler by auto-generated descriptor adapter
    69  // when value metadata does not match expected type.
    70  func ErrInvalidMetadataType(key string) error {
    71  	if key == "" {
    72  		return errors.Errorf("metadata has invalid type")
    73  	}
    74  	return errors.Errorf("metadata has invalid type for key: %s", key)
    75  }
    76  
    77  /****************************** Transaction Error *****************************/
    78  
    79  // TransactionError implements Error interface, wrapping all errors encountered
    80  // during the processing of a single transaction.
    81  type TransactionError struct {
    82  	txnInitError error
    83  	kvErrors     []KeyWithError
    84  }
    85  
    86  // NewTransactionError is a constructor for transaction error.
    87  func NewTransactionError(txnInitError error, kvErrors []KeyWithError) *TransactionError {
    88  	return &TransactionError{txnInitError: txnInitError, kvErrors: kvErrors}
    89  }
    90  
    91  // Error returns a string representation of all errors encountered during
    92  // the transaction processing.
    93  func (e *TransactionError) Error() string {
    94  	if e == nil {
    95  		return ""
    96  	}
    97  	if e.txnInitError != nil {
    98  		return e.txnInitError.Error()
    99  	}
   100  	if len(e.kvErrors) > 0 {
   101  		var kvErrMsgs []string
   102  		for _, kvError := range e.kvErrors {
   103  			kvErrMsgs = append(kvErrMsgs, fmt.Sprintf(
   104  				"%s (%v): %v", kvError.Key, kvError.TxnOperation, kvError.Error,
   105  			))
   106  		}
   107  		return fmt.Sprintf("KeyErrors: [%s]", strings.Join(kvErrMsgs, ", "))
   108  	}
   109  	return ""
   110  }
   111  
   112  // GetKVErrors returns errors for key-value pairs that failed to get applied.
   113  func (e *TransactionError) GetKVErrors() (kvErrors []KeyWithError) {
   114  	if e == nil {
   115  		return kvErrors
   116  	}
   117  	return e.kvErrors
   118  }
   119  
   120  // GetTxnInitError returns error thrown during the transaction initialization.
   121  // If the transaction initialization fails, the other stages of the transaction
   122  // processing are not even started, therefore either GetTxnInitError or GetKVErrors
   123  // may return some errors, but not both.
   124  func (e *TransactionError) GetTxnInitError() error {
   125  	if e == nil {
   126  		return nil
   127  	}
   128  	return e.txnInitError
   129  }
   130  
   131  /******************************** Invalid Value *******************************/
   132  
   133  // InvalidValueError can be used by descriptor for the Validate method to return
   134  // validation error together with a list of invalid fields for further
   135  // clarification.
   136  type InvalidValueError struct {
   137  	err           error
   138  	invalidFields []string
   139  }
   140  
   141  // NewInvalidValueError is a constructor for invalid-value error.
   142  func NewInvalidValueError(err error, invalidFields ...string) *InvalidValueError {
   143  	return &InvalidValueError{err: err, invalidFields: invalidFields}
   144  }
   145  
   146  // Error returns a string representation of all errors encountered during
   147  // the transaction processing.
   148  func (e *InvalidValueError) Error() string {
   149  	if e == nil || e.err == nil {
   150  		return ""
   151  	}
   152  	if len(e.invalidFields) == 0 {
   153  		return e.err.Error()
   154  	}
   155  	if len(e.invalidFields) == 1 {
   156  		return fmt.Sprintf("field %v is invalid: %v", e.invalidFields[0], e.err)
   157  	}
   158  	return fmt.Sprintf("fields %v are invalid: %v", e.invalidFields, e.err)
   159  }
   160  
   161  // GetValidationError returns internally stored validation error.
   162  func (e *InvalidValueError) GetValidationError() error {
   163  	return e.err
   164  }
   165  
   166  // GetInvalidFields returns internally stored slice of invalid fields.
   167  func (e *InvalidValueError) GetInvalidFields() []string {
   168  	return e.invalidFields
   169  }
   170  
   171  /***************************** Invalid Message ****************************/
   172  
   173  // InvalidMessageError is message validation error that links proto message with its
   174  // corresponding InvalidValueError returned from running KVDescriptor.Validate on the given proto message
   175  type InvalidMessageError struct {
   176  	// message is the message to which the invalidError refers to
   177  	message proto.Message
   178  	// parentMessage is filled only when field message is created using KVDescriptor.DerivedValues and
   179  	// it holds the proto message corresponding to the KVDescriptor that was used the derive value.
   180  	parentMessage proto.Message
   181  	// invalidError is the field validation error from KVDescriptor.Validate()
   182  	invalidError *InvalidValueError
   183  }
   184  
   185  // NewInvalidMessageError is constructor for InvalidMessageError
   186  func NewInvalidMessageError(message proto.Message, invalidError *InvalidValueError,
   187  	parentMessage proto.Message) *InvalidMessageError {
   188  	return &InvalidMessageError{
   189  		message:       message,
   190  		parentMessage: parentMessage,
   191  		invalidError:  invalidError,
   192  	}
   193  }
   194  
   195  // Error returns string representation of the pair (proto message, its InvalidValueError)
   196  func (e *InvalidMessageError) Error() string {
   197  	return fmt.Sprintf("message is not valid due to: %v (message=%v, parentMessage=%v)",
   198  		e.invalidError.Error(), e.message, e.parentMessage)
   199  }
   200  
   201  // Message returns proto message to which the InvalidValueError is linked
   202  func (e *InvalidMessageError) Message() proto.Message {
   203  	return e.message
   204  }
   205  
   206  // InvalidFields return fields to which the InvalidValueError is referring
   207  func (e *InvalidMessageError) InvalidFields() []string {
   208  	return e.invalidError.GetInvalidFields()
   209  }
   210  
   211  // ValidationError return error message of linked InvalidValueError
   212  func (e *InvalidMessageError) ValidationError() error {
   213  	return e.invalidError.GetValidationError()
   214  }
   215  
   216  // ParentMessage returns parent proto message to message which the InvalidValueError is linked to. The parent
   217  // proto message is non-nill only when the KVDescriptor.DerivedValues was used to create message
   218  // (InvalidMessageError.Message()), otherwise it is nil
   219  func (e *InvalidMessageError) ParentMessage() proto.Message {
   220  	return e.parentMessage
   221  }
   222  
   223  /***************************** Invalid Messages ****************************/
   224  
   225  // InvalidMessagesError is container for multiple InvalidMessageError instances
   226  type InvalidMessagesError struct {
   227  	messageErrors []*InvalidMessageError
   228  }
   229  
   230  // NewInvalidMessagesError is constructor for new InvalidMessagesError instances
   231  func NewInvalidMessagesError(messageErrors []*InvalidMessageError) *InvalidMessagesError {
   232  	return &InvalidMessagesError{
   233  		messageErrors: messageErrors,
   234  	}
   235  }
   236  
   237  // Error returns string representation of all contained InvalidMessageError instances
   238  func (e *InvalidMessagesError) Error() string {
   239  	var sb strings.Builder
   240  	sb.WriteString("some messages are invalid:\n")
   241  	for _, me := range e.messageErrors {
   242  		sb.WriteString(me.Error() + "\n")
   243  	}
   244  	return sb.String()
   245  }
   246  
   247  // MessageErrors returns all InvalidMessageError instances
   248  func (e *InvalidMessagesError) MessageErrors() []*InvalidMessageError {
   249  	return e.messageErrors
   250  }
   251  
   252  /***************************** Verification Failure ****************************/
   253  
   254  type VerificationErrorType int
   255  
   256  const (
   257  	// ExpectedToExist marks verification error returned when configured (non-nil)
   258  	// value is not found by the refresh.
   259  	ExpectedToExist VerificationErrorType = iota
   260  
   261  	// ExpectedToNotExist marks verification error returned when removed (nil)
   262  	// value is found by the refresh to still exist.
   263  	ExpectedToNotExist
   264  
   265  	// NotEquivalent marks verification error returned when applied value is not
   266  	// equivalent with the refreshed value.
   267  	NotEquivalent
   268  )
   269  
   270  // VerificationError is returned by the scheduler for a transaction when an applied
   271  // value does not match with the refreshed value.
   272  type VerificationError struct {
   273  	key     string
   274  	errType VerificationErrorType
   275  }
   276  
   277  // NewVerificationError is constructor for a verification error.
   278  func NewVerificationError(key string, errType VerificationErrorType) *VerificationError {
   279  	return &VerificationError{key: key, errType: errType}
   280  }
   281  
   282  // Error returns a string representation of the error.
   283  func (e *VerificationError) Error() string {
   284  	switch e.errType {
   285  	case ExpectedToExist:
   286  		return "value is not actually configured"
   287  	case ExpectedToNotExist:
   288  		return "value is not actually removed"
   289  	case NotEquivalent:
   290  		return "applied value is not equivalent with the refreshed value"
   291  	}
   292  	return ""
   293  }
   294  
   295  // Key returns the key of the value for which the verification failed.
   296  func (e *VerificationError) Key() string {
   297  	return e.key
   298  }
   299  
   300  // Type returns the verification error type.
   301  func (e *VerificationError) Type() VerificationErrorType {
   302  	return e.errType
   303  }