You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The basic patching method is patch(PatchContext patchContext, String patch). There could also be a similar patchStatus, or another parameter indicating the subresource - but for now we’ve opted for more specific calls.
The other methods dealing with how the patch is formed can get a little confusing...
resource(item).patch(), patch(item), resource(item).patch(PatchContext.of(PatchType.JSON)), or patch(PatchContext.of(PatchType.JSON), item) - all produce a JSON patch of the item against the latest version on the api server. This was confusing for me at first - it was't clear you were always diffing to the latest version on the api server. If the resource changes in between when you modified it and when you call patch you'll overwrite those changes as the diff will process them as removals. So these are extremely similar to a replace, but as a patch. The advantage of using this patch over replace is that it doesn’t consider the resourceVersion and won’t have the same side effects as a PUT (which newer versions of kubernetes are starting to address).
accept(function) is the same as edit(item -> {function.accept(item); return item;}), and edit(class, visitor) is functionally similar - they will produce a JSON patch based upon a diff of the current item with whatever is evaluated. A withName(name).edit is equivalent to a patch call as the current item must be fetched from the server. With 5.x you can use a load(something).edit or in 6.0 you'll be able to use resource(item).edit to control what the base item is. With 6.0 if you have both the original and modified item you can do resource(original).edit(ignored -> modified) to produce a clean JSON patch of only what you intend to change.
A downside of JSON patches in general is that they aren't tolerant to concurrent removals. If you for example try to patch a configmap twice in a row with [{"op":"remove","path":"/data/key"}] it will fail on the second call. Add / modify don’t have the same problem - the patch will still succeed whether there are any changes.
patchStatus() or patchStatus(item) are similar to the patch calls, but produce a JSON Merge (more on that below) patch instead. Patching a status with a Strategic Merge is disallowed by the api server, and you can produce a JSON patch of the status using editStatus - so it seemed redundant to default to JSON like other patch methods.
There is no support in the client for creating a JSON Merge or Strategic Merge patch via diffing resources - that is supported in kubectl when performing an edit). If we are given an item when one of those patches is expected, the patch is simply the serialized form of that item. That is great for specifying additive partial modifications (like toggling a spec flag), but is useless for removals - which was noted when the feature was developed, but does not appear in the javadocs. This applies to patchStatus and patch(PatchContext.of(PatchType.JSON_MERGE | PatchType.STRATEGIC_MERGE [, item]). And unlike JSON patches JSON_MERGE and STRATEGIC_MERGE are sensitive to the resourceVersion - if it’s set in the patch, then optimistic locking will be used.
Finally there is now also support for PatchType.SERVER_SIDE_APPLY. This is used with patch(PatchContext.of(PatchType.SERVER_SIDE_APPLY), or patch(PatchContext.of(PatchType.SERVER_SIDE_APPLY), item) - similar to the merge patch support, this will simply serialize the entire item as the patch - there’s never a need for a diff.
I’m certainly open to rationalizing the above further. It's not great that the default patch type is and whether we're performing a diff take so much knowledge.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
@metacosm @manusa @rohanKanojia @csviri with #4142 it's probably a good time to review where the patch methods are at.
The basic patching method is patch(PatchContext patchContext, String patch). There could also be a similar patchStatus, or another parameter indicating the subresource - but for now we’ve opted for more specific calls.
The other methods dealing with how the patch is formed can get a little confusing...
resource(item).patch(), patch(item), resource(item).patch(PatchContext.of(PatchType.JSON)), or patch(PatchContext.of(PatchType.JSON), item) - all produce a JSON patch of the item against the latest version on the api server. This was confusing for me at first - it was't clear you were always diffing to the latest version on the api server. If the resource changes in between when you modified it and when you call patch you'll overwrite those changes as the diff will process them as removals. So these are extremely similar to a replace, but as a patch. The advantage of using this patch over replace is that it doesn’t consider the resourceVersion and won’t have the same side effects as a PUT (which newer versions of kubernetes are starting to address).
accept(function) is the same as edit(item -> {function.accept(item); return item;}), and edit(class, visitor) is functionally similar - they will produce a JSON patch based upon a diff of the current item with whatever is evaluated. A withName(name).edit is equivalent to a patch call as the current item must be fetched from the server. With 5.x you can use a load(something).edit or in 6.0 you'll be able to use resource(item).edit to control what the base item is. With 6.0 if you have both the original and modified item you can do resource(original).edit(ignored -> modified) to produce a clean JSON patch of only what you intend to change.
A downside of JSON patches in general is that they aren't tolerant to concurrent removals. If you for example try to patch a configmap twice in a row with [{"op":"remove","path":"/data/key"}] it will fail on the second call. Add / modify don’t have the same problem - the patch will still succeed whether there are any changes.
patchStatus() or patchStatus(item) are similar to the patch calls, but produce a JSON Merge (more on that below) patch instead. Patching a status with a Strategic Merge is disallowed by the api server, and you can produce a JSON patch of the status using editStatus - so it seemed redundant to default to JSON like other patch methods.
There is no support in the client for creating a JSON Merge or Strategic Merge patch via diffing resources - that is supported in kubectl when performing an edit). If we are given an item when one of those patches is expected, the patch is simply the serialized form of that item. That is great for specifying additive partial modifications (like toggling a spec flag), but is useless for removals - which was noted when the feature was developed, but does not appear in the javadocs. This applies to patchStatus and patch(PatchContext.of(PatchType.JSON_MERGE | PatchType.STRATEGIC_MERGE [, item]). And unlike JSON patches JSON_MERGE and STRATEGIC_MERGE are sensitive to the resourceVersion - if it’s set in the patch, then optimistic locking will be used.
Finally there is now also support for PatchType.SERVER_SIDE_APPLY. This is used with patch(PatchContext.of(PatchType.SERVER_SIDE_APPLY), or patch(PatchContext.of(PatchType.SERVER_SIDE_APPLY), item) - similar to the merge patch support, this will simply serialize the entire item as the patch - there’s never a need for a diff.
I’m certainly open to rationalizing the above further. It's not great that the default patch type is and whether we're performing a diff take so much knowledge.
Beta Was this translation helpful? Give feedback.
All reactions