mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-17 15:50:10 +00:00
Merge pull request #121459 from jiahuif-forks/feature/cel/allow-empty-object
allow empty object to be CEL value.
This commit is contained in:
commit
ab096ef3de
@ -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.
|
||||
if schema.IsXPreserveUnknownFields() {
|
||||
return &unstructuredMap{
|
||||
value: m,
|
||||
schema: schema,
|
||||
propSchema: func(key string) (Schema, bool) {
|
||||
return nil, false
|
||||
},
|
||||
}
|
||||
|
||||
// properties and additionalProperties are mutual exclusive, but nothing prevents the situation
|
||||
// where both are missing.
|
||||
// An object that (1) has no properties (2) has no additionalProperties or additionalProperties == false
|
||||
// is treated as an empty object.
|
||||
// An object that has additionalProperties == true is treated as an unstructured map.
|
||||
// An object that has x-kubernetes-preserve-unknown-field extension set is treated as an unstructured map.
|
||||
// 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" {
|
||||
|
@ -97,6 +97,9 @@ var (
|
||||
Type: []string{"object"},
|
||||
AdditionalProperties: &spec.SchemaOrBool{Schema: stringSchema},
|
||||
}}
|
||||
emptyObjectSchema = &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{Type: []string{"object"}},
|
||||
}
|
||||
)
|
||||
|
||||
func TestEquality(t *testing.T) {
|
||||
@ -331,6 +334,12 @@ func TestEquality(t *testing.T) {
|
||||
rhs: UnstructuredToVal([]interface{}{"a", "b", "c"}, atomicListSchema),
|
||||
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",
|
||||
lhs: UnstructuredToVal(map[string]interface{}{"field1": "a", "field2": "b"}, objectSchema),
|
||||
|
@ -301,6 +301,13 @@ func TestCustomResourceValidators(t *testing.T) {
|
||||
t.Error("Unexpected error creating custom resource but metadata validation rule")
|
||||
}
|
||||
})
|
||||
t.Run("CRD creation MUST pass for an CRD with empty field", func(t *testing.T) {
|
||||
structuralWithValidators := crdWithSchema(t, "WithEmptyObject", structuralSchemaWithEmptyObject)
|
||||
_, err := fixtures.CreateNewV1CustomResourceDefinition(structuralWithValidators, apiExtensionClient, dynamicClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error creating CRD with empty field: %v", err)
|
||||
}
|
||||
})
|
||||
t.Run("CR creation MUST fail if a x-kubernetes-validations rule exceeds the runtime cost limit", func(t *testing.T) {
|
||||
structuralWithValidators := crdWithSchema(t, "RuntimeCostLimit", structuralSchemaWithCostLimit)
|
||||
crd, err := fixtures.CreateNewV1CustomResourceDefinition(structuralWithValidators, apiExtensionClient, dynamicClient)
|
||||
@ -1101,3 +1108,26 @@ var structuralSchemaWithCostLimit = []byte(`
|
||||
}
|
||||
}
|
||||
}`)
|
||||
|
||||
var structuralSchemaWithEmptyObject = []byte(`
|
||||
{
|
||||
"openAPIV3Schema": {
|
||||
"description": "weird CRD with empty spec, unstructured status. designed to fit test fixtures.",
|
||||
"type": "object",
|
||||
"x-kubernetes-validations": [
|
||||
{
|
||||
"rule": "[has(self.spec), has(self.status)].exists_one(x, x)"
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"spec": {
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
Loading…
Reference in New Issue
Block a user