You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: keps/sig-api-machinery/4153-declarative-validation/README.md
+16-14Lines changed: 16 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -799,7 +799,7 @@ We will need to add the ability for fields that re-use a type to specify a
799
799
field-level for its nested fields. Kube-openapi gen will inline the custom
800
800
definition.
801
801
802
-
#### Representing Go-isms in Schema
802
+
#### Zero values, `null`, and `omitempty`
803
803
804
804
Our native types are backed by Go and serialized into Go for mutation, defaulting
805
805
and other transformations before being used for validation. The schemas presented
@@ -822,7 +822,7 @@ and propose additional schema annotations to make our native type schemas more
822
822
representative of their implicit constraints to ensure all validations are
823
823
ported correctly.
824
824
825
-
##### Dropped Fields in Unstructured Conversion
825
+
##### `omitempty` Primitives Have Incorrect Schema
826
826
827
827
Consider the following omitempty non-pointer field from `DeploymentSpec`:
828
828
@@ -857,23 +857,25 @@ field not to be considered during validation, even if it was included.
857
857
This would surface as:
858
858
1.`has(self.paused)` in CEL on the Container object always returns `false` if
859
859
that value is `false`. But a CRD with identical schema would return `true`.
860
+
A proof of concept example of how this bug could bite users of ValidatingAdmissionPolicy
861
+
is [here](https://github.com/kubernetes/kubernetes/pull/120244).
860
862
2. CEL and JSONSchema Validations of the field if they exist also will not run.
863
+
But this is not a concern as long as empty values are assumed to match the schema.
861
864
862
-
This class of problem exclusively affects `omitempty` non-pointer fields: pointers
863
-
to the openapi-generater are treated as optionals and nil used to disambiguate
864
-
set/unset.
865
+
There are two alternative approaches to address the difference in behavior
866
+
of native types vs CRDs in the schema.
865
867
866
-
There are two alternative approaches to address this in the schema:
868
+
1. Express in schema that zero values are considered unset: by adding an
869
+
x-kubernetes extension like `x-kubernetes-zero-is-unset: true` to fields where
870
+
this is true.
871
+
2. Express in schema that unset values are considered zero: by settings its
872
+
`default` to the empty value for the type.
873
+
874
+
Option 2 has the drawback of applying a default to fields where the zero
875
+
value is not considered a default. For cases like `Paused` this is correct,
876
+
but for most cases involving `string`, the empty string is treated as `unset`.
867
877
868
-
1. Express in schema that zero values are considered unset by adding
869
-
an x-kubernetes extension like `x-kubernetes-zero-unset: true` to fields where
870
-
this is true.
871
-
2. Express in schema that unset values are considered zero by settings
872
-
its `default` to the empty value.
873
878
874
-
Option 2 seems best, since this is already done for `struct` types, there is
875
-
already support for `default` in OpenAPI, and the solution naturally expresses
876
-
Go's behavior of `unset` being implicitly defaulted to zero.
877
879
878
880
An exhaustive list of all 730 omit-empty non-pointer is [found here](https://gist.github.com/alexzielenski/05f594f3974aec9b3e74620b8dc7dde1). Struct types already have their
879
881
defaults populated with the go zero value, so they are excluded from this list.
0 commit comments