@@ -55,8 +55,15 @@ func SchemaDeclType(s Schema, isResourceRoot bool) *apiservercel.DeclType {
5555 // `type(intOrStringField) == int ? intOrStringField < 5 : double(intOrStringField.replace('%', '')) < 0.5
5656 //
5757 dyn := apiservercel .NewSimpleTypeWithMinSize ("dyn" , cel .DynType , nil , 1 ) // smallest value for a serialized x-kubernetes-int-or-string is 0
58- // handle x-kubernetes-int-or-string by returning the max length/min serialized size of the largest possible string
59- dyn .MaxElements = maxRequestSizeBytes - 2
58+
59+ // If the schema has a maxlength constraint, bound the max elements based on the max length.
60+ // Otherwise, fallback to the max request size.
61+ if s .MaxLength () != nil {
62+ dyn .MaxElements = estimateMaxElementsFromMaxLength (s )
63+ } else {
64+ dyn .MaxElements = estimateMaxStringLengthPerRequest (s )
65+ }
66+
6067 return dyn
6168 }
6269
@@ -159,11 +166,7 @@ func SchemaDeclType(s Schema, isResourceRoot bool) *apiservercel.DeclType {
159166
160167 strWithMaxLength := apiservercel .NewSimpleTypeWithMinSize ("string" , cel .StringType , types .String ("" ), apiservercel .MinStringSize )
161168 if s .MaxLength () != nil {
162- // multiply the user-provided max length by 4 in the case of an otherwise-untyped string
163- // we do this because the OpenAPIv3 spec indicates that maxLength is specified in runes/code points,
164- // but we need to reason about length for things like request size, so we use bytes in this code (and an individual
165- // unicode code point can be up to 4 bytes long)
166- strWithMaxLength .MaxElements = zeroIfNegative (* s .MaxLength ()) * 4
169+ strWithMaxLength .MaxElements = estimateMaxElementsFromMaxLength (s )
167170 } else {
168171 if len (s .Enum ()) > 0 {
169172 strWithMaxLength .MaxElements = estimateMaxStringEnumLength (s )
@@ -228,6 +231,7 @@ func WithTypeAndObjectMeta(s *spec.Schema) *spec.Schema {
228231// must only be called on schemas of type "string" or x-kubernetes-int-or-string: true
229232func estimateMaxStringLengthPerRequest (s Schema ) int64 {
230233 if s .IsXIntOrString () {
234+ // handle x-kubernetes-int-or-string by returning the max length/min serialized size of the largest possible string
231235 return maxRequestSizeBytes - 2
232236 }
233237 switch s .Format () {
@@ -272,3 +276,13 @@ func estimateMaxAdditionalPropertiesFromMinSize(minSize int64) int64 {
272276 // subtract 2 to account for { and }
273277 return (maxRequestSizeBytes - 2 ) / keyValuePairSize
274278}
279+
280+ // estimateMaxElementsFromMaxLength estimates the maximum number of elements for a string schema
281+ // that is bound with a maxLength constraint.
282+ func estimateMaxElementsFromMaxLength (s Schema ) int64 {
283+ // multiply the user-provided max length by 4 in the case of an otherwise-untyped string
284+ // we do this because the OpenAPIv3 spec indicates that maxLength is specified in runes/code points,
285+ // but we need to reason about length for things like request size, so we use bytes in this code (and an individual
286+ // unicode code point can be up to 4 bytes long)
287+ return zeroIfNegative (* s .MaxLength ()) * 4
288+ }
0 commit comments