diff --git a/pkg/controller/data_download_controller.go b/pkg/controller/data_download_controller.go index e6b3f8872..53d83d98e 100644 --- a/pkg/controller/data_download_controller.go +++ b/pkg/controller/data_download_controller.go @@ -434,10 +434,16 @@ func (r *DataDownloadReconciler) OnDataDownloadCompleted(ctx context.Context, na log.Info("Cleaning up exposed environment") r.restoreExposer.CleanUp(ctx, objRef) - original := dd.DeepCopy() - dd.Status.Phase = velerov2alpha1api.DataDownloadPhaseCompleted - dd.Status.CompletionTimestamp = &metav1.Time{Time: r.Clock.Now()} - if err := r.client.Patch(ctx, &dd, client.MergeFrom(original)); err != nil { + if err := UpdateDataDownloadWithRetry(ctx, r.client, types.NamespacedName{Namespace: dd.Namespace, Name: dd.Name}, log, func(dd *velerov2alpha1api.DataDownload) bool { + if isDataDownloadInFinalState(dd) { + return false + } + + dd.Status.Phase = velerov2alpha1api.DataDownloadPhaseCompleted + dd.Status.CompletionTimestamp = &metav1.Time{Time: r.Clock.Now()} + + return true + }); err != nil { log.WithError(err).Error("error updating data download status") } else { log.Infof("Data download is marked as %s", dd.Status.Phase) @@ -470,22 +476,28 @@ func (r *DataDownloadReconciler) OnDataDownloadCancelled(ctx context.Context, na var dd velerov2alpha1api.DataDownload if getErr := r.client.Get(ctx, types.NamespacedName{Name: ddName, Namespace: namespace}, &dd); getErr != nil { log.WithError(getErr).Warn("Failed to get datadownload on cancel") - } else { - // cleans up any objects generated during the snapshot expose - r.restoreExposer.CleanUp(ctx, getDataDownloadOwnerObject(&dd)) + return + } + // cleans up any objects generated during the snapshot expose + r.restoreExposer.CleanUp(ctx, getDataDownloadOwnerObject(&dd)) + + if err := UpdateDataDownloadWithRetry(ctx, r.client, types.NamespacedName{Namespace: dd.Namespace, Name: dd.Name}, log, func(dd *velerov2alpha1api.DataDownload) bool { + if isDataDownloadInFinalState(dd) { + return false + } - original := dd.DeepCopy() dd.Status.Phase = velerov2alpha1api.DataDownloadPhaseCanceled if dd.Status.StartTimestamp.IsZero() { dd.Status.StartTimestamp = &metav1.Time{Time: r.Clock.Now()} } dd.Status.CompletionTimestamp = &metav1.Time{Time: r.Clock.Now()} - if err := r.client.Patch(ctx, &dd, client.MergeFrom(original)); err != nil { - log.WithError(err).Error("error updating data download status") - } else { - r.metrics.RegisterDataDownloadCancel(r.nodeName) - delete(r.cancelledDataDownload, dd.Name) - } + + return true + }); err != nil { + log.WithError(err).Error("error updating data download status") + } else { + r.metrics.RegisterDataDownloadCancel(r.nodeName) + delete(r.cancelledDataDownload, dd.Name) } } diff --git a/pkg/controller/data_upload_controller.go b/pkg/controller/data_upload_controller.go index f9aa2fad4..6ab65f172 100644 --- a/pkg/controller/data_upload_controller.go +++ b/pkg/controller/data_upload_controller.go @@ -468,16 +468,21 @@ func (r *DataUploadReconciler) OnDataUploadCompleted(ctx context.Context, namesp } // Update status to Completed with path & snapshot ID. - original := du.DeepCopy() - du.Status.Path = result.Backup.Source.ByPath - du.Status.Phase = velerov2alpha1api.DataUploadPhaseCompleted - du.Status.SnapshotID = result.Backup.SnapshotID - du.Status.CompletionTimestamp = &metav1.Time{Time: r.Clock.Now()} - if result.Backup.EmptySnapshot { - du.Status.Message = "volume was empty so no data was upload" - } + if err := UpdateDataUploadWithRetry(ctx, r.client, types.NamespacedName{Namespace: du.Namespace, Name: du.Name}, log, func(du *velerov2alpha1api.DataUpload) bool { + if isDataUploadInFinalState(du) { + return false + } - if err := r.client.Patch(ctx, &du, client.MergeFrom(original)); err != nil { + du.Status.Path = result.Backup.Source.ByPath + du.Status.Phase = velerov2alpha1api.DataUploadPhaseCompleted + du.Status.SnapshotID = result.Backup.SnapshotID + du.Status.CompletionTimestamp = &metav1.Time{Time: r.Clock.Now()} + if result.Backup.EmptySnapshot { + du.Status.Message = "volume was empty so no data was upload" + } + + return true + }); err != nil { log.WithError(err).Error("error updating DataUpload status") } else { log.Info("Data upload completed") @@ -510,21 +515,28 @@ func (r *DataUploadReconciler) OnDataUploadCancelled(ctx context.Context, namesp du := &velerov2alpha1api.DataUpload{} if getErr := r.client.Get(ctx, types.NamespacedName{Name: duName, Namespace: namespace}, du); getErr != nil { log.WithError(getErr).Warn("Failed to get dataupload on cancel") - } else { - // cleans up any objects generated during the snapshot expose - r.cleanUp(ctx, du, log) - original := du.DeepCopy() + return + } + // cleans up any objects generated during the snapshot expose + r.cleanUp(ctx, du, log) + + if err := UpdateDataUploadWithRetry(ctx, r.client, types.NamespacedName{Namespace: du.Namespace, Name: du.Name}, log, func(du *velerov2alpha1api.DataUpload) bool { + if isDataUploadInFinalState(du) { + return false + } + du.Status.Phase = velerov2alpha1api.DataUploadPhaseCanceled if du.Status.StartTimestamp.IsZero() { du.Status.StartTimestamp = &metav1.Time{Time: r.Clock.Now()} } du.Status.CompletionTimestamp = &metav1.Time{Time: r.Clock.Now()} - if err := r.client.Patch(ctx, du, client.MergeFrom(original)); err != nil { - log.WithError(err).Error("error updating DataUpload status") - } else { - r.metrics.RegisterDataUploadCancel(r.nodeName) - delete(r.cancelledDataUpload, du.Name) - } + + return true + }); err != nil { + log.WithError(err).Error("error updating DataUpload status") + } else { + r.metrics.RegisterDataUploadCancel(r.nodeName) + delete(r.cancelledDataUpload, du.Name) } }