Skip to content
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

Merged
merged 2 commits into from
Mar 26, 2015

Conversation

thockin
Copy link
Member

@thockin thockin commented Mar 26, 2015

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

@@ -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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gofmt wrong?

Copy link
Member Author

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...

Copy link
Contributor

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.

@smarterclayton
Copy link
Contributor

Don't see anything obviously wrong

newPod := obj.(*api.Pod)
oldPod := old.(*api.Pod)
newPod.Status = oldPod.Status
//FIXME: can Spec.Host be updated?
Copy link
Contributor

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.

Copy link
Member Author

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?

Copy link
Contributor

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

  1. Object meta is normalized
  2. PrepareForCreate
  3. ValidateCreate

Update

  1. Object meta is normalized
  2. PrepareForUpdate
  3. 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

@thockin
Copy link
Member Author

thockin commented Mar 26, 2015

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
Copy link
Member Author

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.

Copy link
Contributor

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.

Copy link
Member Author

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?

Copy link
Contributor

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.

@thockin
Copy link
Member Author

thockin commented Mar 26, 2015

I pushed a new snapshot with everything fixed except the question of errors on invalid input.

@derekwaynecarr
Copy link
Member

I will review this in the morning. Had fell off my radar

@ncdc
Copy link
Member

ncdc commented Mar 26, 2015

@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.

@smarterclayton
Copy link
Contributor

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 -----

@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.


Reply to this email directly or view it on GitHub:
#5970 (comment)

func (namespaceStrategy) PrepareForUpdate(obj, old runtime.Object) {
_ = obj.(*api.Namespace)
_ = old.(*api.Namespace)
// TODO(derekwaynecarr): help to implement?
Copy link
Member

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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in next push

@thockin
Copy link
Member Author

thockin commented Mar 26, 2015

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 :)

@thockin
Copy link
Member Author

thockin commented Mar 26, 2015

@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?

@ncdc
Copy link
Member

ncdc commented Mar 26, 2015

That's fine, thanks
On Thu, Mar 26, 2015 at 2:55 PM Tim Hockin notifications@github.com wrote:

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 :)


Reply to this email directly or view it on GitHub
#5970 (comment)
.

@smarterclayton
Copy link
Contributor

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.

@smarterclayton
Copy link
Contributor

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.

@thockin
Copy link
Member Author

thockin commented Mar 26, 2015

new push is up with (I think) all comments addressed except passing context - @ncdc

PTAL

thockin added 2 commits March 26, 2015 13:48
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.
@thockin
Copy link
Member Author

thockin commented Mar 26, 2015

Shippable is a flake, but travis passed.

@smarterclayton
Copy link
Contributor

LGTM

smarterclayton added a commit that referenced this pull request Mar 26, 2015
Rest hooks for Create and Update
@smarterclayton smarterclayton merged commit f9aa0d5 into kubernetes:master Mar 26, 2015
@thockin thockin deleted the rest_cleanups branch March 27, 2015 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants