updated vendor

This commit is contained in:
2026-06-16 08:02:19 +02:00
parent 2f7f99d3f0
commit 77299d0c64
1283 changed files with 67302 additions and 208958 deletions
+36 -4
View File
@@ -40,10 +40,12 @@ type ErrorMatcher struct {
matchField bool
// TODO(thockin): consider whether value could be assumed - if the
// "want" error has a nil value, don't match on value.
matchValue bool
matchOrigin bool
matchDetail func(want, got string) bool
requireOriginWhenInvalid bool
matchValue bool
matchOrigin bool
matchDetail func(want, got string) bool
requireOriginWhenInvalid bool
matchValidationStabilityLevel bool
matchSource bool
// normalizationRules holds the pre-compiled regex patterns for path normalization.
normalizationRules []NormalizationRule
}
@@ -86,6 +88,14 @@ func (m ErrorMatcher) Matches(want, got *Error) bool {
if m.matchDetail != nil && !m.matchDetail(want.Detail, got.Detail) {
return false
}
if m.matchValidationStabilityLevel && want.ValidationStabilityLevel != got.ValidationStabilityLevel {
return false
}
if m.matchSource && want.FromImperative != got.FromImperative {
return false
}
return true
}
@@ -148,6 +158,14 @@ func (m ErrorMatcher) Render(e *Error) string {
comma()
buf.WriteString(fmt.Sprintf("Detail=%q", e.Detail))
}
if m.matchValidationStabilityLevel {
comma()
buf.WriteString(fmt.Sprintf("ValidationStabilityLevel=%s", e.ValidationStabilityLevel))
}
if m.matchSource {
comma()
buf.WriteString(fmt.Sprintf("FromImperative=%t", e.FromImperative))
}
return "{" + buf.String() + "}"
}
@@ -224,6 +242,20 @@ func (m ErrorMatcher) RequireOriginWhenInvalid() ErrorMatcher {
return m
}
// BySource returns a derived ErrorMatcher which also matches by the error origination
// value of field errors.
func (m ErrorMatcher) BySource() ErrorMatcher {
m.matchSource = true
return m
}
// ByValidationStabilityLevel returns a derived ErrorMatcher which also matches by the validation stability level
// value of field errors.
func (m ErrorMatcher) ByValidationStabilityLevel() ErrorMatcher {
m.matchValidationStabilityLevel = true
return m
}
// ByDetailExact returns a derived ErrorMatcher which also matches errors by
// the exact detail string.
func (m ErrorMatcher) ByDetailExact() ErrorMatcher {
+219 -13
View File
@@ -42,7 +42,7 @@ type Error struct {
// The value should be either:
// - A simple camelCase identifier (e.g., "maximum", "maxItems")
// - A structured format using "format=<dash-style-identifier>" for validation errors related to specific formats
// (e.g., "format=dns-label", "format=qualified-name")
// (e.g. "format=k8s-short-name")
//
// If the Origin corresponds to an existing declarative validation tag or JSON Schema keyword,
// use that same name for consistency.
@@ -55,10 +55,46 @@ type Error struct {
// validation. This field is to identify errors from imperative validation
// that should also be caught by declarative validation.
CoveredByDeclarative bool
// FromImperative denotes these errors are originating from the hand written validations.
FromImperative bool
// ValidationStabilityLevel denotes the validation stability level of the declarative validation from this error is returned. This should be used in the declarative validations only.
ValidationStabilityLevel ValidationStabilityLevel
}
// ValidationStabilityLevel denotes the stability level of a validation.
type ValidationStabilityLevel int
const (
stabilityLevelUnknown ValidationStabilityLevel = iota
stabilityLevelAlpha
stabilityLevelBeta
)
func (v ValidationStabilityLevel) String() string {
switch v {
case stabilityLevelAlpha:
return "alpha"
case stabilityLevelBeta:
return "beta"
default:
return "unknown"
}
}
var _ error = &Error{}
// IsAlpha returns true if the error is an alpha validation error.
func (e *Error) IsAlpha() bool {
return e.ValidationStabilityLevel == stabilityLevelAlpha
}
// IsBeta returns true if the error is a beta validation error.
func (e *Error) IsBeta() bool {
return e.ValidationStabilityLevel == stabilityLevelBeta
}
// Error implements the error interface.
func (e *Error) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.ErrorBody())
@@ -73,10 +109,10 @@ var omitValue = OmitValueType{}
func (e *Error) ErrorBody() string {
var s string
switch e.Type {
case ErrorTypeRequired, ErrorTypeForbidden, ErrorTypeTooLong, ErrorTypeInternal:
case ErrorTypeRequired, ErrorTypeForbidden, ErrorTypeTooLong, ErrorTypeTooShort, ErrorTypeInternal:
s = e.Type.String()
case ErrorTypeInvalid, ErrorTypeTypeInvalid, ErrorTypeNotSupported,
ErrorTypeNotFound, ErrorTypeDuplicate, ErrorTypeTooMany:
ErrorTypeNotFound, ErrorTypeDuplicate, ErrorTypeTooMany, ErrorTypeTooFew:
if e.BadValue == omitValue {
s = e.Type.String()
break
@@ -113,6 +149,7 @@ func (e *Error) ErrorBody() string {
if len(e.Detail) != 0 {
s += fmt.Sprintf(": %s", e.Detail)
}
return s
}
@@ -164,11 +201,18 @@ const (
// report that a given list has too many items. This is similar to FieldValueTooLong,
// but the error indicates quantity instead of length.
ErrorTypeTooMany ErrorType = "FieldValueTooMany"
// ErrorTypeTooFew is used to report "too few". This is used to
// report that a given list has too few items. This is similar to FieldValueTooLong,
// but the error indicates quantity instead of length.
ErrorTypeTooFew ErrorType = "FieldValueTooFew"
// ErrorTypeInternal is used to report other errors that are not related
// to user input. See InternalError().
ErrorTypeInternal ErrorType = "InternalError"
// ErrorTypeTypeInvalid is for the value did not match the schema type for that field
ErrorTypeTypeInvalid ErrorType = "FieldValueTypeInvalid"
// ErrorTypeTooShort is used to report that the given value is too short.
// This is similar to ErrorTypeInvalid. See TooShort().
ErrorTypeTooShort ErrorType = "FieldValueTooShort"
)
// String converts a ErrorType into its corresponding canonical error message.
@@ -190,10 +234,14 @@ func (t ErrorType) String() string {
return "Too long"
case ErrorTypeTooMany:
return "Too many"
case ErrorTypeTooFew:
return "Too few"
case ErrorTypeInternal:
return "Internal error"
case ErrorTypeTypeInvalid:
return "Invalid value"
case ErrorTypeTooShort:
return "Too short"
default:
return fmt.Sprintf("<unknown error %q>", string(t))
}
@@ -201,32 +249,56 @@ func (t ErrorType) String() string {
// TypeInvalid returns a *Error indicating "type is invalid"
func TypeInvalid(field *Path, value interface{}, detail string) *Error {
return &Error{ErrorTypeTypeInvalid, field.String(), value, detail, "", false}
return &Error{
Type: ErrorTypeTypeInvalid,
Field: field.String(),
BadValue: value,
Detail: detail,
}
}
// NotFound returns a *Error indicating "value not found". This is
// used to report failure to find a requested value (e.g. looking up an ID).
func NotFound(field *Path, value interface{}) *Error {
return &Error{ErrorTypeNotFound, field.String(), value, "", "", false}
return &Error{
Type: ErrorTypeNotFound,
Field: field.String(),
BadValue: value,
}
}
// Required returns a *Error indicating "value required". This is used
// to report required values that are not provided (e.g. empty strings, null
// values, or empty arrays).
func Required(field *Path, detail string) *Error {
return &Error{ErrorTypeRequired, field.String(), "", detail, "", false}
return &Error{
Type: ErrorTypeRequired,
Field: field.String(),
Detail: detail,
BadValue: "",
}
}
// Duplicate returns a *Error indicating "duplicate value". This is
// used to report collisions of values that must be unique (e.g. names or IDs).
func Duplicate(field *Path, value interface{}) *Error {
return &Error{ErrorTypeDuplicate, field.String(), value, "", "", false}
return &Error{
Type: ErrorTypeDuplicate,
Field: field.String(),
BadValue: value,
}
}
// Invalid returns a *Error indicating "invalid value". This is used
// to report malformed values (e.g. failed regex match, too long, out of bounds).
func Invalid(field *Path, value interface{}, detail string) *Error {
return &Error{ErrorTypeInvalid, field.String(), value, detail, "", false}
return &Error{
Type: ErrorTypeInvalid,
Field: field.String(),
BadValue: value,
Detail: detail,
}
}
// NotSupported returns a *Error indicating "unsupported value".
@@ -241,7 +313,12 @@ func NotSupported[T ~string](field *Path, value interface{}, validValues []T) *E
}
detail = "supported values: " + strings.Join(quotedValues, ", ")
}
return &Error{ErrorTypeNotSupported, field.String(), value, detail, "", false}
return &Error{
Type: ErrorTypeNotSupported,
Field: field.String(),
BadValue: value,
Detail: detail,
}
}
// Forbidden returns a *Error indicating "forbidden". This is used to
@@ -249,7 +326,12 @@ func NotSupported[T ~string](field *Path, value interface{}, validValues []T) *E
// some conditions, but which are not permitted by current conditions (e.g.
// security policy).
func Forbidden(field *Path, detail string) *Error {
return &Error{ErrorTypeForbidden, field.String(), "", detail, "", false}
return &Error{
Type: ErrorTypeForbidden,
Field: field.String(),
Detail: detail,
BadValue: "",
}
}
// TooLong returns a *Error indicating "too long". This is used to report that
@@ -267,7 +349,35 @@ func TooLong(field *Path, _ interface{}, maxLength int) *Error {
} else {
msg = "value is too long"
}
return &Error{ErrorTypeTooLong, field.String(), "<value omitted>", msg, "", false}
return &Error{
Type: ErrorTypeTooLong,
Field: field.String(),
BadValue: "<value omitted>",
Detail: msg,
}
}
// TooLongCharacters returns a *Error indicating "too long". This is used to report that
// the given value is too long in characters (including multi-byte characters).
// This is similar to Invalid, but the returned error will not include the too-long value.
// If maxLength is negative, it will be included in the message. The value argument is not used.
func TooLongCharacters[T ~string](field *Path, _ T, maxLength int) *Error {
var msg string
if maxLength >= 0 {
bs := "characters"
if maxLength == 1 {
bs = "character"
}
msg = fmt.Sprintf("may not be more than %d %s", maxLength, bs)
} else {
msg = "value is too long"
}
return &Error{
Type: ErrorTypeTooLong,
Field: field.String(),
BadValue: "<value omitted>",
Detail: msg,
}
}
// TooLongMaxLength returns a *Error indicating "too long".
@@ -299,14 +409,46 @@ func TooMany(field *Path, actualQuantity, maxQuantity int) *Error {
actual = omitValue
}
return &Error{ErrorTypeTooMany, field.String(), actual, msg, "", false}
return &Error{
Type: ErrorTypeTooMany,
Field: field.String(),
BadValue: actual,
Detail: msg,
}
}
// InternalError returns a *Error indicating "internal error". This is used
// to signal that an error was found that was not directly related to user
// input. The err argument must be non-nil.
func InternalError(field *Path, err error) *Error {
return &Error{ErrorTypeInternal, field.String(), nil, err.Error(), "", false}
return &Error{
Type: ErrorTypeInternal,
Field: field.String(),
BadValue: err,
Detail: err.Error(),
}
}
// TooShort returns a *Error indicating "too short". This is used to report that
// the given value is too short in characters. This is similar to Invalid.
// If minLength is non-negative, it will be included in the message.
func TooShort[T ~string](field *Path, value T, minLength int) *Error {
var msg string
if minLength >= 0 {
bs := "characters"
if minLength == 1 {
bs = "character"
}
msg = fmt.Sprintf("must be at least %d %s", minLength, bs)
} else {
msg = "value is too short"
}
return &Error{
Type: ErrorTypeTooShort,
Field: field.String(),
BadValue: value,
Detail: msg,
}
}
// ErrorList holds a set of Errors. It is plausible that we might one day have
@@ -397,6 +539,46 @@ func (list ErrorList) ExtractCoveredByDeclarative() ErrorList {
return newList
}
// MarkAlpha marks the error as an alpha validation error.
func (e *Error) MarkAlpha() *Error {
e.ValidationStabilityLevel = stabilityLevelAlpha
return e
}
// MarkAlpha marks the errors as alpha validation errors.
func (list ErrorList) MarkAlpha() ErrorList {
for _, err := range list {
err.ValidationStabilityLevel = stabilityLevelAlpha
}
return list
}
// MarkBeta marks the error as a beta validation error.
func (e *Error) MarkBeta() *Error {
e.ValidationStabilityLevel = stabilityLevelBeta
return e
}
// MarkBeta marks the errors as beta validation errors.
func (list ErrorList) MarkBeta() ErrorList {
for _, err := range list {
err.ValidationStabilityLevel = stabilityLevelBeta
}
return list
}
func (e *Error) MarkFromImperative() *Error {
e.FromImperative = true
return e
}
func (list ErrorList) MarkFromImperative() ErrorList {
for _, err := range list {
err.FromImperative = true
}
return list
}
// RemoveCoveredByDeclarative returns a new ErrorList containing only the errors that should not be covered by declarative validation.
func (list ErrorList) RemoveCoveredByDeclarative() ErrorList {
newList := ErrorList{}
@@ -407,3 +589,27 @@ func (list ErrorList) RemoveCoveredByDeclarative() ErrorList {
}
return newList
}
// TooFew returns a *Error indicating "too few". This is used to
// report that a given list has too few items. This is similar to TooLong,
// but the returned error indicates quantity instead of length.
func TooFew(field *Path, actualQuantity, minQuantity int) *Error {
var msg string
if minQuantity >= 0 {
is := "items"
if minQuantity == 1 {
is = "item"
}
msg = fmt.Sprintf("must have at least %d %s", minQuantity, is)
} else {
msg = "has too few items"
}
return &Error{
Type: ErrorTypeTooFew,
Field: field.String(),
BadValue: actualQuantity,
Detail: msg,
}
}