mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Update err handling
This commit is contained in:
parent
460121fa1e
commit
50795b1afa
@ -84,14 +84,25 @@ func ValidateCustomResource(fldPath *field.Path, customResource interface{}, val
|
|||||||
if err.Value != nil {
|
if err.Value != nil {
|
||||||
value = err.Value
|
value = err.Value
|
||||||
}
|
}
|
||||||
allErrs = append(allErrs, field.TooLongFail(errPath, value, err.Error()))
|
max := int64(-1)
|
||||||
|
if i, ok := err.Value.(int64); ok {
|
||||||
case openapierrors.TooManyPropertiesCode, openapierrors.MaxItemsFailCode:
|
max = i
|
||||||
value := interface{}("")
|
|
||||||
if err.Value != nil {
|
|
||||||
value = err.Value
|
|
||||||
}
|
}
|
||||||
allErrs = append(allErrs, field.TooManyFail(errPath, value, err.Error()))
|
allErrs = append(allErrs, field.TooLongMaxLength(errPath, value, int(max)))
|
||||||
|
|
||||||
|
case openapierrors.MaxItemsFailCode:
|
||||||
|
max := int64(-1)
|
||||||
|
if i, ok := err.Value.(int64); ok {
|
||||||
|
max = i
|
||||||
|
}
|
||||||
|
allErrs = append(allErrs, field.TooMany(errPath, -1, int(max)))
|
||||||
|
|
||||||
|
case openapierrors.TooManyPropertiesCode:
|
||||||
|
max := int64(-1)
|
||||||
|
if i, ok := err.Value.(int64); ok {
|
||||||
|
max = i
|
||||||
|
}
|
||||||
|
allErrs = append(allErrs, field.TooMany(errPath, -1, int(max)))
|
||||||
|
|
||||||
case openapierrors.InvalidTypeCode:
|
case openapierrors.InvalidTypeCode:
|
||||||
value := interface{}("")
|
value := interface{}("")
|
||||||
|
@ -26,10 +26,9 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
|
utilpointer "k8s.io/utils/pointer"
|
||||||
kjson "sigs.k8s.io/json"
|
kjson "sigs.k8s.io/json"
|
||||||
|
|
||||||
kubeopenapispec "k8s.io/kube-openapi/pkg/validation/spec"
|
|
||||||
|
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||||
apiextensionsfuzzer "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer"
|
apiextensionsfuzzer "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
@ -41,6 +40,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
kubeopenapispec "k8s.io/kube-openapi/pkg/validation/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRoundTrip checks the conversion to go-openapi types.
|
// TestRoundTrip checks the conversion to go-openapi types.
|
||||||
@ -535,6 +535,51 @@ func TestValidateCustomResource(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{name: "maxProperties",
|
||||||
|
schema: apiextensions.JSONSchemaProps{
|
||||||
|
Properties: map[string]apiextensions.JSONSchemaProps{
|
||||||
|
"fieldX": {
|
||||||
|
Type: "object",
|
||||||
|
MaxProperties: utilpointer.Int64(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
failingObjects: []failingObject{
|
||||||
|
{object: map[string]interface{}{"fieldX": map[string]interface{}{"a": true, "b": true, "c": true}}, expectErrs: []string{
|
||||||
|
`fieldX: Too many: must have at most 2 items`,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{name: "maxItems",
|
||||||
|
schema: apiextensions.JSONSchemaProps{
|
||||||
|
Properties: map[string]apiextensions.JSONSchemaProps{
|
||||||
|
"fieldX": {
|
||||||
|
Type: "array",
|
||||||
|
MaxItems: utilpointer.Int64(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
failingObjects: []failingObject{
|
||||||
|
{object: map[string]interface{}{"fieldX": []interface{}{"a", "b", "c"}}, expectErrs: []string{
|
||||||
|
`fieldX: Too many: must have at most 3 items`,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{name: "maxLength",
|
||||||
|
schema: apiextensions.JSONSchemaProps{
|
||||||
|
Properties: map[string]apiextensions.JSONSchemaProps{
|
||||||
|
"fieldX": {
|
||||||
|
Type: "string",
|
||||||
|
MaxLength: utilpointer.Int64(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
failingObjects: []failingObject{
|
||||||
|
{object: map[string]interface{}{"fieldX": "abc"}, expectErrs: []string{
|
||||||
|
`fieldX: Too long: value is too long`,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
@ -42,12 +42,24 @@ func (v *Error) Error() string {
|
|||||||
return fmt.Sprintf("%s: %s", v.Field, v.ErrorBody())
|
return fmt.Sprintf("%s: %s", v.Field, v.ErrorBody())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type omitValueType struct{}
|
||||||
|
|
||||||
|
var omitValue = omitValueType{}
|
||||||
|
|
||||||
// ErrorBody returns the error message without the field name. This is useful
|
// ErrorBody returns the error message without the field name. This is useful
|
||||||
// for building nice-looking higher-level error reporting.
|
// for building nice-looking higher-level error reporting.
|
||||||
func (v *Error) ErrorBody() string {
|
func (v *Error) ErrorBody() string {
|
||||||
var s string
|
var s string
|
||||||
switch v.Type {
|
switch {
|
||||||
case ErrorTypeRequired, ErrorTypeForbidden, ErrorTypeTooLong, ErrorTypeInternal:
|
case v.Type == ErrorTypeRequired:
|
||||||
|
s = v.Type.String()
|
||||||
|
case v.Type == ErrorTypeForbidden:
|
||||||
|
s = v.Type.String()
|
||||||
|
case v.Type == ErrorTypeTooLong:
|
||||||
|
s = v.Type.String()
|
||||||
|
case v.Type == ErrorTypeInternal:
|
||||||
|
s = v.Type.String()
|
||||||
|
case v.BadValue == omitValue:
|
||||||
s = v.Type.String()
|
s = v.Type.String()
|
||||||
default:
|
default:
|
||||||
value := v.BadValue
|
value := v.BadValue
|
||||||
@ -226,11 +238,40 @@ func TooLong(field *Path, value interface{}, maxLength int) *Error {
|
|||||||
return &Error{ErrorTypeTooLong, field.String(), value, fmt.Sprintf("must have at most %d bytes", maxLength)}
|
return &Error{ErrorTypeTooLong, field.String(), value, fmt.Sprintf("must have at most %d bytes", maxLength)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TooLongMaxLength returns a *Error indicating "too long". This is used to
|
||||||
|
// report that the given value is too long. This is similar to
|
||||||
|
// Invalid, but the returned error will not include the too-long
|
||||||
|
// value. If maxLength is negative, no max length will be included in the message.
|
||||||
|
func TooLongMaxLength(field *Path, value interface{}, maxLength int) *Error {
|
||||||
|
var msg string
|
||||||
|
if maxLength >= 0 {
|
||||||
|
msg = fmt.Sprintf("may not be longer than %d", maxLength)
|
||||||
|
} else {
|
||||||
|
msg = "value is too long"
|
||||||
|
}
|
||||||
|
return &Error{ErrorTypeTooLong, field.String(), value, msg}
|
||||||
|
}
|
||||||
|
|
||||||
// TooMany returns a *Error indicating "too many". This is used to
|
// TooMany returns a *Error indicating "too many". This is used to
|
||||||
// report that a given list has too many items. This is similar to TooLong,
|
// report that a given list has too many items. This is similar to TooLong,
|
||||||
// but the returned error indicates quantity instead of length.
|
// but the returned error indicates quantity instead of length.
|
||||||
func TooMany(field *Path, actualQuantity, maxQuantity int) *Error {
|
func TooMany(field *Path, actualQuantity, maxQuantity int) *Error {
|
||||||
return &Error{ErrorTypeTooMany, field.String(), actualQuantity, fmt.Sprintf("must have at most %d items", maxQuantity)}
|
var msg string
|
||||||
|
|
||||||
|
if maxQuantity >= 0 {
|
||||||
|
msg = fmt.Sprintf("must have at most %d items", maxQuantity)
|
||||||
|
} else {
|
||||||
|
msg = "has too many items"
|
||||||
|
}
|
||||||
|
|
||||||
|
var actual interface{}
|
||||||
|
if actualQuantity >= 0 {
|
||||||
|
actual = actualQuantity
|
||||||
|
} else {
|
||||||
|
actual = omitValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Error{ErrorTypeTooMany, field.String(), actual, msg}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InternalError returns a *Error indicating "internal error". This is used
|
// InternalError returns a *Error indicating "internal error". This is used
|
||||||
|
Loading…
Reference in New Issue
Block a user