k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/validation/errors/schema.go (about) 1 // Copyright 2015 go-swagger maintainers 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 errors 16 17 import ( 18 "fmt" 19 "strings" 20 ) 21 22 const ( 23 invalidType = "%s is an invalid type name" 24 typeFail = "%s in %s must be of type %s" 25 typeFailWithData = "%s in %s must be of type %s: %q" 26 typeFailWithError = "%s in %s must be of type %s, because: %s" 27 requiredFail = "%s in %s is required" 28 tooLongMessage = "%s in %s should be at most %d chars long" 29 tooShortMessage = "%s in %s should be at least %d chars long" 30 patternFail = "%s in %s should match '%s'" 31 enumFail = "%s in %s should be one of %v" 32 multipleOfFail = "%s in %s should be a multiple of %v" 33 maxIncFail = "%s in %s should be less than or equal to %v" 34 maxExcFail = "%s in %s should be less than %v" 35 minIncFail = "%s in %s should be greater than or equal to %v" 36 minExcFail = "%s in %s should be greater than %v" 37 uniqueFail = "%s in %s shouldn't contain duplicates" 38 maxItemsFail = "%s in %s should have at most %d items" 39 minItemsFail = "%s in %s should have at least %d items" 40 typeFailNoIn = "%s must be of type %s" 41 typeFailWithDataNoIn = "%s must be of type %s: %q" 42 typeFailWithErrorNoIn = "%s must be of type %s, because: %s" 43 requiredFailNoIn = "%s is required" 44 tooLongMessageNoIn = "%s should be at most %d chars long" 45 tooShortMessageNoIn = "%s should be at least %d chars long" 46 patternFailNoIn = "%s should match '%s'" 47 enumFailNoIn = "%s should be one of %v" 48 multipleOfFailNoIn = "%s should be a multiple of %v" 49 maxIncFailNoIn = "%s should be less than or equal to %v" 50 maxExcFailNoIn = "%s should be less than %v" 51 minIncFailNoIn = "%s should be greater than or equal to %v" 52 minExcFailNoIn = "%s should be greater than %v" 53 uniqueFailNoIn = "%s shouldn't contain duplicates" 54 maxItemsFailNoIn = "%s should have at most %d items" 55 minItemsFailNoIn = "%s should have at least %d items" 56 noAdditionalItems = "%s in %s can't have additional items" 57 noAdditionalItemsNoIn = "%s can't have additional items" 58 tooFewProperties = "%s in %s should have at least %d properties" 59 tooFewPropertiesNoIn = "%s should have at least %d properties" 60 tooManyProperties = "%s in %s should have at most %d properties" 61 tooManyPropertiesNoIn = "%s should have at most %d properties" 62 unallowedProperty = "%s.%s in %s is a forbidden property" 63 unallowedPropertyNoIn = "%s.%s is a forbidden property" 64 failedAllPatternProps = "%s.%s in %s failed all pattern properties" 65 failedAllPatternPropsNoIn = "%s.%s failed all pattern properties" 66 multipleOfMustBePositive = "factor MultipleOf declared for %s must be positive: %v" 67 ) 68 69 // All code responses can be used to differentiate errors for different handling 70 // by the consuming program 71 const ( 72 // CompositeErrorCode remains 422 for backwards-compatibility 73 // and to separate it from validation errors with cause 74 CompositeErrorCode = 422 75 // InvalidTypeCode is used for any subclass of invalid types 76 InvalidTypeCode = 600 + iota 77 RequiredFailCode 78 TooLongFailCode 79 TooShortFailCode 80 PatternFailCode 81 EnumFailCode 82 MultipleOfFailCode 83 MaxFailCode 84 MinFailCode 85 UniqueFailCode 86 MaxItemsFailCode 87 MinItemsFailCode 88 NoAdditionalItemsCode 89 TooFewPropertiesCode 90 TooManyPropertiesCode 91 UnallowedPropertyCode 92 FailedAllPatternPropsCode 93 MultipleOfMustBePositiveCode 94 ) 95 96 // CompositeError is an error that groups several errors together 97 type CompositeError struct { 98 Errors []error 99 code int32 100 message string 101 } 102 103 // Code for this error 104 func (c *CompositeError) Code() int32 { 105 return c.code 106 } 107 108 func (c *CompositeError) Error() string { 109 if len(c.Errors) > 0 { 110 msgs := []string{c.message + ":"} 111 for _, e := range c.Errors { 112 msgs = append(msgs, e.Error()) 113 } 114 return strings.Join(msgs, "\n") 115 } 116 return c.message 117 } 118 119 // CompositeValidationError an error to wrap a bunch of other errors 120 func CompositeValidationError(errors ...error) *CompositeError { 121 return &CompositeError{ 122 code: CompositeErrorCode, 123 Errors: append([]error{}, errors...), 124 message: "validation failure list", 125 } 126 } 127 128 // FailedAllPatternProperties an error for when the property doesn't match a pattern 129 func FailedAllPatternProperties(name, in, key string) *Validation { 130 msg := fmt.Sprintf(failedAllPatternProps, name, key, in) 131 if in == "" { 132 msg = fmt.Sprintf(failedAllPatternPropsNoIn, name, key) 133 } 134 return &Validation{ 135 code: FailedAllPatternPropsCode, 136 Name: name, 137 In: in, 138 Value: key, 139 message: msg, 140 } 141 } 142 143 // PropertyNotAllowed an error for when the property doesn't match a pattern 144 func PropertyNotAllowed(name, in, key string) *Validation { 145 msg := fmt.Sprintf(unallowedProperty, name, key, in) 146 if in == "" { 147 msg = fmt.Sprintf(unallowedPropertyNoIn, name, key) 148 } 149 return &Validation{ 150 code: UnallowedPropertyCode, 151 Name: name, 152 In: in, 153 Value: key, 154 message: msg, 155 } 156 } 157 158 // TooFewProperties an error for an object with too few properties 159 func TooFewProperties(name, in string, minProperties, size int64) *Validation { 160 msg := fmt.Sprintf(tooFewProperties, name, in, minProperties) 161 if in == "" { 162 msg = fmt.Sprintf(tooFewPropertiesNoIn, name, minProperties) 163 } 164 return &Validation{ 165 code: TooFewPropertiesCode, 166 Name: name, 167 In: in, 168 Value: size, 169 Valid: minProperties, 170 message: msg, 171 } 172 } 173 174 // TooManyProperties an error for an object with too many properties 175 func TooManyProperties(name, in string, maxProperties, size int64) *Validation { 176 msg := fmt.Sprintf(tooManyProperties, name, in, maxProperties) 177 if in == "" { 178 msg = fmt.Sprintf(tooManyPropertiesNoIn, name, maxProperties) 179 } 180 return &Validation{ 181 code: TooManyPropertiesCode, 182 Name: name, 183 In: in, 184 Value: size, 185 Valid: maxProperties, 186 message: msg, 187 } 188 } 189 190 // AdditionalItemsNotAllowed an error for invalid additional items 191 func AdditionalItemsNotAllowed(name, in string) *Validation { 192 msg := fmt.Sprintf(noAdditionalItems, name, in) 193 if in == "" { 194 msg = fmt.Sprintf(noAdditionalItemsNoIn, name) 195 } 196 return &Validation{ 197 code: NoAdditionalItemsCode, 198 Name: name, 199 In: in, 200 message: msg, 201 } 202 } 203 204 // InvalidCollectionFormat another flavor of invalid type error 205 func InvalidCollectionFormat(name, in, format string) *Validation { 206 return &Validation{ 207 code: InvalidTypeCode, 208 Name: name, 209 In: in, 210 Value: format, 211 message: fmt.Sprintf("the collection format %q is not supported for the %s param %q", format, in, name), 212 } 213 } 214 215 // InvalidTypeName an error for when the type is invalid 216 func InvalidTypeName(typeName string) *Validation { 217 return &Validation{ 218 code: InvalidTypeCode, 219 Value: typeName, 220 message: fmt.Sprintf(invalidType, typeName), 221 } 222 } 223 224 // InvalidType creates an error for when the type is invalid 225 func InvalidType(name, in, typeName string, value interface{}) *Validation { 226 var message string 227 228 if in != "" { 229 switch value.(type) { 230 case string: 231 message = fmt.Sprintf(typeFailWithData, name, in, typeName, value) 232 case error: 233 message = fmt.Sprintf(typeFailWithError, name, in, typeName, value) 234 default: 235 message = fmt.Sprintf(typeFail, name, in, typeName) 236 } 237 } else { 238 switch value.(type) { 239 case string: 240 message = fmt.Sprintf(typeFailWithDataNoIn, name, typeName, value) 241 case error: 242 message = fmt.Sprintf(typeFailWithErrorNoIn, name, typeName, value) 243 default: 244 message = fmt.Sprintf(typeFailNoIn, name, typeName) 245 } 246 } 247 248 return &Validation{ 249 code: InvalidTypeCode, 250 Name: name, 251 In: in, 252 Value: value, 253 message: message, 254 } 255 256 } 257 258 // DuplicateItems error for when an array contains duplicates 259 func DuplicateItems(name, in string) *Validation { 260 msg := fmt.Sprintf(uniqueFail, name, in) 261 if in == "" { 262 msg = fmt.Sprintf(uniqueFailNoIn, name) 263 } 264 return &Validation{ 265 code: UniqueFailCode, 266 Name: name, 267 In: in, 268 message: msg, 269 } 270 } 271 272 // TooManyItems error for when an array contains too many items 273 func TooManyItems(name, in string, max int64, value interface{}) *Validation { 274 msg := fmt.Sprintf(maxItemsFail, name, in, max) 275 if in == "" { 276 msg = fmt.Sprintf(maxItemsFailNoIn, name, max) 277 } 278 279 return &Validation{ 280 code: MaxItemsFailCode, 281 Name: name, 282 In: in, 283 Value: value, 284 Valid: max, 285 message: msg, 286 } 287 } 288 289 // TooFewItems error for when an array contains too few items 290 func TooFewItems(name, in string, min int64, value interface{}) *Validation { 291 msg := fmt.Sprintf(minItemsFail, name, in, min) 292 if in == "" { 293 msg = fmt.Sprintf(minItemsFailNoIn, name, min) 294 } 295 return &Validation{ 296 code: MinItemsFailCode, 297 Name: name, 298 In: in, 299 Value: value, 300 Valid: min, 301 message: msg, 302 } 303 } 304 305 // ExceedsMaximumInt error for when maxinum validation fails 306 func ExceedsMaximumInt(name, in string, max int64, exclusive bool, value interface{}) *Validation { 307 var message string 308 if in == "" { 309 m := maxIncFailNoIn 310 if exclusive { 311 m = maxExcFailNoIn 312 } 313 message = fmt.Sprintf(m, name, max) 314 } else { 315 m := maxIncFail 316 if exclusive { 317 m = maxExcFail 318 } 319 message = fmt.Sprintf(m, name, in, max) 320 } 321 return &Validation{ 322 code: MaxFailCode, 323 Name: name, 324 In: in, 325 Value: value, 326 message: message, 327 } 328 } 329 330 // ExceedsMaximumUint error for when maxinum validation fails 331 func ExceedsMaximumUint(name, in string, max uint64, exclusive bool, value interface{}) *Validation { 332 var message string 333 if in == "" { 334 m := maxIncFailNoIn 335 if exclusive { 336 m = maxExcFailNoIn 337 } 338 message = fmt.Sprintf(m, name, max) 339 } else { 340 m := maxIncFail 341 if exclusive { 342 m = maxExcFail 343 } 344 message = fmt.Sprintf(m, name, in, max) 345 } 346 return &Validation{ 347 code: MaxFailCode, 348 Name: name, 349 In: in, 350 Value: value, 351 message: message, 352 } 353 } 354 355 // ExceedsMaximum error for when maxinum validation fails 356 func ExceedsMaximum(name, in string, max float64, exclusive bool, value interface{}) *Validation { 357 var message string 358 if in == "" { 359 m := maxIncFailNoIn 360 if exclusive { 361 m = maxExcFailNoIn 362 } 363 message = fmt.Sprintf(m, name, max) 364 } else { 365 m := maxIncFail 366 if exclusive { 367 m = maxExcFail 368 } 369 message = fmt.Sprintf(m, name, in, max) 370 } 371 return &Validation{ 372 code: MaxFailCode, 373 Name: name, 374 In: in, 375 Value: value, 376 message: message, 377 } 378 } 379 380 // ExceedsMinimumInt error for when maxinum validation fails 381 func ExceedsMinimumInt(name, in string, min int64, exclusive bool, value interface{}) *Validation { 382 var message string 383 if in == "" { 384 m := minIncFailNoIn 385 if exclusive { 386 m = minExcFailNoIn 387 } 388 message = fmt.Sprintf(m, name, min) 389 } else { 390 m := minIncFail 391 if exclusive { 392 m = minExcFail 393 } 394 message = fmt.Sprintf(m, name, in, min) 395 } 396 return &Validation{ 397 code: MinFailCode, 398 Name: name, 399 In: in, 400 Value: value, 401 message: message, 402 } 403 } 404 405 // ExceedsMinimumUint error for when maxinum validation fails 406 func ExceedsMinimumUint(name, in string, min uint64, exclusive bool, value interface{}) *Validation { 407 var message string 408 if in == "" { 409 m := minIncFailNoIn 410 if exclusive { 411 m = minExcFailNoIn 412 } 413 message = fmt.Sprintf(m, name, min) 414 } else { 415 m := minIncFail 416 if exclusive { 417 m = minExcFail 418 } 419 message = fmt.Sprintf(m, name, in, min) 420 } 421 return &Validation{ 422 code: MinFailCode, 423 Name: name, 424 In: in, 425 Value: value, 426 message: message, 427 } 428 } 429 430 // ExceedsMinimum error for when maxinum validation fails 431 func ExceedsMinimum(name, in string, min float64, exclusive bool, value interface{}) *Validation { 432 var message string 433 if in == "" { 434 m := minIncFailNoIn 435 if exclusive { 436 m = minExcFailNoIn 437 } 438 message = fmt.Sprintf(m, name, min) 439 } else { 440 m := minIncFail 441 if exclusive { 442 m = minExcFail 443 } 444 message = fmt.Sprintf(m, name, in, min) 445 } 446 return &Validation{ 447 code: MinFailCode, 448 Name: name, 449 In: in, 450 Value: value, 451 message: message, 452 } 453 } 454 455 // NotMultipleOf error for when multiple of validation fails 456 func NotMultipleOf(name, in string, multiple, value interface{}) *Validation { 457 var msg string 458 if in == "" { 459 msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple) 460 } else { 461 msg = fmt.Sprintf(multipleOfFail, name, in, multiple) 462 } 463 return &Validation{ 464 code: MultipleOfFailCode, 465 Name: name, 466 In: in, 467 Value: value, 468 message: msg, 469 } 470 } 471 472 // EnumFail error for when an enum validation fails 473 func EnumFail(name, in string, value interface{}, values []interface{}) *Validation { 474 var msg string 475 if in == "" { 476 msg = fmt.Sprintf(enumFailNoIn, name, values) 477 } else { 478 msg = fmt.Sprintf(enumFail, name, in, values) 479 } 480 481 return &Validation{ 482 code: EnumFailCode, 483 Name: name, 484 In: in, 485 Value: value, 486 Values: values, 487 message: msg, 488 } 489 } 490 491 // Required error for when a value is missing 492 func Required(name, in string) *Validation { 493 var msg string 494 if in == "" { 495 msg = fmt.Sprintf(requiredFailNoIn, name) 496 } else { 497 msg = fmt.Sprintf(requiredFail, name, in) 498 } 499 return &Validation{ 500 code: RequiredFailCode, 501 Name: name, 502 In: in, 503 message: msg, 504 } 505 } 506 507 // TooLong error for when a string is too long 508 func TooLong(name, in string, max int64, value interface{}) *Validation { 509 var msg string 510 if in == "" { 511 msg = fmt.Sprintf(tooLongMessageNoIn, name, max) 512 } else { 513 msg = fmt.Sprintf(tooLongMessage, name, in, max) 514 } 515 return &Validation{ 516 code: TooLongFailCode, 517 Name: name, 518 In: in, 519 Value: value, 520 Valid: max, 521 message: msg, 522 } 523 } 524 525 // TooShort error for when a string is too short 526 func TooShort(name, in string, min int64, value interface{}) *Validation { 527 var msg string 528 if in == "" { 529 msg = fmt.Sprintf(tooShortMessageNoIn, name, min) 530 } else { 531 msg = fmt.Sprintf(tooShortMessage, name, in, min) 532 } 533 534 return &Validation{ 535 code: TooShortFailCode, 536 Name: name, 537 In: in, 538 Value: value, 539 Valid: min, 540 message: msg, 541 } 542 } 543 544 // FailedPattern error for when a string fails a regex pattern match 545 // the pattern that is returned is the ECMA syntax version of the pattern not the golang version. 546 func FailedPattern(name, in, pattern string, value interface{}) *Validation { 547 var msg string 548 if in == "" { 549 msg = fmt.Sprintf(patternFailNoIn, name, pattern) 550 } else { 551 msg = fmt.Sprintf(patternFail, name, in, pattern) 552 } 553 554 return &Validation{ 555 code: PatternFailCode, 556 Name: name, 557 In: in, 558 Value: value, 559 message: msg, 560 } 561 } 562 563 // MultipleOfMustBePositive error for when a 564 // multipleOf factor is negative 565 func MultipleOfMustBePositive(name, in string, factor interface{}) *Validation { 566 return &Validation{ 567 code: MultipleOfMustBePositiveCode, 568 Name: name, 569 In: in, 570 Value: factor, 571 message: fmt.Sprintf(multipleOfMustBePositive, name, factor), 572 } 573 }