[bugfix] fix Custom or Unstruncted Resources can't update problem.

Signed-off-by: haojingcn <mhjlq1989@gmail.com>
pull/12888/head
haojingcn 2 years ago
parent 976ed8c0be
commit 9c25a8df16

@ -609,27 +609,29 @@ func deleteResource(info *resource.Info, policy metav1.DeletionPropagation) erro
return err return err
} }
func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) { func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, bool, error) {
isCRDOrUnstructured := false
oldData, err := json.Marshal(current) oldData, err := json.Marshal(current)
if err != nil { if err != nil {
return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing current configuration") return nil, types.StrategicMergePatchType, isCRDOrUnstructured, errors.Wrap(err, "serializing current configuration")
} }
newData, err := json.Marshal(target.Object) newData, err := json.Marshal(target.Object)
if err != nil { if err != nil {
return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing target configuration") return nil, types.StrategicMergePatchType, isCRDOrUnstructured, errors.Wrap(err, "serializing target configuration")
} }
// Fetch the current object for the three way merge // Fetch the current object for the three way merge
helper := resource.NewHelper(target.Client, target.Mapping).WithFieldManager(getManagedFieldsManager()) helper := resource.NewHelper(target.Client, target.Mapping).WithFieldManager(getManagedFieldsManager())
currentObj, err := helper.Get(target.Namespace, target.Name) currentObj, err := helper.Get(target.Namespace, target.Name)
if err != nil && !apierrors.IsNotFound(err) { if err != nil && !apierrors.IsNotFound(err) {
return nil, types.StrategicMergePatchType, errors.Wrapf(err, "unable to get data for current object %s/%s", target.Namespace, target.Name) return nil, types.StrategicMergePatchType, isCRDOrUnstructured, errors.Wrapf(err, "unable to get data for current object %s/%s", target.Namespace, target.Name)
} }
// Even if currentObj is nil (because it was not found), it will marshal just fine // Even if currentObj is nil (because it was not found), it will marshal just fine
currentData, err := json.Marshal(currentObj) currentData, err := json.Marshal(currentObj)
if err != nil { if err != nil {
return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing live configuration") return nil, types.StrategicMergePatchType, isCRDOrUnstructured, errors.Wrap(err, "serializing live configuration")
} }
// Get a versioned object // Get a versioned object
@ -647,16 +649,17 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P
if isUnstructured || isCRD { if isUnstructured || isCRD {
// fall back to generic JSON merge patch // fall back to generic JSON merge patch
patch, err := jsonpatch.CreateMergePatch(oldData, newData) patch, err := jsonpatch.CreateMergePatch(oldData, newData)
return patch, types.MergePatchType, err isCRDOrUnstructured = true
return patch, types.MergePatchType, isCRDOrUnstructured, err
} }
patchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject) patchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject)
if err != nil { if err != nil {
return nil, types.StrategicMergePatchType, errors.Wrap(err, "unable to create patch metadata from object") return nil, types.StrategicMergePatchType, isCRDOrUnstructured, errors.Wrap(err, "unable to create patch metadata from object")
} }
patch, err := strategicpatch.CreateThreeWayMergePatch(oldData, newData, currentData, patchMeta, true) patch, err := strategicpatch.CreateThreeWayMergePatch(oldData, newData, currentData, patchMeta, true)
return patch, types.StrategicMergePatchType, err return patch, types.StrategicMergePatchType, isCRDOrUnstructured, err
} }
func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force bool) error { func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force bool) error {
@ -675,7 +678,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
} }
c.Log("Replaced %q with kind %s for kind %s", target.Name, currentObj.GetObjectKind().GroupVersionKind().Kind, kind) c.Log("Replaced %q with kind %s for kind %s", target.Name, currentObj.GetObjectKind().GroupVersionKind().Kind, kind)
} else { } else {
patch, patchType, err := createPatch(target, currentObj) patch, patchType, isCRDOrUnstructured, err := createPatch(target, currentObj)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to create patch") return errors.Wrap(err, "failed to create patch")
} }
@ -690,8 +693,14 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
return nil return nil
} }
// send patch to server // send patch to server
c.Log("Patch %s %q in namespace %s", kind, target.Name, target.Namespace) if isCRDOrUnstructured {
obj, err = helper.Patch(target.Namespace, target.Name, patchType, patch, nil) // CRDs and Unstructured resources do not support strategic merge patch, so just replace it
c.Log("Custom or Unstructured Resouce Replace %s %q in namespace %s ", kind, target.Name, target.Namespace)
obj, err = helper.Replace(target.Namespace, target.Name, true, target.Object)
} else {
c.Log("Patch %s %q in namespace %s", kind, target.Name, target.Namespace)
obj, err = helper.Patch(target.Namespace, target.Name, patchType, patch, nil)
}
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot patch %q with kind %s", target.Name, kind) return errors.Wrapf(err, "cannot patch %q with kind %s", target.Name, kind)
} }

Loading…
Cancel
Save