diff --git a/pkg/controller/backup_sync_controller.go b/pkg/controller/backup_sync_controller.go index 17edd3b81..a36403137 100644 --- a/pkg/controller/backup_sync_controller.go +++ b/pkg/controller/backup_sync_controller.go @@ -29,6 +29,7 @@ import ( "github.com/heptio/ark/pkg/cloudprovider" arkv1client "github.com/heptio/ark/pkg/generated/clientset/versioned/typed/ark/v1" "github.com/heptio/ark/pkg/util/kube" + "github.com/heptio/ark/pkg/util/stringslice" ) type backupSyncController struct { @@ -68,6 +69,8 @@ func (c *backupSyncController) Run(ctx context.Context, workers int) error { return nil } +const gcFinalizer = "gc.ark.heptio.com" + func (c *backupSyncController) run() { c.logger.Info("Syncing backups from object storage") backups, err := c.backupService.GetAllBackups(c.bucket) @@ -81,6 +84,10 @@ func (c *backupSyncController) run() { logContext := c.logger.WithField("backup", kube.NamespaceAndName(cloudBackup)) logContext.Info("Syncing backup") + // If we're syncing backups made by pre-0.8.0 versions, the server removes all finalizers + // faster than the sync finishes. Just process them as we find them. + cloudBackup.Finalizers = stringslice.Except(cloudBackup.Finalizers, gcFinalizer) + cloudBackup.ResourceVersion = "" if _, err := c.client.Backups(cloudBackup.Namespace).Create(cloudBackup); err != nil && !kuberrs.IsAlreadyExists(err) { logContext.WithError(errors.WithStack(err)).Error("Error syncing backup from object storage") diff --git a/pkg/controller/backup_sync_controller_test.go b/pkg/controller/backup_sync_controller_test.go index 7585d6053..f1b5dc6be 100644 --- a/pkg/controller/backup_sync_controller_test.go +++ b/pkg/controller/backup_sync_controller_test.go @@ -27,6 +27,7 @@ import ( "github.com/heptio/ark/pkg/apis/ark/v1" "github.com/heptio/ark/pkg/generated/clientset/versioned/fake" + "github.com/heptio/ark/pkg/util/stringslice" arktest "github.com/heptio/ark/pkg/util/test" ) @@ -51,6 +52,18 @@ func TestBackupSyncControllerRun(t *testing.T) { arktest.NewTestBackup().WithNamespace("ns-2").WithName("backup-3").Backup, }, }, + { + name: "Finalizer gets removed on sync", + cloudBackups: []*v1.Backup{ + arktest.NewTestBackup().WithNamespace("ns-1").WithFinalizers(gcFinalizer).Backup, + }, + }, + { + name: "Only target finalizer is removed", + cloudBackups: []*v1.Backup{ + arktest.NewTestBackup().WithNamespace("ns-1").WithFinalizers(gcFinalizer, "blah").Backup, + }, + }, } for _, test := range tests { @@ -77,6 +90,8 @@ func TestBackupSyncControllerRun(t *testing.T) { // we only expect creates for items within the target bucket for _, cloudBackup := range test.cloudBackups { + // Verify that the run function stripped the GC finalizer + assert.False(t, stringslice.Has(cloudBackup.Finalizers, gcFinalizer)) action := core.NewCreateAction( v1.SchemeGroupVersion.WithResource("backups"), cloudBackup.Namespace, diff --git a/pkg/util/test/test_backup.go b/pkg/util/test/test_backup.go index bd870fd29..4dc52409b 100644 --- a/pkg/util/test/test_backup.go +++ b/pkg/util/test/test_backup.go @@ -124,3 +124,9 @@ func (b *TestBackup) WithResourceVersion(version string) *TestBackup { b.ResourceVersion = version return b } + +func (b *TestBackup) WithFinalizers(finalizers ...string) *TestBackup { + b.ObjectMeta.Finalizers = append(b.ObjectMeta.Finalizers, finalizers...) + + return b +}