headlamp
headlamp copied to clipboard
Resolve conflicts before edit resources
Headlamp edits resources by put method. It will replace the original object without conflict merge. Finally, it might fail to deploy because the conflict. Ideally, we want headlamp resolve conflicts before send put request.
- https://datatracker.ietf.org/doc/html/rfc7396
// getMergedPatchData genereates a 3-way merge patch based on JSON-merge patch.
// The main purpose is to implement a declarative behavior like kubectl apply.
func getMergedPatchData(currentObj, modifiedObj runtime.Object) ([]byte, error) {
current, err := runtime.Encode(unstructured.UnstructuredJSONScheme, currentObj)
if err != nil {
return nil, err
}
original, err := getOriginalConfiguration(currentObj)
if err != nil {
return nil, err
}
modified, err := getModifiedConfiguration(modifiedObj)
if err != nil {
return nil, err
}
// Objects retrieved through client-go do not have apiVersion and kind populated.
// The issue is known as https://github.com/kubernetes/client-go/issues/308.
// This issue will likely stay as the PR to fix that was closed without checking in (https://github.com/kubernetes/kubernetes/pull/63972).
// As such, a merge patch always tries to add apiVesion and kind as it sees apiVersion and kind in the modified (i.e. new)
// object but not in the current (i.e. retrieved) object. We could add code to make a best guess of apiVersion and kind and insert them
// (like kubectl), but for now we can live with a simple check based on name.
// Only scenario that this may cause issues is API major version upgrades (e.g v1 -> v2). For that case,
// object updates will fail anyway, so the check here does not add lots of value.
// BTW, intra-major-version upgrades (e.g. v1beta1 -> v1) are supported according to
// https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups-and-versioning.
preconditions := []mergepatch.PreconditionFunc{
mergepatch.RequireMetadataKeyUnchanged("name"),
}
patchData, err := jsonmergepatch.CreateThreeWayJSONMergePatch(original, modified, current, preconditions...)
if err != nil {
return nil, err
}
return patchData, nil
}
Agreed. We should do as kubectl does.
Is this issue still important @lijianzhi01 ? I wonder if the things that @ashu8912 recently changed for #2118 is related.