allow empty object to be CEL value.

This commit is contained in:
Jiahui Feng 2023-10-23 15:30:17 -07:00
parent 18d5a6fa64
commit c6b3a2f477
2 changed files with 24 additions and 11 deletions

View File

@ -84,18 +84,22 @@ func UnstructuredToVal(unstructured interface{}, schema Schema) ref.Val {
}, },
} }
} }
// A object with x-kubernetes-preserve-unknown-fields but no properties or additionalProperties is treated
// as an empty object. // properties and additionalProperties are mutual exclusive, but nothing prevents the situation
if schema.IsXPreserveUnknownFields() { // where both are missing.
return &unstructuredMap{ // An object that (1) has no properties (2) has no additionalProperties or additionalProperties == false
value: m, // is treated as an empty object.
schema: schema, // An object that has additionalProperties == true is treated as an unstructured map.
propSchema: func(key string) (Schema, bool) { // An object that has x-kubernetes-preserve-unknown-field extension set is treated as an unstructured map.
return nil, false // Empty object vs unstructured map is differentiated by unstructuredMap implementation with the set schema.
}, // The resulting result remains the same.
} return &unstructuredMap{
value: m,
schema: schema,
propSchema: func(key string) (Schema, bool) {
return nil, false
},
} }
return types.NewErr("invalid object type, expected either Properties or AdditionalProperties with Allows=true and non-empty Schema")
} }
if schema.Type() == "array" { if schema.Type() == "array" {

View File

@ -97,6 +97,9 @@ var (
Type: []string{"object"}, Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{Schema: stringSchema}, AdditionalProperties: &spec.SchemaOrBool{Schema: stringSchema},
}} }}
emptyObjectSchema = &spec.Schema{
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
}
) )
func TestEquality(t *testing.T) { func TestEquality(t *testing.T) {
@ -331,6 +334,12 @@ func TestEquality(t *testing.T) {
rhs: UnstructuredToVal([]interface{}{"a", "b", "c"}, atomicListSchema), rhs: UnstructuredToVal([]interface{}{"a", "b", "c"}, atomicListSchema),
equal: false, equal: false,
}, },
{
name: "empty objects are equal",
lhs: UnstructuredToVal(map[string]interface{}{}, emptyObjectSchema),
rhs: UnstructuredToVal(map[string]interface{}{}, emptyObjectSchema),
equal: true,
},
{ {
name: "identical objects are equal", name: "identical objects are equal",
lhs: UnstructuredToVal(map[string]interface{}{"field1": "a", "field2": "b"}, objectSchema), lhs: UnstructuredToVal(map[string]interface{}{"field1": "a", "field2": "b"}, objectSchema),