mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-17 23:57:49 +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 {
|
func genBytesWithRule(rule string) func(maxLength *int64) *schema.Structural {
|
||||||
return func(maxLength *int64) *schema.Structural {
|
return func(maxLength *int64) *schema.Structural {
|
||||||
return &schema.Structural{
|
return &schema.Structural{
|
||||||
@ -1744,6 +1773,13 @@ func TestCostEstimation(t *testing.T) {
|
|||||||
setMaxElements: 42,
|
setMaxElements: 42,
|
||||||
expectedSetCost: 8,
|
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 {
|
for _, testCase := range cases {
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
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) {
|
func hasBlockingErr(errs field.ErrorList) (bool, *field.Error) {
|
||||||
for _, err := range errs {
|
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")
|
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)
|
// unicode code point can be up to 4 bytes long)
|
||||||
strWithMaxLength.MaxElements = zeroIfNegative(*s.MaxLength()) * 4
|
strWithMaxLength.MaxElements = zeroIfNegative(*s.MaxLength()) * 4
|
||||||
} else {
|
} else {
|
||||||
strWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s)
|
if len(s.Enum()) > 0 {
|
||||||
|
strWithMaxLength.MaxElements = estimateMaxStringEnumLength(s)
|
||||||
|
} else {
|
||||||
|
strWithMaxLength.MaxElements = estimateMaxStringLengthPerRequest(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strWithMaxLength
|
return strWithMaxLength
|
||||||
case "boolean":
|
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
|
// estimateMaxArrayItemsPerRequest estimates the maximum number of array items with
|
||||||
// the provided minimum serialized size that can fit into a single request.
|
// the provided minimum serialized size that can fit into a single request.
|
||||||
func estimateMaxArrayItemsFromMinSize(minSize int64) int64 {
|
func estimateMaxArrayItemsFromMinSize(minSize int64) int64 {
|
||||||
|
Loading…
Reference in New Issue
Block a user