* 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.
* 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 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
Args[]string`json:"args,omitempty" description:"command array; the docker image's cmd is used if this is not provided; arguments to the entrypoint; cannot be updated"`
Args[]string`json:"args,omitempty" description:"command array; the docker image's cmd is used if this is not provided; arguments to the entrypoint; cannot be updated"`
// Optional: Defaults to Docker's default.
// Optional: Defaults to Docker's default.
WorkingDirstring`json:"workingDir,omitempty" description:"container's working directory; defaults to image's default; cannot be updated"`
WorkingDirstring`json:"workingDir,omitempty" description:"container's working directory; defaults to image's default; cannot be updated"`
Ports[]ContainerPort`json:"ports,omitempty" description:"list of ports to expose from the container; cannot be updated"`
Ports[]ContainerPort`json:"ports,omitempty" description:"list of ports to expose from the container; cannot be updated" patchStrategy:"merge" patchMergeKey:"containerPort"`
Env[]EnvVar`json:"env,omitempty" description:"list of environment variables to set in the container; cannot be updated"`
Env[]EnvVar`json:"env,omitempty" description:"list of environment variables to set in the container; cannot be updated" patchStrategy:"merge" patchMergeKey:"name"`
ResourcesResourceRequirements`json:"resources,omitempty" description:"Compute Resources required by this container; cannot be updated"`
ResourcesResourceRequirements`json:"resources,omitempty" description:"Compute Resources required by this container; cannot be updated"`
VolumeMounts[]VolumeMount`json:"volumeMounts,omitempty" description:"pod volumes to mount into the container's filesyste; cannot be updated"`
VolumeMounts[]VolumeMount`json:"volumeMounts,omitempty" description:"pod volumes to mount into the container's filesyste; cannot be updated" patchStrategy:"merge" patchMergeKey:"name"`
LivenessProbe*Probe`json:"livenessProbe,omitempty" description:"periodic probe of container liveness; container will be restarted if the probe fails; cannot be updated"`
LivenessProbe*Probe`json:"livenessProbe,omitempty" description:"periodic probe of container liveness; container will be restarted if the probe fails; cannot be updated"`
ReadinessProbe*Probe`json:"readinessProbe,omitempty" description:"periodic probe of container service readiness; container will be removed from service endpoints if the probe fails; cannot be updated"`
ReadinessProbe*Probe`json:"readinessProbe,omitempty" description:"periodic probe of container service readiness; container will be removed from service endpoints if the probe fails; cannot be updated"`
Lifecycle*Lifecycle`json:"lifecycle,omitempty" description:"actions that the management system should take in response to container lifecycle events; cannot be updated"`
Lifecycle*Lifecycle`json:"lifecycle,omitempty" description:"actions that the management system should take in response to container lifecycle events; cannot be updated"`
...
@@ -695,9 +695,9 @@ const (
...
@@ -695,9 +695,9 @@ const (
// PodSpec is a description of a pod
// PodSpec is a description of a pod
typePodSpecstruct{
typePodSpecstruct{
Volumes[]Volume`json:"volumes" description:"list of volumes that can be mounted by containers belonging to the pod"`
Volumes[]Volume`json:"volumes" description:"list of volumes that can be mounted by containers belonging to the pod" patchStrategy:"merge" patchMergeKey:"name"`
// Required: there must be at least one container in a pod.
// Required: there must be at least one container in a pod.
Containers[]Container`json:"containers" description:"list of containers belonging to the pod; cannot be updated; containers cannot currently be added or removed; there must be at least one container in a Pod"`
Containers[]Container`json:"containers" description:"list of containers belonging to the pod; cannot be updated; containers cannot currently be added or removed; there must be at least one container in a Pod" patchStrategy:"merge" patchMergeKey:"name"`
RestartPolicyRestartPolicy`json:"restartPolicy,omitempty" description:"restart policy for all containers within the pod; one of RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyNever"`
RestartPolicyRestartPolicy`json:"restartPolicy,omitempty" description:"restart policy for all containers within the pod; one of RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyNever"`
// Optional: Set DNS policy. Defaults to "ClusterFirst"
// Optional: Set DNS policy. Defaults to "ClusterFirst"
DNSPolicyDNSPolicy`json:"dnsPolicy,omitempty" description:"DNS policy for containers within the pod; one of 'ClusterFirst' or 'Default'"`
DNSPolicyDNSPolicy`json:"dnsPolicy,omitempty" description:"DNS policy for containers within the pod; one of 'ClusterFirst' or 'Default'"`
...
@@ -718,7 +718,7 @@ type PodSpec struct {
...
@@ -718,7 +718,7 @@ type PodSpec struct {
// state of a system.
// state of a system.
typePodStatusstruct{
typePodStatusstruct{
PhasePodPhase`json:"phase,omitempty" description:"current condition of the pod."`
PhasePodPhase`json:"phase,omitempty" description:"current condition of the pod."`
Conditions[]PodCondition`json:"Condition,omitempty" description:"current service state of pod"`
Conditions[]PodCondition`json:"Condition,omitempty" description:"current service state of pod" patchStrategy:"merge" patchMergeKey:"type"`
// A human readable message indicating details about why the pod is in this state.
// A human readable message indicating details about why the pod is in this state.
Messagestring`json:"message,omitempty" description:"human readable message indicating details about why the pod is in this condition"`
Messagestring`json:"message,omitempty" description:"human readable message indicating details about why the pod is in this condition"`
...
@@ -1029,9 +1029,9 @@ type NodeStatus struct {
...
@@ -1029,9 +1029,9 @@ type NodeStatus struct {
// NodePhase is the current lifecycle phase of the node.
// NodePhase is the current lifecycle phase of the node.
PhaseNodePhase`json:"phase,omitempty" description:"most recently observed lifecycle phase of the node"`
PhaseNodePhase`json:"phase,omitempty" description:"most recently observed lifecycle phase of the node"`
// Conditions is an array of current node conditions.
// Conditions is an array of current node conditions.
Conditions[]NodeCondition`json:"conditions,omitempty" description:"list of node conditions observed"`
Conditions[]NodeCondition`json:"conditions,omitempty" description:"list of node conditions observed" patchStrategy:"merge" patchMergeKey:"type"`
// Queried from cloud provider, if available.
// Queried from cloud provider, if available.
Addresses[]NodeAddress`json:"addresses,omitempty" description:"list of addresses reachable to the node"`
Addresses[]NodeAddress`json:"addresses,omitempty" description:"list of addresses reachable to the node" patchStrategy:"merge" patchMergeKey:"type"`
// NodeSystemInfo is a set of ids/uuids to uniquely identify the node
// NodeSystemInfo is a set of ids/uuids to uniquely identify the node