mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-06 19:52:42 +00:00
Implement Strategic Merge Patch in apiserver
This commit is contained in:
@@ -146,6 +146,7 @@ API resources should use the traditional REST pattern:
|
||||
* GET /<resourceNamePlural>/<name> - Retrieves a single resource with the given name, e.g. GET /pods/first returns a Pod named 'first'.
|
||||
* DELETE /<resourceNamePlural>/<name> - Delete the single resource with the given name.
|
||||
* PUT /<resourceNamePlural>/<name> - Update or create the resource with the given name with the JSON object provided by the client.
|
||||
* PATCH /<resourceNamePlural>/<name> - Selectively modify the specified fields of the resource. See more information [below](#patch).
|
||||
|
||||
Kubernetes by convention exposes additional verbs as new root endpoints with singular names. Examples:
|
||||
|
||||
@@ -160,6 +161,87 @@ When resources wish to expose alternative actions that are closely coupled to a
|
||||
|
||||
TODO: more documentation of Watch
|
||||
|
||||
### PATCH operations
|
||||
|
||||
The API supports three different PATCH operations, determined by their corresponding Content-Type header:
|
||||
|
||||
* JSON Patch, `Content-Type: application/json-patch+json`
|
||||
* As defined in [RFC6902](https://tools.ietf.org/html/rfc6902), a JSON Patch is a sequence of operations that are executed on the resource, e.g. `{"op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ]}`. For more details on how to use JSON Patch, see the RFC.
|
||||
* Merge Patch, `Content-Type: application/merge-json-patch+json`
|
||||
* As defined in [RFC7386](https://tools.ietf.org/html/rfc7386), a Merge Patch is essentially a partial representation of the resource. The submitted JSON is "merged" with the current resource to create a new one, then the new one is saved. For more details on how to use Merge Patch, see the RFC.
|
||||
* Strategic Merge Patch, `Content-Type: application/strategic-merge-json-patch+json`
|
||||
* Strategic Merge Patch is a custom implementation of Merge Patch. For a detailed explanation of how it works and why it needed to be introduced, see below.
|
||||
|
||||
#### Strategic Merge Patch
|
||||
|
||||
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 following Pod:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx-1.0
|
||||
```
|
||||
|
||||
...and we POST that to the server (as JSON). Then let's say we want to *add* a container to this Pod.
|
||||
|
||||
```yaml
|
||||
PATCH /v1beta1/pod
|
||||
spec:
|
||||
containers:
|
||||
- name: log-tailer
|
||||
image: log-tailer-1.0
|
||||
```
|
||||
|
||||
If we were to use standard Merge Patch, the entire container list would be replaced with the single log-tailer container. However, our intent is for the container lists to merge together based on the `name` field.
|
||||
|
||||
To solve this problem, Strategic Merge Patch uses metadata attached to the API objects to determine what lists should be merged and which ones should not. Currently the metadata is available as struct tags on the API objects themselves, but will become available to clients as Swagger annotations in the future. In the above example, the `patchStrategy` metadata for the `containers` field would be `merge` and the `patchMergeKey` would be `name`.
|
||||
|
||||
Note: If the patch results in merging two lists of scalars, the scalars are first deduplicated and then merged.
|
||||
|
||||
Strategic Merge Patch also supports special operations as listed below.
|
||||
|
||||
### List Operations
|
||||
|
||||
To override the container list to be strictly replaced, regardless of the default:
|
||||
|
||||
```yaml
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx-1.0
|
||||
- $patch: replace # any further $patch operations nested in this list will be ignored
|
||||
```
|
||||
|
||||
To delete an element of a list that should be merged:
|
||||
|
||||
```yaml
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx-1.0
|
||||
- $patch: delete
|
||||
name: log-tailer # merge key and value goes here
|
||||
```
|
||||
|
||||
### Map Operations
|
||||
|
||||
To indicate that a map should not be merged and instead should be taken literally:
|
||||
|
||||
```yaml
|
||||
$patch: replace # recursive and applies to all fields of the map it's in
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx-1.0
|
||||
```
|
||||
|
||||
To delete a field of a map:
|
||||
|
||||
```yaml
|
||||
name: nginx
|
||||
image: nginx-1.0
|
||||
labels:
|
||||
live: null # set the value of the map key to null
|
||||
```
|
||||
|
||||
|
||||
Idempotency
|
||||
-----------
|
||||
|
Reference in New Issue
Block a user