Merge pull request #592 from pwittrock/patch
Write guide on how to evolve the strategic merge patch format.
This commit is contained in:
commit
3a1e6d22f8
|
@ -3,7 +3,9 @@ Strategic Merge Patch
|
|||
|
||||
# Background
|
||||
|
||||
TODO: @pwittrock complete this section
|
||||
Kubernetes supports a customized version of JSON merge patch called strategic merge patch. This
|
||||
patch format is used by `kubectl apply`, `kubectl edit` and `kubectl patch`, and contains
|
||||
specialized directives to control how specific fields are merged.
|
||||
|
||||
In the standard JSON merge patch, JSON objects are always merged but lists are
|
||||
always replaced. Often that isn't what we want. Let's say we start with the
|
||||
|
@ -209,15 +211,118 @@ In an erroneous case, the set may be created with duplicates. Deleting an
|
|||
item that has duplicates will delete all matching items.
|
||||
|
||||
|
||||
TODO: @pwittrock
|
||||
# Changing Patch Format
|
||||
# Changing patch format
|
||||
|
||||
## Purpose
|
||||
As issues and limitations have been discovered with the strategic merge
|
||||
patch implementation, it has been necessary to change the patch format
|
||||
to support additional semantics - such as merging lists of
|
||||
primitives and defining order when merging lists.
|
||||
|
||||
## Requirement
|
||||
## Requirments for any changes to the patch format
|
||||
|
||||
### Version Skew
|
||||
**Note:** Changes to the strategic merge patch must be backwards compatible such
|
||||
that patch requests valid in previous versions continue to be valid.
|
||||
That is, old patch formats sent by old clients to new servers with
|
||||
must continue to function correctly.
|
||||
|
||||
## Strategy
|
||||
Previously valid patch requests do not need to keep the exact same
|
||||
behavior, but do need to behave correctly.
|
||||
|
||||
**Example:** if a patch request previously randomized the order of elements
|
||||
in a list and we want to provide a deterministic order, we must continue
|
||||
to support old patch format but we can make the ordering deterministic
|
||||
for the old format.
|
||||
|
||||
### Client version skew
|
||||
|
||||
Because the server does not publish which patch versions it supports,
|
||||
and it silently ignores patch directives that it does not recognize,
|
||||
new patches should behave correctly when sent to old servers that
|
||||
may not support all of the patch directives.
|
||||
|
||||
While the patch API must be backwards compatible, it must also
|
||||
be forward compatible for 1 version. This is needed because `kubectl` must
|
||||
support talking to older and newer server versions without knowing what
|
||||
parts of patch are supported on each, and generate patches that work correctly on both.
|
||||
|
||||
## Strategies for introducing new patch behavior
|
||||
|
||||
#### 1. Add optional semantic meaning to the existing patch format.
|
||||
|
||||
**Note:** Must not require new data or elements to be present that was not required before. Meaning must not break old interpretation of old patches.
|
||||
|
||||
**Good Example:**
|
||||
|
||||
Old format
|
||||
- ordering of elements in patch had no meaning and the final ordering was arbitrary
|
||||
|
||||
New format
|
||||
- ordering of elements in patch has meaning and the final ordering is deterministic based on the ordering in the patch
|
||||
|
||||
**Bad Example:**
|
||||
|
||||
Old format
|
||||
- fields not present in a patch for Kind foo are ignored
|
||||
- unmodified fields for Kind foo are optional in patch request
|
||||
|
||||
New format
|
||||
- fields not present in a patch for Kind foo are cleared
|
||||
- unmodified fields for Kind foo are required in patch request
|
||||
|
||||
This example won't work, because old patch formats will contain data that is now
|
||||
considered required. To support this, introduce a new directive to guard the
|
||||
new patch format.
|
||||
|
||||
#### 2. Add support for new directives in the patch format
|
||||
|
||||
- Optional directives may be introduced to change how the patch is applied by the server - **backwards compatible** (old patch against newer server).
|
||||
- May control how the patch is applied
|
||||
- May contain patch information - such as elements to delete from a list
|
||||
- Must NOT impose new requirements on the old patch format
|
||||
|
||||
- New patch requests should be a superset of old patch requests - **forwards compatible** (newer patch against older server)
|
||||
- *Old servers will ignore directives they do not recognize*
|
||||
- Must include the full patch that would have been sent before the new directives were added.
|
||||
- Must NOT rely on the directive being supported by the server
|
||||
|
||||
**Good Example:**
|
||||
|
||||
Old format
|
||||
- fields not present in a patch for Kind foo are ignored
|
||||
- unmodified fields for Kind foo are optional in patch request
|
||||
|
||||
New format *without* directive
|
||||
- Same as old
|
||||
|
||||
New format *with* directive
|
||||
- fields not present in a patch for Kind foo are cleared
|
||||
- unmodified fields for Kind foo are required in patch request
|
||||
|
||||
In this example, the behavior was unchanged when the directive was missing,
|
||||
retaining the old behavior for old patch requests.
|
||||
|
||||
**Bad Example:**
|
||||
|
||||
Old format
|
||||
- fields not present in a patch for Kind foo are ignored
|
||||
- unmodified fields for Kind foo are optional in patch request
|
||||
|
||||
New format *with* directive
|
||||
- Same as old
|
||||
|
||||
New format *without* directive
|
||||
- fields not present in a patch for Kind foo are cleared
|
||||
- unmodified fields for Kind foo are required in patch request
|
||||
|
||||
In this example, the behavior was changed when the directive was missing,
|
||||
breaking compatibility.
|
||||
|
||||
## Alternatives
|
||||
|
||||
The previous strategy is necessary because there is no notion of
|
||||
patch versions. Having the client negotiate the patch version
|
||||
with the server would allow changing the patch format, but at
|
||||
the cost of supporting multiple patch formats in the server and client.
|
||||
Using client provided directives to evolve how a patch is merged
|
||||
provides some limited support for multiple versions.
|
||||
|
||||
## Example
|
||||
|
|
Loading…
Reference in New Issue