refactor: export correlated fields

This commit is contained in:
Alexander Zielenski 2023-10-10 10:15:50 -07:00
parent e73f3c8cdb
commit 83a1dbf885

View File

@ -60,11 +60,7 @@ func (r *RatchetingSchemaValidator) Validate(new interface{}) *validate.Result {
} }
func (r *RatchetingSchemaValidator) ValidateUpdate(new, old interface{}) *validate.Result { func (r *RatchetingSchemaValidator) ValidateUpdate(new, old interface{}) *validate.Result {
return newRatchetingValueValidator(&CorrelatedObject{ return newRatchetingValueValidator(NewCorrelatedObject(new, old, r.schema), r.schemaArgs).Validate(new)
oldValue: old,
value: new,
schema: r.schema,
}, r.schemaArgs).Validate(new)
} }
// ratchetingValueValidator represents an invocation of SchemaValidator.ValidateUpdate // ratchetingValueValidator represents an invocation of SchemaValidator.ValidateUpdate
@ -89,12 +85,12 @@ type ratchetingValueValidator struct {
type CorrelatedObject struct { type CorrelatedObject struct {
// Currently correlated old value during traversal of the schema/object // Currently correlated old value during traversal of the schema/object
oldValue interface{} OldValue interface{}
// Value being validated // Value being validated
value interface{} Value interface{}
schema *spec.Schema Schema *spec.Schema
// Scratch space below, may change during validation // Scratch space below, may change during validation
@ -117,6 +113,14 @@ type CorrelatedObject struct {
children map[interface{}]*CorrelatedObject children map[interface{}]*CorrelatedObject
} }
func NewCorrelatedObject(new, old interface{}, schema *spec.Schema) *CorrelatedObject {
return &CorrelatedObject{
OldValue: old,
Value: new,
Schema: schema,
}
}
func newRatchetingValueValidator(correlation *CorrelatedObject, args schemaArgs) *ratchetingValueValidator { func newRatchetingValueValidator(correlation *CorrelatedObject, args schemaArgs) *ratchetingValueValidator {
return &ratchetingValueValidator{ return &ratchetingValueValidator{
schemaArgs: args, schemaArgs: args,
@ -159,7 +163,7 @@ func (r *ratchetingValueValidator) Validate(new interface{}) *validate.Result {
s := validate.NewSchemaValidator(r.schema, r.root, r.path, r.knownFormats, opts...) s := validate.NewSchemaValidator(r.schema, r.root, r.path, r.knownFormats, opts...)
res := s.Validate(r.correlation.value) res := s.Validate(r.correlation.Value)
if res.IsValid() { if res.IsValid() {
return res return res
@ -226,12 +230,12 @@ func (r *ratchetingValueValidator) SubIndexValidator(index int, schema *spec.Sch
// If listType is map, creates a map representation of the list using the designated // If listType is map, creates a map representation of the list using the designated
// map-keys and caches it for future calls. // map-keys and caches it for future calls.
func (r *CorrelatedObject) correlateOldValueForChildAtNewIndex(index int) any { func (r *CorrelatedObject) correlateOldValueForChildAtNewIndex(index int) any {
oldAsList, ok := r.oldValue.([]interface{}) oldAsList, ok := r.OldValue.([]interface{})
if !ok { if !ok {
return nil return nil
} }
asList, ok := r.value.([]interface{}) asList, ok := r.Value.([]interface{})
if !ok { if !ok {
return nil return nil
} else if len(asList) <= index { } else if len(asList) <= index {
@ -239,7 +243,7 @@ func (r *CorrelatedObject) correlateOldValueForChildAtNewIndex(index int) any {
return nil return nil
} }
listType, _ := r.schema.Extensions.GetString("x-kubernetes-list-type") listType, _ := r.Schema.Extensions.GetString("x-kubernetes-list-type")
switch listType { switch listType {
case "map": case "map":
// Look up keys for this index in current object // Look up keys for this index in current object
@ -247,7 +251,7 @@ func (r *CorrelatedObject) correlateOldValueForChildAtNewIndex(index int) any {
oldList := r.mapList oldList := r.mapList
if oldList == nil { if oldList == nil {
oldList = celopenapi.MakeMapList(r.schema, oldAsList) oldList = celopenapi.MakeMapList(r.Schema, oldAsList)
r.mapList = oldList r.mapList = oldList
} }
return oldList.Get(currentElement) return oldList.Get(currentElement)
@ -292,14 +296,14 @@ func (r *CorrelatedObject) CachedDeepEqual() (res bool) {
r.comparisonResult = &res r.comparisonResult = &res
}() }()
if r.value == nil && r.oldValue == nil { if r.Value == nil && r.OldValue == nil {
return true return true
} else if r.value == nil || r.oldValue == nil { } else if r.Value == nil || r.OldValue == nil {
return false return false
} }
oldAsArray, oldIsArray := r.oldValue.([]interface{}) oldAsArray, oldIsArray := r.OldValue.([]interface{})
newAsArray, newIsArray := r.value.([]interface{}) newAsArray, newIsArray := r.Value.([]interface{})
if oldIsArray != newIsArray { if oldIsArray != newIsArray {
return false return false
@ -335,8 +339,8 @@ func (r *CorrelatedObject) CachedDeepEqual() (res bool) {
return true return true
} }
oldAsMap, oldIsMap := r.oldValue.(map[string]interface{}) oldAsMap, oldIsMap := r.OldValue.(map[string]interface{})
newAsMap, newIsMap := r.value.(map[string]interface{}) newAsMap, newIsMap := r.Value.(map[string]interface{})
if oldIsMap != newIsMap { if oldIsMap != newIsMap {
return false return false
@ -369,7 +373,7 @@ func (r *CorrelatedObject) CachedDeepEqual() (res bool) {
return true return true
} }
return reflect.DeepEqual(r.oldValue, r.value) return reflect.DeepEqual(r.OldValue, r.Value)
} }
var _ validate.ValueValidator = (&ratchetingValueValidator{}) var _ validate.ValueValidator = (&ratchetingValueValidator{})
@ -388,15 +392,15 @@ func (f ratchetingValueValidator) Applies(source interface{}, valueKind reflect.
// value is not correlatable to an old value. // value is not correlatable to an old value.
// If receiver is nil or if the new value is not an object/map, returns nil. // If receiver is nil or if the new value is not an object/map, returns nil.
func (l *CorrelatedObject) Key(field string) *CorrelatedObject { func (l *CorrelatedObject) Key(field string) *CorrelatedObject {
if l == nil || l.schema == nil { if l == nil || l.Schema == nil {
return nil return nil
} else if existing, exists := l.children[field]; exists { } else if existing, exists := l.children[field]; exists {
return existing return existing
} }
// Find correlated old value // Find correlated old value
oldAsMap, okOld := l.oldValue.(map[string]interface{}) oldAsMap, okOld := l.OldValue.(map[string]interface{})
newAsMap, okNew := l.value.(map[string]interface{}) newAsMap, okNew := l.Value.(map[string]interface{})
if !okOld || !okNew { if !okOld || !okNew {
return nil return nil
} }
@ -408,22 +412,19 @@ func (l *CorrelatedObject) Key(field string) *CorrelatedObject {
} }
var propertySchema *spec.Schema var propertySchema *spec.Schema
if prop, exists := l.schema.Properties[field]; exists { if prop, exists := l.Schema.Properties[field]; exists {
propertySchema = &prop propertySchema = &prop
} else if addP := l.schema.AdditionalProperties; addP != nil && addP.Schema != nil { } else if addP := l.Schema.AdditionalProperties; addP != nil && addP.Schema != nil {
propertySchema = addP.Schema propertySchema = addP.Schema
} else { } else {
return nil return nil
} }
res := &CorrelatedObject{
oldValue: oldValueForField,
value: newValueForField,
schema: propertySchema,
}
if l.children == nil { if l.children == nil {
l.children = make(map[interface{}]*CorrelatedObject, len(newAsMap)) l.children = make(map[interface{}]*CorrelatedObject, len(newAsMap))
} }
res := NewCorrelatedObject(newValueForField, oldValueForField, propertySchema)
l.children[field] = res l.children[field] = res
return res return res
} }
@ -433,13 +434,13 @@ func (l *CorrelatedObject) Key(field string) *CorrelatedObject {
// correlatable to an old value. // correlatable to an old value.
// If receiver is nil or if the new value is not an array, returns nil. // If receiver is nil or if the new value is not an array, returns nil.
func (l *CorrelatedObject) Index(i int) *CorrelatedObject { func (l *CorrelatedObject) Index(i int) *CorrelatedObject {
if l == nil || l.schema == nil { if l == nil || l.Schema == nil {
return nil return nil
} else if existing, exists := l.children[i]; exists { } else if existing, exists := l.children[i]; exists {
return existing return existing
} }
asList, ok := l.value.([]interface{}) asList, ok := l.Value.([]interface{})
if !ok || len(asList) <= i { if !ok || len(asList) <= i {
return nil return nil
} }
@ -449,20 +450,17 @@ func (l *CorrelatedObject) Index(i int) *CorrelatedObject {
return nil return nil
} }
var itemSchema *spec.Schema var itemSchema *spec.Schema
if i := l.schema.Items; i != nil && i.Schema != nil { if i := l.Schema.Items; i != nil && i.Schema != nil {
itemSchema = i.Schema itemSchema = i.Schema
} else { } else {
return nil return nil
} }
res := &CorrelatedObject{
oldValue: oldValueForIndex,
value: asList[i],
schema: itemSchema,
}
if l.children == nil { if l.children == nil {
l.children = make(map[interface{}]*CorrelatedObject, len(asList)) l.children = make(map[interface{}]*CorrelatedObject, len(asList))
} }
res := NewCorrelatedObject(asList[i], oldValueForIndex, itemSchema)
l.children[i] = res l.children[i] = res
return res return res
} }