-
Notifications
You must be signed in to change notification settings - Fork 180
simplify patching spec and status in reconciler #39
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
simplify patching spec and status in reconciler #39
Conversation
The way that we were handling patching spec/metadata and status in the main reconciler loop was starting to get awkward and messy. We were calling `patchResource`, `patchResourceStatus` or `patchResourceMetadataAndSpec` in quite a few places, the main `resourceReconciler.Sync()` code path was getting messy and hard to read, and we were in danger of having more subtle bugs creep into the reconciler logic because of the duplicative patch calls and non-obvious nature of the calls. This patch simplifies and cleans up the logic around the core `resourceReconciler.Sync()` code paths in the following ways: * Breaks out the create and update code paths into their own separate `createResource` and `updateResource` methods. * Renames the `cleanup` method to `deleteResource` in order to match the create and update methods * Removes ALL calls to `patchResourceStatus` in favor of always ensuring Status patching is done in the `resourceReconciler.HandleReconcileError` wrapper method * Removes the `resourceReconciler.patchResource` method entirely (which patched both Metadata/Spec as well as Status) and ensures that the `createResource`, `updateResource` and `deleteResource` methods on `resourceReconciler` only ever call `patchResourceMetadataAndSpec` (since `patchResourceStatus` is now always called by the `HandleReconcileError` wrapper) These changes should make the late initialize work easier to fit into the core reconciler logic and provide a more explicit contract about what is responsible for patching status (**only** the `HandleReconcileError` wrapper) and what is responsible for patching metadata and spec (the `createResource`, `updateResource` and `deleteResource` methods).
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.
Excellent Refactoring 🙌
| // No changes to metadata or spec so Patch on the object shouldn't be done | ||
| kc.AssertNotCalled(t, "Patch", ctx, latestRTObj, client.MergeFrom(desiredRTObj)) | ||
| statusWriter.AssertCalled(t, "Patch", ctx, latestRTObj, client.MergeFrom(desiredRTObj)) | ||
| // Only the HandleReconcilerError wrapper function ever calls patchResourceStatus |
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.
nit: should the test be renamed to TestSync_Update() , which is correct representation of the test.
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.
Nice! LGTM
| // NOTE(jaypipes): This is really only here for dependency injection | ||
| // purposes in unit testing in order to simplify test setups. |
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.
👍
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: A-Hilaly, jaypipes, vijtrip2 The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
The way that we were handling patching spec/metadata and status in the main reconciler loop was starting to get awkward and messy. We were calling `patchResource`, `patchResourceStatus` or `patchResourceMetadataAndSpec` in quite a few places, the main `resourceReconciler.Sync()` code path was getting messy and hard to read, and we were in danger of having more subtle bugs creep into the reconciler logic because of the duplicative patch calls and non-obvious nature of the calls. This patch simplifies and cleans up the logic around the core `resourceReconciler.Sync()` code paths in the following ways: * Breaks out the create and update code paths into their own separate `createResource` and `updateResource` methods. * Renames the `cleanup` method to `deleteResource` in order to match the create and update methods * Removes ALL calls to `patchResourceStatus` in favor of always ensuring Status patching is done in the `resourceReconciler.HandleReconcileError` wrapper method * Removes the `resourceReconciler.patchResource` method entirely (which patched both Metadata/Spec as well as Status) and ensures that the `createResource`, `updateResource` and `deleteResource` methods on `resourceReconciler` only ever call `patchResourceMetadataAndSpec` (since `patchResourceStatus` is now always called by the `HandleReconcileError` wrapper) These changes should make the late initialize work easier to fit into the core reconciler logic and provide a more explicit contract about what is responsible for patching status (**only** the `HandleReconcileError` wrapper) and what is responsible for patching metadata and spec (the `createResource`, `updateResource` and `deleteResource` methods). By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Fixes: aws-controllers-k8s/community#886 The reconciler will indefinitely requeue even when there have been no changes made to the `spec` or `status`. This is happening in both the adoption and resource reconciler types. The root cause comes from `controller-runtime` requeue-ing the resource when we patch the `status` subresource - see [this issue](kubernetes-sigs/kubebuilder#618) for details. This bug was introduced for the resource reconciler as part of #39 , since we now call `patchResourceStatus` on every reconcile loop. This fix adds an event filter to each manager, with a predicate that the resource must have changed generation. The generation is not changed unless there has been a modification to the `spec`.
The way that we were handling patching spec/metadata and status in the
main reconciler loop was starting to get awkward and messy. We were
calling
patchResource,patchResourceStatusorpatchResourceMetadataAndSpecin quite a few places, the mainresourceReconciler.Sync()code path was getting messy and hard toread, and we were in danger of having more subtle bugs creep into the
reconciler logic because of the duplicative patch calls and non-obvious
nature of the calls.
This patch simplifies and cleans up the logic around the core
resourceReconciler.Sync()code paths in the following ways:createResourceandupdateResourcemethods.cleanupmethod todeleteResourcein order to match thecreate and update methods
patchResourceStatusin favor of always ensuringStatus patching is done in the
resourceReconciler.HandleReconcileErrorwrapper methodresourceReconciler.patchResourcemethod entirely (whichpatched both Metadata/Spec as well as Status) and ensures that the
createResource,updateResourceanddeleteResourcemethods onresourceReconcileronly ever callpatchResourceMetadataAndSpec(since
patchResourceStatusis now always called by theHandleReconcileErrorwrapper)These changes should make the late initialize work easier to fit into
the core reconciler logic and provide a more explicit contract about
what is responsible for patching status (only the
HandleReconcileErrorwrapper) and what is responsible for patchingmetadata and spec (the
createResource,updateResourceanddeleteResourcemethods).By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.