-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Consider changing controllerutil#CreateOrUpdate to use equality.Semantic.DeepEqual instead of reflect.DeepEqual #464
Comments
yeah, can you submit a PR to fix this? |
/kind bug |
Is For example, the following always results in
If I dump the server object and the locally generated object, I see the following are always different:
For a simple object such as a |
No, deepequal won't prevent issues from defaulting, IIRC. For that, you need some pretty complex logic. Server-side apply provides that logic, otherwise you have to just be careful how you code things. |
Server side apply is tracked in #347. Knative takes the approach of calling Update and then comparing the result from Get with the result from Update. If it's the same then it implies no real change happened. See Would something like that work? func CreateOrUpdate(ctx context.Context, c client.Client, obj runtime.Object, f MutateFn) (OperationResult, error) {
key, err := client.ObjectKeyFromObject(obj)
if err != nil {
return OperationResultNone, err
}
if err := c.Get(ctx, key, obj); err != nil {
if !errors.IsNotFound(err) {
return OperationResultNone, err
}
if err := mutate(f, key, obj); err != nil {
return OperationResultNone, err
}
if err := c.Create(ctx, obj); err != nil {
return OperationResultNone, err
}
return OperationResultCreated, nil
}
existing := obj.DeepCopyObject()
if err := mutate(f, key, obj); err != nil {
return OperationResultNone, err
}
// CHANGE #1
if equality.Semantic.DeepEqual(existing, obj) {
return OperationResultNone, nil
}
if err := c.Update(ctx, obj); err != nil {
return OperationResultNone, err
} else if equality.Semantic.DeepEqual(existing, obj) { // CHANGE #2
// If what comes back from the update (with defaults applied by the API server) is the same as what we have
// then nothing changed
return OperationResultNone, nil
}
return OperationResultUpdated, nil
} If so, maybe we can add logging with warning level there so the developer would know that he should probably add these specific fields and their server-side default values to its mutated object to avoid unnecessary Update calls. |
Server-side apply works by tracking "ownership" of a field, so if you don't set a field, and you don't own that field, the server won't try to change anything. It's only when you "own" a field that the server will change the value. You take ownership of fields by setting them. All of that is a long-winded way of saying that with server-side apply, you only have to care about the fields that you actually want to set, not about defaults set by the server, or fields set by other compilers.
Yeah, that'd help the result. You'd still have to be more careful than with server-side apply, though, since if you unset something that's defaulted, you can get yourself into a reconcile loop. |
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. |
Stale issues rot after 30d 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 |
/good-first-issue |
@DirectXMan12: Please ensure the request meets the requirements listed here. If this request no longer meets these requirements, the label can be removed 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. |
I tried to use CreateOrUpdate with a NetworkPolicy object and it kept resulting in OperationResultUpdated even though nothing has changed. It seems like using reflect.DeepEqual sometimes gives false positives.
I have created a copy of CreateOrUpdate that uses equality.Semantic.DeepEqual from the apimachinery package (
Semantic can do semantic deep equality checks for api objects
). It seems to resolve the issue for me. Should this be changed upstream?The text was updated successfully, but these errors were encountered: