Passing namespace list in batches to resourceCollector.GetResources()
@@ -55,6 +55,7 @@ const (
allNamespacesSpecifier = "*"
backupVolumeBatchCount = 10
+ backupResourcesBatchCount = 15
maxRetry = 10
retrySleep = 10 * time.Second
)
@@ -968,8 +969,15 @@ func (a *ApplicationBackupController) backupResources(
// Always backup optional resources. When restorting they need to be
// explicitly added to the spec
objectMap := stork_api.CreateObjectsMap(backup.Spec.IncludeResources)
- allObjects, err := a.resourceCollector.GetResources(
- backup.Spec.Namespaces,
+ namespacelist := backup.Spec.Namespaces
+ // GetResources takes more time, if we have more number of namespaces
+ // So, submitting it in batches and in between each batch,
+ // updating the LastUpdateTimestamp to show that backup is progressing
+ allObjects := make([]runtime.Unstructured, 0)
+ for i := 0; i < len(namespacelist); i += backupResourcesBatchCount {
+ batch := namespacelist[i:min(i+backupResourcesBatchCount, len(namespacelist))]
+ objects, err := a.resourceCollector.GetResources(
+ batch,
backup.Spec.Selectors,
objectMap,
optionalBackupResources,
@@ -978,11 +986,45 @@ func (a *ApplicationBackupController) backupResources(
log.ApplicationBackupLog(backup).Errorf("Error getting resources: %v", err)
return err
}
+ allObjects = append(allObjects, objects...)
+ // Do a dummy update to the backup CR to update only the last update timestamp
+ namespacedName := types.NamespacedName{}
+ namespacedName.Namespace = backup.Namespace
+ namespacedName.Name = backup.Name
+ for i := 0; i < maxRetry; i++ {
+ err = a.client.Get(context.TODO(), namespacedName, backup)
+ if err != nil {
+ time.Sleep(retrySleep)
+ continue
+ }
+ backup.Status.LastUpdateTimestamp = metav1.Now()
+ err = a.client.Update(context.TODO(), backup)
+ if err != nil {
+ time.Sleep(retrySleep)
+ continue
+ } else {
+ break
+ }
+ }
+ }
+ updatedAllObjects := make([]runtime.Unstructured, 0)
+ for _, obj := range allObjects {
+ resourceMap := make(map[types.UID]bool)
+ metadata, err := meta.Accessor(obj)
+ if err != nil {
+ return err
+ }
+ if _, ok := resourceMap[metadata.GetUID()]; ok {
+ continue
+ }
+ resourceMap[metadata.GetUID()] = true
+ updatedAllObjects = append(updatedAllObjects, obj)
+ }
if backup.Status.Resources == nil {
// Save the collected resources infos in the status
resourceInfos := make([]*stork_api.ApplicationBackupResourceInfo, 0)
- for _, obj := range allObjects {
+ for _, obj := range updatedAllObjects {
metadata, err := meta.Accessor(obj)
if err != nil {
return err
@@ -1015,7 +1057,7 @@ func (a *ApplicationBackupController) backupResources(
}
// Do any additional preparation for the resources if required
- if err = a.prepareResources(backup, allObjects); err != nil {
+ if err = a.prepareResources(backup, updatedAllObjects); err != nil {
message := fmt.Sprintf("Error preparing resources for backup: %v", err)
backup.Status.Status = stork_api.ApplicationBackupStatusFailed
backup.Status.Stage = stork_api.ApplicationBackupStageFinal
@@ -1034,7 +1076,7 @@ func (a *ApplicationBackupController) backupResources(
}
// Upload the resources to the backup location
- if err = a.uploadResources(backup, allObjects); err != nil {
+ if err = a.uploadResources(backup, updatedAllObjects); err != nil {
message := fmt.Sprintf("Error uploading resources: %v", err)
backup.Status.Status = stork_api.ApplicationBackupStatusFailed
backup.Status.Stage = stork_api.ApplicationBackupStageFinal
