Skip to content

Commit e090fd3

Browse files
authored
Add details about the merge strategies to the Kpt book (#2145)
* Add details about the merge strategies to the Kpt book * Addressed comments * Addressed more comments * Addressed comments * Moved content to reference docs
1 parent cb24362 commit e090fd3

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

site/reference/cli/pkg/update/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,129 @@ $ kpt pkg update my-package-dir/@master --strategy fast-forward
9494
```
9595

9696
<!--mdtogo-->
97+
98+
### Details
99+
100+
#### Resource-merge strategy
101+
102+
The resource-merge strategy performs a structural comparison of each resource using the
103+
OpenAPI schema. So rather than performing a text-based merge, kpt leverages the
104+
common structure of KRM resources.
105+
106+
##### Resource identity
107+
In order to perform a per-resource merge, kpt needs to be able to match a resource in
108+
the local package with the same resource in the upstream version of the package. It does
109+
this matching based on the identity of a resource, which is the combination of group,
110+
kind, name and namespace. So in our wordpress example, the identity of the`Deployment`
111+
resource is:
112+
```
113+
group: apps
114+
kind: Deployment
115+
name: wordpress
116+
namespace: ""
117+
```
118+
Changing the name and/or namespace of a resource is a pretty common way to customize
119+
a package. In order to make sure this doesn't create problems during merge, kpt will
120+
automatically adding the `# kpt-merge: <namespace>/<name>` comment on the `metadata`
121+
field of every resource when getting or updating a package. An example is the `Deployment`
122+
resource from the wordpress package:
123+
```yaml
124+
apiVersion: apps/v1
125+
kind: Deployment
126+
metadata: # kpt-merge: /wordpress
127+
name: wordpress
128+
labels:
129+
app: wordpress
130+
...
131+
```
132+
133+
##### Merge rules
134+
kpt performs a 3-way merge for every resource. This means it will use the resource
135+
in the local package, the updated resource from upstream, as well as the resource
136+
at the version where the local and upstream package diverged (i.e.
137+
common ancestor). When discussing the merge rules in detail, we will be referring to
138+
the three different sources as local, upstream and origin.
139+
140+
In the discussion, we will be referring to non-associative and associative lists. A
141+
non-associative list either has elements that are scalars or another list, or it has elements
142+
that are mappings but without an associative key. An example of this in the kubernetes
143+
API is the `command` property on containers:
144+
```yaml
145+
apiVersion: v1
146+
kind: Pod
147+
metadata:
148+
name: pod
149+
spec:
150+
containers:
151+
- name: hello
152+
image: busybox
153+
command: ['sh', '-c', 'echo "Hello, World!"]
154+
```
155+
156+
An associative list has elements that are mappings and
157+
one or more of the fields in the mappings are designated as associative keys. An associative key
158+
(also sometimes referred to as a merge key) is used to identify the "same" elements in two
159+
different lists for the purpose of merging them. An example from the kubernetes API
160+
is the list of containers in a pod which uses the `name` property as the merge key:
161+
```yaml
162+
apiVersion: v1
163+
kind: Pod
164+
metadata:
165+
name: pod
166+
spec:
167+
containers:
168+
- name: web
169+
image: nginx
170+
- name: sidecar
171+
image: log-collector
172+
```
173+
174+
kpt will primarily look for information about
175+
any associative keys from the OpenAPI schema, but some fields are also automatically recognized as
176+
associative keys:
177+
* `mountPath`
178+
* `devicePath`
179+
* `ip`
180+
* `type`
181+
* `topologyKey`
182+
* `name`
183+
* `containerPort`
184+
185+
The 3-way merge algorithm operates both on the level of each resource and on
186+
each individual field with a resource.
187+
188+
On the resource level, the rules are:
189+
190+
* A resource present in origin and deleted from upstream will be deleted from local.
191+
* A resource missing from origin and added in upstream will be added to local.
192+
* A resource only in local will be kept without changes.
193+
* A resource in both upstream and local will be merged into local.
194+
195+
On the field level, the rules differ based on the type of field.
196+
197+
For scalars and non-associative lists:
198+
* If the field is present in either upstream or local and the value is `null`, remove the field from local.
199+
* If the field is unchanged between upstream and local, leave the local value unchanged.
200+
* If the field has been changed in both upstream and local, update local with the value from upstream.
201+
202+
For mappings:
203+
* If the field is present in either upstream or local and the value is `null`, remove the field from local.
204+
* If the field is present only in local, leave the local value unchanged.
205+
* If the field is not present in local, add the delta between origin and upstream as the value in local.
206+
* If the field is present in both upstream and local, recursively merge the values between local, upstream and origin.
207+
208+
For associative lists:
209+
* If the field is present in either upstream or local and the value is `null`, remove the field from local.
210+
* If the field is present only in local, leave the local value unchanged.
211+
* If the field is not present in local, add the delta between origin and upstream as the value in local.
212+
* If the field is present in both upstream and local, recursively merge the values between local, upstream and origin.
213+
214+
#### Fast-forward strategy
215+
216+
The fast-forward strategy updates a local package with the changes from upstream, but will
217+
fail if the local package has been modified since it was fetched.
218+
219+
#### Force-delete-replace strategy
220+
221+
The force-delete-replace strategy updates a local package with changes from upstream, but will
222+
wipe out any modifications to the local package.

0 commit comments

Comments
 (0)