@@ -94,3 +94,129 @@ $ kpt pkg update my-package-dir/@master --strategy fast-forward
94
94
```
95
95
96
96
<!-- 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