Skip to content

Commit a59ce03

Browse files
committed
fix: clean metadata fields to avoid resourceVersion patch errors
Add cleanMetadataForPatch function to remove server-managed metadata fields (resourceVersion, generation, uid, etc.) before creating merge patches. This prevents 'resourceVersion: Invalid value: 0' errors when dry-running patches against CRs/CRDs. Signed-off-by: yxxhero <aiopsclub@163.com>
1 parent efb7e0a commit a59ce03

1 file changed

Lines changed: 39 additions & 4 deletions

File tree

manifest/generate.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,23 @@ func createPatch(originalObj, currentObj runtime.Object, target *resource.Info)
181181
// 5. If chart unchanged (old == new) but current != new, return current->new patch applied to current to restore chart state
182182
// (i.e., detect and revert manual changes by restoring chart-owned fields to the chart's desired state)
183183

184+
// Clean metadata fields that shouldn't be compared (they're server-managed)
185+
// This prevents "resourceVersion: Invalid value: 0" errors when dry-running patches
186+
cleanedOldData, err := cleanMetadataForPatch(oldData)
187+
if err != nil {
188+
return nil, types.MergePatchType, fmt.Errorf("cleaning old metadata: %w", err)
189+
}
190+
cleanedNewData, err := cleanMetadataForPatch(newData)
191+
if err != nil {
192+
return nil, types.MergePatchType, fmt.Errorf("cleaning new metadata: %w", err)
193+
}
194+
cleanedCurrentData, err := cleanMetadataForPatch(currentData)
195+
if err != nil {
196+
return nil, types.MergePatchType, fmt.Errorf("cleaning current metadata: %w", err)
197+
}
198+
184199
// Step 1: Create patch from old -> new (what the chart wants to change)
185-
chartChanges, err := jsonpatch.CreateMergePatch(oldData, newData)
200+
chartChanges, err := jsonpatch.CreateMergePatch(cleanedOldData, cleanedNewData)
186201
if err != nil {
187202
return nil, types.MergePatchType, fmt.Errorf("creating chart changes patch: %w", err)
188203
}
@@ -192,22 +207,22 @@ func createPatch(originalObj, currentObj runtime.Object, target *resource.Info)
192207

193208
if chartChanged {
194209
// Step 2: Apply chart changes to current (merge chart changes with live state)
195-
mergedData, err := jsonpatch.MergePatch(currentData, chartChanges)
210+
mergedData, err := jsonpatch.MergePatch(cleanedCurrentData, chartChanges)
196211
if err != nil {
197212
return nil, types.MergePatchType, fmt.Errorf("applying chart changes to current: %w", err)
198213
}
199214

200215
// Step 3: Create patch from current -> merged (what to apply to current)
201216
// This patch, when applied to current, will produce the merged result
202-
patch, err := jsonpatch.CreateMergePatch(currentData, mergedData)
217+
patch, err := jsonpatch.CreateMergePatch(cleanedCurrentData, mergedData)
203218
return patch, types.MergePatchType, err
204219
}
205220

206221
// Chart didn't change (old == new), but we need to detect if current diverges
207222
// from the chart state. This is the case where manual changes were made to
208223
// chart-owned fields.
209224
// Create a patch from current -> new to detect and restore drift
210-
patch, err := jsonpatch.CreateMergePatch(currentData, newData)
225+
patch, err := jsonpatch.CreateMergePatch(cleanedCurrentData, cleanedNewData)
211226
return patch, types.MergePatchType, err
212227
}
213228

@@ -224,6 +239,26 @@ func isPatchEmpty(patch []byte) bool {
224239
return len(patch) == 0 || string(patch) == "{}" || string(patch) == "null"
225240
}
226241

242+
func cleanMetadataForPatch(data []byte) ([]byte, error) {
243+
var objMap map[string]interface{}
244+
if err := json.Unmarshal(data, &objMap); err != nil {
245+
return nil, err
246+
}
247+
248+
if metadata, ok := objMap["metadata"].(map[string]interface{}); ok {
249+
delete(metadata, "resourceVersion")
250+
delete(metadata, "generation")
251+
delete(metadata, "creationTimestamp")
252+
delete(metadata, "uid")
253+
delete(metadata, "managedFields")
254+
delete(metadata, "selfLink")
255+
}
256+
257+
delete(objMap, "status")
258+
259+
return json.Marshal(objMap)
260+
}
261+
227262
func objectKey(r *resource.Info) string {
228263
gvk := r.Object.GetObjectKind().GroupVersionKind()
229264
return fmt.Sprintf("%s/%s/%s/%s", gvk.GroupVersion().String(), gvk.Kind, r.Namespace, r.Name)

0 commit comments

Comments
 (0)