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 }