in pkg/controllers/workapplier/preprocess.go [448:534]
func (r *Reconciler) removeOneLeftOverManifest(
ctx context.Context,
leftOverManifest fleetv1beta1.AppliedResourceMeta,
expectedAppliedWorkOwnerRef *metav1.OwnerReference,
) error {
// Build the GVR.
gvr := schema.GroupVersionResource{
Group: leftOverManifest.Group,
Version: leftOverManifest.Version,
Resource: leftOverManifest.Resource,
}
manifestNamespace := leftOverManifest.Namespace
manifestName := leftOverManifest.Name
inMemberClusterObj, err := r.spokeDynamicClient.
Resource(gvr).
Namespace(manifestNamespace).
Get(ctx, manifestName, metav1.GetOptions{})
switch {
case err != nil && apierrors.IsNotFound(err):
// The object has been deleted from the member cluster; no further action is needed.
return nil
case err != nil:
// Failed to retrieve the object from the member cluster.
wrappedErr := controller.NewAPIServerError(true, err)
return fmt.Errorf("failed to retrieve the object from the member cluster (gvr=%+v, manifestObj=%+v): %w", gvr, klog.KRef(manifestNamespace, manifestName), wrappedErr)
case inMemberClusterObj.GetDeletionTimestamp() != nil:
// The object has been marked for deletion; no further action is needed.
return nil
}
// There are occasions, though rare, where the object has the same GVR + namespace + name
// combo but is not the applied object Fleet tries to find. This could happen if the object
// has been deleted and then re-created manually without Fleet's acknowledgement. In such cases
// Fleet would ignore the object, and this is not registered as an error.
if !isInMemberClusterObjectDerivedFromManifestObj(inMemberClusterObj, expectedAppliedWorkOwnerRef) {
// The object is not derived from the manifest object.
klog.V(2).InfoS("The object to remove is not derived from the manifest object; will not proceed with the removal",
"gvr", gvr, "manifestObj",
klog.KRef(manifestNamespace, manifestName), "inMemberClusterObj", klog.KObj(inMemberClusterObj),
"expectedAppliedWorkOwnerRef", *expectedAppliedWorkOwnerRef)
return nil
}
switch {
case len(inMemberClusterObj.GetOwnerReferences()) > 1:
// Fleet is not the sole owner of the object; in this case, Fleet will only drop the
// ownership.
klog.V(2).InfoS("The object to remove is co-owned by other sources; Fleet will drop the ownership",
"gvr", gvr, "manifestObj",
klog.KRef(manifestNamespace, manifestName), "inMemberClusterObj", klog.KObj(inMemberClusterObj),
"expectedAppliedWorkOwnerRef", *expectedAppliedWorkOwnerRef)
removeOwnerRef(inMemberClusterObj, expectedAppliedWorkOwnerRef)
if _, err := r.spokeDynamicClient.Resource(gvr).Namespace(manifestNamespace).Update(ctx, inMemberClusterObj, metav1.UpdateOptions{}); err != nil && !apierrors.IsNotFound(err) {
// Failed to drop the ownership.
wrappedErr := controller.NewAPIServerError(false, err)
return fmt.Errorf("failed to drop the ownership of the object (gvr=%+v, manifestObj=%+v, inMemberClusterObj=%+v, expectedAppliedWorkOwnerRef=%+v): %w",
gvr, klog.KRef(manifestNamespace, manifestName), klog.KObj(inMemberClusterObj), *expectedAppliedWorkOwnerRef, wrappedErr)
}
default:
// Fleet is the sole owner of the object; in this case, Fleet will delete the object.
klog.V(2).InfoS("The object to remove is solely owned by Fleet; Fleet will delete the object",
"gvr", gvr, "manifestObj",
klog.KRef(manifestNamespace, manifestName), "inMemberClusterObj", klog.KObj(inMemberClusterObj),
"expectedAppliedWorkOwnerRef", *expectedAppliedWorkOwnerRef)
inMemberClusterObjUID := inMemberClusterObj.GetUID()
deleteOpts := metav1.DeleteOptions{
Preconditions: &metav1.Preconditions{
// Add a UID pre-condition to guard against the case where the object has changed
// right before the deletion request is sent.
//
// Technically speaking resource version based concurrency control should also be
// enabled here; Fleet drops the check to avoid conflicts; this is safe as the Fleet
// ownership is considered to be a reserved field and other changes on the object are
// irrelevant to this step.
UID: &inMemberClusterObjUID,
},
}
if err := r.spokeDynamicClient.Resource(gvr).Namespace(manifestNamespace).Delete(ctx, manifestName, deleteOpts); err != nil && !apierrors.IsNotFound(err) {
// Failed to delete the object from the member cluster.
wrappedErr := controller.NewAPIServerError(false, err)
return fmt.Errorf("failed to delete the object (gvr=%+v, manifestObj=%+v, inMemberClusterObj=%+v, expectedAppliedWorkOwnerRef=%+v): %w",
gvr, klog.KRef(manifestNamespace, manifestName), klog.KObj(inMemberClusterObj), *expectedAppliedWorkOwnerRef, wrappedErr)
}
}
return nil
}