mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-18 22:40:35 +00:00
feat(validation): enhance slice validation with declarative options
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -1097,28 +1098,49 @@ func validateCIdentifier(id string, fldPath *field.Path) field.ErrorList {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validationOption is an option for validation.
|
||||
type validationOption int
|
||||
|
||||
const (
|
||||
// The validation of each item is covered by declarative validation.
|
||||
itemsCovered validationOption = iota
|
||||
// The list size check is covered by declarative validation.
|
||||
sizeCovered
|
||||
// The uniqueness check is covered by declarative validation.
|
||||
uniquenessCovered
|
||||
)
|
||||
|
||||
// validateSlice ensures that a slice does not exceed a certain maximum size
|
||||
// and that all entries are valid.
|
||||
// A negative maxSize disables the length check.
|
||||
func validateSlice[T any](slice []T, maxSize int, validateItem func(T, *field.Path) field.ErrorList, fldPath *field.Path) field.ErrorList {
|
||||
func validateSlice[T any](slice []T, maxSize int, validateItem func(T, *field.Path) field.ErrorList, fldPath *field.Path, opts ...validationOption) field.ErrorList {
|
||||
var allErrs field.ErrorList
|
||||
for i, item := range slice {
|
||||
idxPath := fldPath.Index(i)
|
||||
allErrs = append(allErrs, validateItem(item, idxPath)...)
|
||||
errs := validateItem(item, idxPath)
|
||||
if slices.Contains(opts, itemsCovered) {
|
||||
errs = errs.MarkCoveredByDeclarative()
|
||||
}
|
||||
allErrs = append(allErrs, errs...)
|
||||
}
|
||||
if maxSize >= 0 && len(slice) > maxSize {
|
||||
// Dumping the entire field into the error message is likely to be too long,
|
||||
// in particular when it is already beyond the maximum size. Instead this
|
||||
// just shows the number of entries.
|
||||
allErrs = append(allErrs, field.TooMany(fldPath, len(slice), maxSize))
|
||||
err := field.TooMany(fldPath, len(slice), maxSize)
|
||||
if slices.Contains(opts, sizeCovered) {
|
||||
err = err.MarkCoveredByDeclarative()
|
||||
}
|
||||
allErrs = append(allErrs, err)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateSet ensures that a slice contains no duplicates, does not
|
||||
// exceed a certain maximum size and that all entries are valid.
|
||||
func validateSet[T any, K comparable](slice []T, maxSize int, validateItem func(item T, fldPath *field.Path) field.ErrorList, itemKey func(T) (K, string), fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateSlice(slice, maxSize, validateItem, fldPath)
|
||||
func validateSet[T any, K comparable](slice []T, maxSize int, validateItem func(item T, fldPath *field.Path) field.ErrorList, itemKey func(T) (K, string), fldPath *field.Path, opts ...validationOption) field.ErrorList {
|
||||
allErrs := validateSlice(slice, maxSize, validateItem, fldPath, opts...)
|
||||
|
||||
allItems := sets.New[K]()
|
||||
for i, item := range slice {
|
||||
idxPath := fldPath.Index(i)
|
||||
@@ -1128,7 +1150,11 @@ func validateSet[T any, K comparable](slice []T, maxSize int, validateItem func(
|
||||
childPath = childPath.Child(fieldName)
|
||||
}
|
||||
if allItems.Has(key) {
|
||||
allErrs = append(allErrs, field.Duplicate(childPath, key))
|
||||
err := field.Duplicate(childPath, key)
|
||||
if slices.Contains(opts, uniquenessCovered) {
|
||||
err = err.MarkCoveredByDeclarative()
|
||||
}
|
||||
allErrs = append(allErrs, err)
|
||||
} else {
|
||||
allItems.Insert(key)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user