-
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
Relax update validation of uninitialized pod #51733
Relax update validation of uninitialized pod #51733
Conversation
/release-note-none |
5494a31
to
408892f
Compare
pkg/registry/core/pod/strategy.go
Outdated
@@ -92,6 +94,14 @@ func (podStrategy) AllowCreateOnUpdate() bool { | |||
// ValidateUpdate is the default update validation for an end user. | |||
func (podStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { | |||
errorList := validation.ValidatePod(obj.(*api.Pod)) | |||
oldMeta, err := meta.Accessor(old) |
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.
wrap all of this with a check of the initializers feature gate
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.
or actually, maybe just a helper func:
initialized, err := IsInitializedObject(old)
switch {
case err != nil:
return append(errorList, field.InternalError(field.NewPath("metadata"), err))
case !initialized:
return errorList
default:
return append(errorList, validation.ValidatePodUpdate(obj.(*api.Pod), old.(*api.Pod))...)
}
test/e2e/resource_quota.go
Outdated
@@ -148,71 +149,71 @@ var _ = framework.KubeDescribe("ResourceQuota", func() { | |||
}) | |||
|
|||
It("should create a ResourceQuota and capture the life of an uninitialized pod.", func() { |
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.
depends on initializer feature, right?
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.
marked as [Feature: Initializers]
@@ -92,6 +94,14 @@ func (podStrategy) AllowCreateOnUpdate() bool { | |||
// ValidateUpdate is the default update validation for an end user. | |||
func (podStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { | |||
errorList := validation.ValidatePod(obj.(*api.Pod)) |
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.
Why shouldn't a pod be allowed to be invalid during the process of initialization? It is possible to do with admission today and given a "my special defaulter that can take an invalid user object and choose a good/valid default" initializer, seems even more useful after.
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 is possible to do with admission today
not in a persisted, visible state that someone getting an object from the API has to deal with, or that migration has to take into account. bad data in etcd is not something I'm excited about.
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.
not in a persisted, visible state that someone getting an object from the API has to deal with, or that migration has to take into account. bad data in etcd is not something I'm excited about.
It's uninitialized data. Not allowing someone to initialize that data to a shape of their choosing seems excessively restrictive. I know that I would respond to an API not letting me do it by pushing garbage into fields that fail validation and using magic values.
Our API already has problems dealing with new fields and I don't see forcing this limitation as helping.
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.
if we want to further relax this in the future, I think we can, if there are compelling use cases that outweigh the downsides of persisting bad data.
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.
if we want to further relax this in the future, I think we can, if there are compelling use cases that outweigh the downsides of persisting bad data.
I suppose its true that we can't go the other way around. If we do it, I reserve the right to say "I told you so" twice. :)
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.
seems even more useful after.
It might be useful. However, user can GET uninitialized objects. I think it's more important to never persist invalid objects.
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.
fc34efe
to
7eebea4
Compare
// ValidateUpdate is the default update validation for an end user. | ||
func (podStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList { | ||
errorList := validation.ValidatePod(obj.(*api.Pod)) | ||
uninitializedUpdate, err := isUpdatingUninitializedPod(old) |
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.
@liggitt I just saw the code you posted. Do you have a strong preference using the switch
statement?
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 find it easier to read, but don't feel strongly
@@ -89,9 +93,31 @@ func (podStrategy) AllowCreateOnUpdate() bool { | |||
return false | |||
} | |||
|
|||
func isUpdatingUninitializedPod(old runtime.Object) (bool, error) { | |||
if !utilfeature.DefaultFeatureGate.Enabled(features.Initializers) { |
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.
The generic registry will delete the initiailizers if the feature gate is disabled, so the check here is just to be future-proof.
test/e2e/resource_quota.go
Outdated
|
||
// TODO: uncomment the test when the replenishment_controller uses the | ||
// sharedInformer that list/watches uninitialized objects. | ||
It("[Feature: Initializers] should create a ResourceQuota and capture the life of an uninitialized pod.", func() { |
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.
[Feature:Initializers]
7eebea4
to
b0cbaa5
Compare
@derekwaynecarr is there an issue tracking the quota admission updates that need to be done? |
@liggitt @derekwaynecarr my sharedInformer PR (#51247) isn't going to get merged before the deadline, so the quota replenishment controller won't capture the deletion of uninitialized objects. I will send a follow-up PR to let the quota admission only charge the quota when the object is initialized. |
/lgtm |
Release notes added. @deads2k could you approve? Thanks. |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: caesarxuchao, deads2k, liggitt Associated issue: 47837 The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
added an item to do this generically and remove the pod special case in #49038 |
Added the item to the umbrella issue. |
/retest Review the full test history for this PR. |
9 similar comments
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest Review the full test history for this PR. |
/retest |
/retest Review the full test history for this PR. |
add UninitializedStatusUpdateErrorMsg
b0cbaa5
to
dac486a
Compare
The unit test was broken because I tightened up the rule for initializer name in another PR. Fixed the test and reapplying the label. |
/retest |
1 similar comment
/retest |
still seeing the test error:
|
dac486a
to
3432e38
Compare
Thanks. Somehow lost part of the changes during squash. |
/test all [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue (batch tested with PRs 51733, 51838) |
Split from #50344
Fix #47837
validation.ValidatePod()
if the old pod is not initialized, so fields are mutable.cc @smarterclayton