mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-16 23:29:21 +00:00
Merge pull request #121085 from jiahuif-forks/fix/crd-validation-expressions/enum-cost
CRD Validation Expresions: set maxLength to longest enum.
This commit is contained in:
commit
0304c567b6
@ -989,6 +989,35 @@ func genStringWithRule(rule string) func(maxLength *int64) *schema.Structural {
|
||||
}
|
||||
}
|
||||
|
||||
// genEnumWithRuleAndValues creates a function that accepts an optional maxLength
|
||||
// with given validation rule and a set of enum values, following the convention of existing tests.
|
||||
// The test has two checks, first with maxLength unset to check if maxLength can be concluded from enums,
|
||||
// second with maxLength set to ensure it takes precedence.
|
||||
func genEnumWithRuleAndValues(rule string, values ...string) func(maxLength *int64) *schema.Structural {
|
||||
enums := make([]schema.JSON, 0, len(values))
|
||||
for _, v := range values {
|
||||
enums = append(enums, schema.JSON{Object: v})
|
||||
}
|
||||
return func(maxLength *int64) *schema.Structural {
|
||||
return &schema.Structural{
|
||||
Generic: schema.Generic{
|
||||
Type: "string",
|
||||
},
|
||||
ValueValidation: &schema.ValueValidation{
|
||||
MaxLength: maxLength,
|
||||
Enum: enums,
|
||||
},
|
||||
Extensions: schema.Extensions{
|
||||
XValidations: apiextensions.ValidationRules{
|
||||
{
|
||||
Rule: rule,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func genBytesWithRule(rule string) func(maxLength *int64) *schema.Structural {
|
||||
return func(maxLength *int64) *schema.Structural {
|
||||
return &schema.Structural{
|
||||
@ -1744,6 +1773,13 @@ func TestCostEstimation(t *testing.T) {
|
||||
setMaxElements: 42,
|
||||
expectedSetCost: 8,
|
||||
},
|
||||
{
|
||||
name: "enums with maxLength equals to the longest possible value",
|
||||
schemaGenerator: genEnumWithRuleAndValues("self.contains('A')", "A", "B", "C", "LongValue"),
|
||||
expectedCalcCost: 2,
|
||||
setMaxElements: 1000,
|
||||
expectedSetCost: 401,
|
||||
},
|
||||
}
|
||||
for _, testCase := range cases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
|
@ -306,10 +306,10 @@ func (a customResourceStrategy) MatchCustomResourceDefinitionStorage(label label
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAPIv3 type/maxLength/maxItems/MaxProperties/required/wrong type field validation failures are viewed as blocking err for CEL validation
|
||||
// OpenAPIv3 type/maxLength/maxItems/MaxProperties/required/enum violation/wrong type field validation failures are viewed as blocking err for CEL validation
|
||||
func hasBlockingErr(errs field.ErrorList) (bool, *field.Error) {
|
||||
for _, err := range errs {
|
||||
if err.Type == field.ErrorTypeRequired || err.Type == field.ErrorTypeTooLong || err.Type == field.ErrorTypeTooMany || err.Type == field.ErrorTypeTypeInvalid {
|
||||
if err.Type == field.ErrorTypeNotSupported || err.Type == field.ErrorTypeRequired || err.Type == field.ErrorTypeTooLong || err.Type == field.ErrorTypeTooMany || err.Type == field.ErrorTypeTypeInvalid {
|
||||
return true, field.Invalid(nil, nil, "some validation rules were not checked because the object was invalid; correct the existing errors to complete validation")
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,11 @@ func SchemaDeclType(s Schema, isResourceRoot bool) *apiservercel.DeclType {
|
||||
// unicode code point can be up to 4 bytes long)
|
||||
strWithMaxLength.MaxElements = zeroIfNegative(*s.MaxLength()) * 4
|
||||
} else {
|
||||
strWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s)
|
||||
if len(s.Enum()) > 0 {
|
||||
strWithMaxLength.MaxElements = estimateMaxStringEnumLength(s)
|
||||
} else {
|
||||
strWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s)
|
||||
}
|
||||
}
|
||||
return strWithMaxLength
|
||||
case "boolean":
|
||||
@ -239,6 +243,19 @@ func estimateMaxStringLengthPerRequest(s Schema) int64 {
|
||||
}
|
||||
}
|
||||
|
||||
// estimateMaxStringLengthPerRequest estimates the maximum string length (in characters)
|
||||
// that has a set of enum values.
|
||||
// The result of the estimation is the length of the longest possible value.
|
||||
func estimateMaxStringEnumLength(s Schema) int64 {
|
||||
var maxLength int64
|
||||
for _, v := range s.Enum() {
|
||||
if s, ok := v.(string); ok && int64(len(s)) > maxLength {
|
||||
maxLength = int64(len(s))
|
||||
}
|
||||
}
|
||||
return maxLength
|
||||
}
|
||||
|
||||
// estimateMaxArrayItemsPerRequest estimates the maximum number of array items with
|
||||
// the provided minimum serialized size that can fit into a single request.
|
||||
func estimateMaxArrayItemsFromMinSize(minSize int64) int64 {
|
||||
|
Loading…
Reference in New Issue
Block a user