-
Notifications
You must be signed in to change notification settings - Fork 416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Support for oneOf Groups for Discriminate Types #298
Conversation
Welcome @seglberg! |
Thanks for your pull request. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please follow instructions at https://git.k8s.io/community/CLA.md#the-contributor-license-agreement to sign the CLA. It may take a couple minutes for the CLA signature to be fully registered; after that, please reply here with a new comment and we'll verify. Thanks.
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: seglberg The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/hold a) you'll need to sign the CLA b) I'd like to see a more comprehensive design for this c) this might be a foot-gun considering some uses of one-of could produce "non-structural" schemata (https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#specifying-a-structural-schema) d) we generally discourage this pattern, preferring unions instead (we'll need to support the |
I'll gladly sign the CLA if this ends up going anywhere significant since it sounds like I may have gone down the wrong road here. I didn't seem to come across any concepts of a Union type when digging at the current sources. I had been modeling my APIs after Kubernetes 1.15 types such as VolumeSource. Is there more information or docs you could point me towards so that I may formulate a more comprehensive design for this? |
Ah. So I just ran across https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/20190425-structural-openapi.md I'm still getting my bearing around the Kubernetes project structure... but it looks like the Union extensions have yet to land? |
The union thing is a new feature that codifies a pattern that we've had for a while. And yeah, it's hard to navigate those some times. union appears to have half-landed, but I think we can produce the equivalent openapi off of the standard union markers introduced in the union kep linked in that doc ( |
also @apelisse @jennybuckley might know more about the state of the union bits, but I don't see XUnion as part of the JSON schema types yet, but it's in kube-openapi already. |
Producing (or "unfolding" as one of the docs put it) the equivalent openapi schema shouldn't be too difficult until there is full support for the extension. That begs the question. In the example: x-kubernetes-unions:
- discriminator: type
fields-discriminated:
foo: Foo
bar: Bar
oneOf:
- required: ["foo"]
- required: ["bar"]
properties:
type:
type: string
enum:
- Foo
- Bar should the discriminator inside the oneOf be set to a narrowed enum? Until the apiserver supports setting the discriminator field for us, we need to lock it down so users cannot do something like setting the field For now, I would think a more correct expansion would be: oneOf:
- required: ["foo"]
properties:
type:
enum:
- Foo
- required: ["bar"]
properties:
type:
enum:
- Bar |
There's an OpenAPI concept of a discriminator. That should be sufficient to prevent that case. |
+1 on what @DirectXMan12 says, we don't know if it's going to land in 1.16, we can't really agree on all the semantics for union, but we're working on it. Also, I don't think I'm opposed to have the "oneOf" field being generated by kube-builder. The "union" marker that we're proposing in the KEP is orthogonal and still requires validation. |
I think unfolding does not harm. The first one looks good:
But the other one is wrong because
|
Issues go stale after 90d of inactivity. If this issue is safe to close now please do so with Send feedback to sig-testing, kubernetes/test-infra and/or fejta. |
/lifecycle frozen |
To generate CRD validation schemas (also known as structual validation schemas[1]), we bring in controller-tools. This houses a tool called controller-gen which performs various K8s related code generation. Note that we are using a fork of controller-tools due to the upstream (as of v0.3.0) lacking support in two main areas. 1) A type which implements custom JSON marshalling has its validation schema generation skipped. In our case, api.Rule (which is set as the Spec field in CNP and CCNP) implements custom JSON marshalling. With the upstream tool, this skips the validation generation for it. In our fork, we revert this feature. See PR: kubernetes-sigs/controller-tools#427 2) For CNP and CCNP, we require `oneOf` validation for the endpointSelector and nodeSelector fields. This is because we want to validate that either endpointSelector OR nodeSelector is present, but not both, and at least one. In the upstream, there's currently an open PR that implements support for this. We have manually merged it in our fork. See PR: kubernetes-sigs/controller-tools#298 This commit also brings updates to our dependencies: - gomega v1.7.0 -> v1.8.1 - golang.org/x/internal/{tools,event...} [1]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema Co-authored-by: Chris Tarazi <chris@isovalent.com> Signed-off-by: André Martins <andre@cilium.io> Signed-off-by: Chris Tarazi <chris@isovalent.com>
To generate CRD validation schemas (also known as structual validation schemas[1]), we bring in controller-tools. This houses a tool called controller-gen which performs various K8s related code generation. Note that we are using a fork of controller-tools due to the upstream (as of v0.3.0) lacking support in two main areas. 1) A type which implements custom JSON marshalling has its validation schema generation skipped. In our case, api.Rule (which is set as the Spec field in CNP and CCNP) implements custom JSON marshalling. With the upstream tool, this skips the validation generation for it. In our fork, we revert this feature. See PR: kubernetes-sigs/controller-tools#427 2) For CNP and CCNP, we require `oneOf` validation for the endpointSelector and nodeSelector fields. This is because we want to validate that either endpointSelector OR nodeSelector is present, but not both, and at least one. In the upstream, there's currently an open PR that implements support for this. We have manually merged it in our fork. See PR: kubernetes-sigs/controller-tools#298 This commit also brings updates to our dependencies: - gomega v1.7.0 -> v1.8.1 - golang.org/x/internal/{tools,event...} [1]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema Co-authored-by: Chris Tarazi <chris@isovalent.com> Signed-off-by: André Martins <andre@cilium.io> Signed-off-by: Chris Tarazi <chris@isovalent.com>
@mmellison: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
This approach seems like it could block adopting an approach that permits multiple fieldA or fieldB are required and |
The This bot removes
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /remove-lifecycle frozen |
@seglberg is this PR officially obsolete? |
Closing this due to lack of updates, feel free to pick it up again as needed |
/close |
@vincepri: Closed this PR. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
In case anyone picks this up again, I think, from the docs about union types, that we need to support an "at most one" not an "exactly one". Based on that, I think the schema needs to be more like this below to allow 1, the other, or neither
I also noticed that in the doc it talks about the idea of having multiple unions embedded within a single struct, to allow this we need to satisfy each union separately, so I think we can do (this represents the two inlined unions in
I tested this and seemed to be able to add If no one is planning to take this work up, I might try to do this as it would be useful for something I'm working on soon |
These changes add support for the field marker:
kubebuilder:validation:OneOf
which will generate aoneOf
block in the CRD structural definition[1]. This could be expanded in the future to include more complex oneOf objects, however for now, it works to simply define fields which are mutually exclusive:becomes
This then allows the CRD to enforce a mutually exclusive type:
produces
"spec" must validate one and only one schema (oneOf). Found 2 valid alternatives
produces
"spec" must validate one and only one schema (oneOf). Found none valid
[1] https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/