Return type instead of object

This commit is contained in:
cici37 2021-12-15 16:28:32 -08:00
parent 24a71990e0
commit 4a49e5f4ca
3 changed files with 17 additions and 17 deletions

View File

@ -132,14 +132,14 @@ func (s *Validator) validateExpressions(ctx context.Context, fldPath *field.Path
return nil, remainingBudget return nil, remainingBudget
} }
if s.compilationErr != nil { if s.compilationErr != nil {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("rule compiler initialization error: %v", s.compilationErr))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("rule compiler initialization error: %v", s.compilationErr)))
return errs, remainingBudget return errs, remainingBudget
} }
if len(s.compiledRules) == 0 { if len(s.compiledRules) == 0 {
return nil, remainingBudget // nothing to do return nil, remainingBudget // nothing to do
} }
if remainingBudget <= 0 { if remainingBudget <= 0 {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run")))
return errs, -1 return errs, -1
} }
if s.isResourceRoot { if s.isResourceRoot {
@ -149,7 +149,7 @@ func (s *Validator) validateExpressions(ctx context.Context, fldPath *field.Path
for i, compiled := range s.compiledRules { for i, compiled := range s.compiledRules {
rule := sts.XValidations[i] rule := sts.XValidations[i]
if compiled.Error != nil { if compiled.Error != nil {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("rule compile error: %v", compiled.Error))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("rule compile error: %v", compiled.Error)))
continue continue
} }
if compiled.Program == nil { if compiled.Program == nil {
@ -168,11 +168,11 @@ func (s *Validator) validateExpressions(ctx context.Context, fldPath *field.Path
} else { } else {
rtCost := evalDetails.ActualCost() rtCost := evalDetails.ActualCost()
if rtCost == nil { if rtCost == nil {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("runtime cost could not be calculated for validation rule: %v, no further validation rules will be run", ruleErrorString(rule)))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("runtime cost could not be calculated for validation rule: %v, no further validation rules will be run", ruleErrorString(rule))))
return errs, -1 return errs, -1
} else { } else {
if *rtCost > math.MaxInt64 || int64(*rtCost) > remainingBudget { if *rtCost > math.MaxInt64 || int64(*rtCost) > remainingBudget {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run"))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("validation failed due to running out of cost budget, no further validation rules will be run")))
return errs, -1 return errs, -1
} }
remainingBudget -= int64(*rtCost) remainingBudget -= int64(*rtCost)
@ -185,21 +185,21 @@ func (s *Validator) validateExpressions(ctx context.Context, fldPath *field.Path
// error was found. Here, an overload error has occurred at runtime no details are provided, so we // error was found. Here, an overload error has occurred at runtime no details are provided, so we
// append a more descriptive error message. This error can only occur when static type checking has // append a more descriptive error message. This error can only occur when static type checking has
// been bypassed. int-or-string is typed as dynamic and so bypasses compiler type checking. // been bypassed. int-or-string is typed as dynamic and so bypasses compiler type checking.
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("'%v': call arguments did not match a supported operator, function or macro signature for rule: %v", err, ruleErrorString(rule)))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("'%v': call arguments did not match a supported operator, function or macro signature for rule: %v", err, ruleErrorString(rule))))
} else if strings.HasPrefix(err.Error(), "operation cancelled: actual cost limit exceeded") { } else if strings.HasPrefix(err.Error(), "operation cancelled: actual cost limit exceeded") {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("'%v': no further validation rules will be run due to call cost exceeds limit for rule: %v", err, ruleErrorString(rule)))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("'%v': no further validation rules will be run due to call cost exceeds limit for rule: %v", err, ruleErrorString(rule))))
return errs, -1 return errs, -1
} else { } else {
// no such key: {key}, index out of bounds: {index}, integer overflow, division by zero, ... // no such key: {key}, index out of bounds: {index}, integer overflow, division by zero, ...
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("%v evaluating rule: %v", err, ruleErrorString(rule)))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("%v evaluating rule: %v", err, ruleErrorString(rule))))
} }
continue continue
} }
if evalResult != types.True { if evalResult != types.True {
if len(rule.Message) != 0 { if len(rule.Message) != 0 {
errs = append(errs, field.Invalid(fldPath, obj, rule.Message)) errs = append(errs, field.Invalid(fldPath, sts.Type, rule.Message))
} else { } else {
errs = append(errs, field.Invalid(fldPath, obj, fmt.Sprintf("failed rule: %s", ruleErrorString(rule)))) errs = append(errs, field.Invalid(fldPath, sts.Type, fmt.Sprintf("failed rule: %s", ruleErrorString(rule))))
} }
} }
} }

View File

@ -1444,11 +1444,11 @@ func TestValidationExpressions(t *testing.T) {
}), }),
errors: map[string]string{ errors: map[string]string{
// data is validated before CEL evaluation, so these errors should not be surfaced to end users // data is validated before CEL evaluation, so these errors should not be surfaced to end users
"has(self.o)": "invalid data, expected map[string]interface{} to match the provided schema with type=object", "has(self.o)": "invalid data, expected a map for the provided schema with type=object",
"has(self.m)": "invalid data, expected map[string]interface{} to match the provided schema with type=object", "has(self.m)": "invalid data, expected a map for the provided schema with type=object",
"has(self.l)": "invalid data, expected []interface{} to match the provided schema with type=array", "has(self.l)": "invalid data, expected an array for the provided schema with type=array",
"has(self.s)": "invalid data, expected []interface{} to match the provided schema with type=array", "has(self.s)": "invalid data, expected an array for the provided schema with type=array",
"has(self.lm)": "invalid data, expected []interface{} to match the provided schema with type=array", "has(self.lm)": "invalid data, expected an array for the provided schema with type=array",
"has(self.intorstring)": "invalid data, expected XIntOrString value to be either a string or integer", "has(self.intorstring)": "invalid data, expected XIntOrString value to be either a string or integer",
"self.nullable[0] == 'x'": "invalid data, got null for schema with nullable=false", "self.nullable[0] == 'x'": "invalid data, got null for schema with nullable=false",
// TODO: also find a way to test the errors returned for: array with no items, object with no properties or additionalProperties, invalid listType and invalid type. // TODO: also find a way to test the errors returned for: array with no items, object with no properties or additionalProperties, invalid listType and invalid type.

View File

@ -58,7 +58,7 @@ func UnstructuredToVal(unstructured interface{}, schema *structuralschema.Struct
if schema.Type == "object" { if schema.Type == "object" {
m, ok := unstructured.(map[string]interface{}) m, ok := unstructured.(map[string]interface{})
if !ok { if !ok {
return types.NewErr("invalid data, expected map[string]interface{} to match the provided schema with type=object") return types.NewErr("invalid data, expected a map for the provided schema with type=object")
} }
if schema.XEmbeddedResource || schema.Properties != nil { if schema.XEmbeddedResource || schema.Properties != nil {
if schema.XEmbeddedResource { if schema.XEmbeddedResource {
@ -101,7 +101,7 @@ func UnstructuredToVal(unstructured interface{}, schema *structuralschema.Struct
if schema.Type == "array" { if schema.Type == "array" {
l, ok := unstructured.([]interface{}) l, ok := unstructured.([]interface{})
if !ok { if !ok {
return types.NewErr("invalid data, expected []interface{} to match the provided schema with type=array") return types.NewErr("invalid data, expected an array for the provided schema with type=array")
} }
if schema.Items == nil { if schema.Items == nil {
return types.NewErr("invalid array type, expected Items with a non-empty Schema") return types.NewErr("invalid array type, expected Items with a non-empty Schema")