-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Optional struct literal fields in the API do not allow defaulting them via a Webhook #552
Comments
@pwittrock / @erictune - can you confirm that making these fields pointers is the intended approach with CRDs? I think we followed the convention from [pod] Deployments for making spec.Strategy a literal, and it seems unfortunate to have different conventions for CRD-based types and native types. |
I wasn't aware of this specific issue. I see this is a problem. The reason in that I and others have said to use pointers for optional is so that controllers, validation, and webhooks can distinguish between intentionally set to zero vs unset. I think some API implementors thought that they could skip the pointer if they could not think of a valid reason for setting to an empty value. But, it seems that is causing a problem. |
As I read it, this is not a CRD vs core types issue, right? If I wanted to write a webhook that mutated deployment strategy, then I would have the same problem, right? |
For this specific case, are you trying to set to a fixed default value? If so, does defaulting in the openAPI fix the problem? |
Not sure, it may work as the apiserver knows that appv1.Deployment has a
Well, not exactly, we want to set The docs on crd openapi tell me |
@mengqiy might know the answer to this one since he is more familiar with the webhook machinery. |
This will happen to both CRD and core types. This is a pointer vs non-pointer issue, aka round-tripping issue in k8s.
Not always. If the mutating webhook reacts on |
Is this a bug in the way we are calculating JSON patches? Perhaps another way of asking the question: if we constructed the JSON patch using a different mechanism, is it possible to express the object initialization and would apiserver correctly apply the patch? |
Interesting question. I think its not, because the json patch has to look different depending on if the user passed in The only way to make that happen would be to marshal the raw request object into a Ideally, we would have a different patch type that is less sensitive to these subtile difference or the option to have the webhook return the whole object instead of a patch. Unfortunately, json patch is the only supported way of altering an object via a |
/assign @alvaroaleman |
kubernetes-sigs/controller-runtime#256 should be able to help with the issue here. |
That approach is indeed a lot more elegant. I'd vote for just closing this issue then. If someone disagrees, just re-open it. /close |
@alvaroaleman: Closing this issue. 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. |
Currently we have a set of optional struct literal fields in our API, e.G: (This is an incomplete list):
cluster-api/pkg/apis/cluster/v1alpha1/cluster_types.go
Lines 52 to 53 in 19551f1
cluster-api/pkg/apis/cluster/v1alpha1/machinedeployment_types.go
Lines 42 to 43 in 19551f1
cluster-api/pkg/apis/cluster/v1alpha1/machine_types.go
Lines 68 to 69 in 19551f1
These are impossible to default via a
MutatingAdmissionWebhook
, because the only supported patch type currently isJsonpatch
. Ajsonpatch
is generated by marshalling an objectoriginal
and an objectcurrent
, then calculating the json patch for the diff. However the marshaled representation the Webhook that knows the types will always contain an empty object field ({}
) for the optional property when it is a literal, even whenomitempty
is set. Consequently, the resulting Jsonpatch will not try to add the main object but only its children. This patch will then get rejected by the APIServer with an error likedoc is missing path: "/spec/strategy/type
because it doesn't know anything about the main object (here:/spec/strategy
).The text was updated successfully, but these errors were encountered: