-
Notifications
You must be signed in to change notification settings - Fork 40k
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
Rest hooks for Create and Update #5970
Conversation
@@ -33,6 +33,10 @@ type RESTUpdateStrategy interface { | |||
NamespaceScoped() bool | |||
// AllowCreateOnUpdate returns true if the object can be created by a PUT. | |||
AllowCreateOnUpdate() bool | |||
// PrepareForUpdate is invoked on update before validation to normalize | |||
// the object. For example: remove fields that are not to be persisted, | |||
// sort order-insensitive list fields, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gofmt wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about it is wrong? gofmt runs on every save...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fixed now for some reason.
Don't see anything obviously wrong |
newPod := obj.(*api.Pod) | ||
oldPod := old.(*api.Pod) | ||
newPod.Status = oldPod.Status | ||
//FIXME: can Spec.Host be updated? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, ValidatePodUpdate
allows only container.image to be updated. That said, I think it's more clear for the request to fail at the validation than simply overwriting Spec.Host
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. @smarterclayton should we validate first? Or should we allow Prepare to return errors? Or should we intentionally copy Host over and let it fail in validation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intent was for prepare to do things that involve stripping invalid user input based on the semantics of the call. Status, things that are not intended to be allowed to change. Then validate runs and should fail if the user provides something.
Currently ValidateObjectMetaUpdate is doing some checks (creationTimestamp, etc) that should be handled before PrepareForUpdate and Validation are called:
Create
- Object meta is normalized
- PrepareForCreate
- ValidateCreate
Update
- Object meta is normalized
- PrepareForUpdate
- ValidateUpdate
----- Original Message -----
@@ -59,6 +59,14 @@ func (podStrategy) ResetBeforeCreate(obj runtime.Object)
{
}
}+// PrepareForUpdate clears fields that are not allowed to be set by end
users on update.
+func (podStrategy) PrepareForUpdate(obj, old runtime.Object) {
- newPod := obj.(*api.Pod)
- oldPod := old.(*api.Pod)
- newPod.Status = oldPod.Status
- //FIXME: can Spec.Host be updated?
That's a good point. @smarterclayton should we validate first? Or should we
allow Prepare to return errors? Or should we intentionally copy Host over
and let it fail in validation?
Reply to this email directly or view it on GitHub:
https://github.com/GoogleCloudPlatform/kubernetes/pull/5970/files#r27182480
And now integration does not pass. |
func (rcStrategy) PrepareForUpdate(obj, old runtime.Object) { | ||
newController := obj.(*api.ReplicationController) | ||
oldController := old.(*api.ReplicationController) | ||
newController.Status = oldController.Status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Humm, clearly I do not fully comprehend this logic. The existence of this line causes integration tests to fail.
E0325 20:15:57.728446 10801 replication_controller.go:175] unexpected sync error: replicationControllers "nginx-controller" cannot be updated: the resource was updated to 1306
Inspecting old and new I see new has Replicas = 2, and old has Replicas = 0.
I am not sure how to track this, and my lack of understanding makes me scared to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think replication controller does not have a subresource endpoint for status update (#4909), which means it relies on this update to update the status as well. Your change prevents that from happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ha, great observation. Given this framework, what is the fix? Just don't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, don't. Not until we add the status endpoint.
I pushed a new snapshot with everything fixed except the question of errors on invalid input. |
I will review this in the morning. Had fell off my radar |
@thockin could you please pass the ctx to PrepareForCreate/Update? My use case is I need to ensure the current user is authorized to reference another cluster resource. |
Vs us going now and adding CheckObjectIntegrity or something... which we could do. I'm a bit torn. If we add context to Create (which we should) then I think we're ok for now. ----- Original Message -----
|
func (namespaceStrategy) PrepareForUpdate(obj, old runtime.Object) { | ||
_ = obj.(*api.Namespace) | ||
_ = old.(*api.Namespace) | ||
// TODO(derekwaynecarr): help to implement? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to add:
namespace.Spec.Finalizers = oldNamespace.Spec.Finalizers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done in next push
regarding context, can I punt that to another PR (or back to you Andy) - I am trying to finish multi-port services, and can't afford any more distraction :) |
@smarterclayton I did not parse your last comment. Was that in regards to returning errors if the user tries to change immutable fields? What do you want me to do in this PR vs what can we file a bug on and come back to? |
That's fine, thanks
|
Prepare* for should set up the object so that Validate does not need to know about fields the user can't change. I.e., update clears status because some status updates are invalid, but for the normal path, a user cannot change status, and therefore validation should not have to return an immutable error. |
Put another way, Prepare* handles taking the context of an update (status, regular post, resize, binding) and ensures the object that will be passed to Validate is a true, properly formed resource object. Validate decides whether the changes are allowed at a fundamental level (is creationtimestamp allowed to change ever). Prepare* might ensure that creationtimestamp gets set properly, so validation doesn't have to make that distinction. |
new push is up with (I think) all comments addressed except passing context - @ncdc PTAL |
As per discussion with @snmarterclayton. I implemented this for most types in the "obvious" way. I am not sure how to implement this for a couple types, though.
Shippable is a flake, but travis passed. |
LGTM |
Rest hooks for Create and Update
Rename pre-create hooks and add pre-validate hooks. I need this for multi-port services.
@smarterclayton in general
@derekwaynecarr for advice on namespace updates
@bgrant0607 or @yujuhong for advice on pod updates