From 4beb8aab3cfaf1efa026dc6d8a2e72b96c64325f Mon Sep 17 00:00:00 2001 From: Rohan Vora Date: Thu, 4 Apr 2019 14:59:13 -0700 Subject: [PATCH] Set default backup TTL Set default backup TTL to 30 days when TTL is not provided in the backup yaml configuration. Updates #138 Signed-off-by: Rohan Vora --- changelogs/unreleased/1352-vorar | 1 + docs/api-types/backup.md | 4 +- pkg/cmd/server/server.go | 7 +++ pkg/controller/backup_controller.go | 12 +++-- pkg/controller/backup_controller_test.go | 58 ++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/1352-vorar diff --git a/changelogs/unreleased/1352-vorar b/changelogs/unreleased/1352-vorar new file mode 100644 index 000000000..e051415f2 --- /dev/null +++ b/changelogs/unreleased/1352-vorar @@ -0,0 +1 @@ +set default TTL for backups \ No newline at end of file diff --git a/docs/api-types/backup.md b/docs/api-types/backup.md index f7dd9fdfc..561500400 100644 --- a/docs/api-types/backup.md +++ b/docs/api-types/backup.md @@ -66,7 +66,9 @@ spec: volumeSnapshotLocations: - aws-primary - gcp-primary - # The amount of time before this backup is eligible for garbage collection. + # The amount of time before this backup is eligible for garbage collection. If not specified, + # a default value of 30 days will be used. The default can be configured on the velero server + # by passing the flag --default-backup-ttl. ttl: 24h0m0s # Actions to perform at different times during a backup. The only hook currently supported is # executing a command in a container in a pod using the pod exec API. Optional. diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index ca27bfba1..4df0dfc40 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -83,11 +83,15 @@ const ( defaultClientBurst int = 30 defaultProfilerAddress = "localhost:6060" + + // the default TTL for a backup + defaultBackupTTL = 30 * 24 * time.Hour ) type serverConfig struct { pluginDir, metricsAddress, defaultBackupLocation string backupSyncPeriod, podVolumeOperationTimeout, resourceTerminatingTimeout time.Duration + defaultBackupTTL time.Duration restoreResourcePriorities []string defaultVolumeSnapshotLocations map[string]string restoreOnly bool @@ -106,6 +110,7 @@ func NewCommand() *cobra.Command { defaultBackupLocation: "default", defaultVolumeSnapshotLocations: make(map[string]string), backupSyncPeriod: defaultBackupSyncPeriod, + defaultBackupTTL: defaultBackupTTL, podVolumeOperationTimeout: defaultPodVolumeOperationTimeout, restoreResourcePriorities: defaultRestorePriorities, clientQPS: defaultClientQPS, @@ -171,6 +176,7 @@ func NewCommand() *cobra.Command { command.Flags().IntVar(&config.clientBurst, "client-burst", config.clientBurst, "maximum number of requests by the server to the Kubernetes API in a short period of time") command.Flags().StringVar(&config.profilerAddress, "profiler-address", config.profilerAddress, "the address to expose the pprof profiler") command.Flags().DurationVar(&config.resourceTerminatingTimeout, "terminating-resource-timeout", config.resourceTerminatingTimeout, "how long to wait on persistent volumes and namespaces to terminate during a restore before timing out") + command.Flags().DurationVar(&config.defaultBackupTTL, "default-backup-ttl", config.defaultBackupTTL, "how long to wait by default before backups can be garbage collected") return command } @@ -565,6 +571,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string backupTracker, s.sharedInformerFactory.Velero().V1().BackupStorageLocations(), s.config.defaultBackupLocation, + s.config.defaultBackupTTL, s.sharedInformerFactory.Velero().V1().VolumeSnapshotLocations(), defaultVolumeSnapshotLocations, s.metrics, diff --git a/pkg/controller/backup_controller.go b/pkg/controller/backup_controller.go index 9dc2abf2a..d3cb2d664 100644 --- a/pkg/controller/backup_controller.go +++ b/pkg/controller/backup_controller.go @@ -64,6 +64,7 @@ type backupController struct { backupTracker BackupTracker backupLocationLister listers.BackupStorageLocationLister defaultBackupLocation string + defaultBackupTTL time.Duration snapshotLocationLister listers.VolumeSnapshotLocationLister defaultSnapshotLocations map[string]string metrics *metrics.ServerMetrics @@ -80,6 +81,7 @@ func NewBackupController( backupTracker BackupTracker, backupLocationInformer informers.BackupStorageLocationInformer, defaultBackupLocation string, + defaultBackupTTL time.Duration, volumeSnapshotLocationInformer informers.VolumeSnapshotLocationInformer, defaultSnapshotLocations map[string]string, metrics *metrics.ServerMetrics, @@ -95,6 +97,7 @@ func NewBackupController( backupTracker: backupTracker, backupLocationLister: backupLocationInformer.Lister(), defaultBackupLocation: defaultBackupLocation, + defaultBackupTTL: defaultBackupTTL, snapshotLocationLister: volumeSnapshotLocationInformer.Lister(), defaultSnapshotLocations: defaultSnapshotLocations, metrics: metrics, @@ -247,11 +250,14 @@ func (c *backupController) prepareBackupRequest(backup *velerov1api.Backup) *pkg // set backup version request.Status.Version = pkgbackup.BackupVersion - // calculate expiration - if request.Spec.TTL.Duration > 0 { - request.Status.Expiration = metav1.NewTime(c.clock.Now().Add(request.Spec.TTL.Duration)) + if request.Spec.TTL.Duration == 0 { + // set default backup TTL + request.Spec.TTL.Duration = c.defaultBackupTTL } + // calculate expiration + request.Status.Expiration = metav1.NewTime(c.clock.Now().Add(request.Spec.TTL.Duration)) + // default storage location if not specified if request.Spec.StorageLocation == "" { request.Spec.StorageLocation = c.defaultBackupLocation diff --git a/pkg/controller/backup_controller_test.go b/pkg/controller/backup_controller_test.go index 9d34ac121..5cf56694e 100644 --- a/pkg/controller/backup_controller_test.go +++ b/pkg/controller/backup_controller_test.go @@ -170,6 +170,7 @@ func TestProcessBackupValidationFailures(t *testing.T) { backupLocationLister: sharedInformers.Velero().V1().BackupStorageLocations().Lister(), snapshotLocationLister: sharedInformers.Velero().V1().VolumeSnapshotLocations().Lister(), defaultBackupLocation: defaultBackupLocation.Name, + clock: &clock.RealClock{}, } require.NotNil(t, test.backup) @@ -198,6 +199,61 @@ func TestProcessBackupValidationFailures(t *testing.T) { } } +func TestDefaultBackupTTL(t *testing.T) { + + var ( + defaultBackupTTL = metav1.Duration{Duration: 24 * 30 * time.Hour} + ) + + now, err := time.Parse(time.RFC1123Z, time.RFC1123Z) + require.NoError(t, err) + now = now.Local() + + tests := []struct { + name string + backup *v1.Backup + backupLocation *v1.BackupStorageLocation + expectedTTL metav1.Duration + expectedExpiration metav1.Time + }{ + { + name: "backup with no TTL specified", + backup: velerotest.NewTestBackup().WithName("backup-1").Backup, + expectedTTL: defaultBackupTTL, + expectedExpiration: metav1.NewTime(now.Add(defaultBackupTTL.Duration)), + }, + { + name: "backup with TTL specified", + backup: velerotest.NewTestBackup().WithName("backup-1").WithTTL(1 * time.Hour).Backup, + expectedTTL: metav1.Duration{Duration: 1 * time.Hour}, + expectedExpiration: metav1.NewTime(now.Add(1 * time.Hour)), + }, + } + + for _, test := range tests { + var ( + clientset = fake.NewSimpleClientset(test.backup) + logger = logging.DefaultLogger(logrus.DebugLevel) + sharedInformers = informers.NewSharedInformerFactory(clientset, 0) + ) + + t.Run(test.name, func(t *testing.T) { + c := &backupController{ + genericController: newGenericController("backup-test", logger), + backupLocationLister: sharedInformers.Velero().V1().BackupStorageLocations().Lister(), + snapshotLocationLister: sharedInformers.Velero().V1().VolumeSnapshotLocations().Lister(), + defaultBackupTTL: defaultBackupTTL.Duration, + clock: clock.NewFakeClock(now), + } + + res := c.prepareBackupRequest(test.backup) + assert.NotNil(t, res) + assert.Equal(t, test.expectedTTL, res.Spec.TTL) + assert.Equal(t, test.expectedExpiration, res.Status.Expiration) + }) + } +} + func TestProcessBackupCompletions(t *testing.T) { defaultBackupLocation := velerotest.NewTestBackupStorageLocation().WithName("loc-1").BackupStorageLocation @@ -231,6 +287,7 @@ func TestProcessBackupCompletions(t *testing.T) { Version: 1, StartTimestamp: metav1.NewTime(now), CompletionTimestamp: metav1.NewTime(now), + Expiration: metav1.NewTime(now), }, }, }, @@ -254,6 +311,7 @@ func TestProcessBackupCompletions(t *testing.T) { Version: 1, StartTimestamp: metav1.NewTime(now), CompletionTimestamp: metav1.NewTime(now), + Expiration: metav1.NewTime(now), }, }, },