Skip to content

Commit 5457a2e

Browse files
committed
Add support for one time backup
1 parent 4961e65 commit 5457a2e

15 files changed

+379
-85
lines changed

api/v1beta2/foundationdbbackup_types.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
// +kubebuilder:metadata:annotations="foundationdb.org/release=v2.14.0"
3434
// +kubebuilder:printcolumn:name="Generation",type="integer",JSONPath=".metadata.generation",description="Latest generation of the spec",priority=0
3535
// +kubebuilder:printcolumn:name="Reconciled",type="integer",JSONPath=".status.generations.reconciled",description="Last reconciled generation of the spec",priority=0
36+
// +kubebuilder:printcolumn:name="Restorable",type="boolean",JSONPath=".status.backupDetails.restorable",description="If the backup is restorable",priority=0
3637
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
3738
// +kubebuilder:storageversion
3839

@@ -134,6 +135,15 @@ type FoundationDBBackupSpec struct {
134135
// +kubebuilder:validation:Enum=noop;stop;cleanup
135136
// +kubebuilder:default:=noop
136137
DeletionPolicy *BackupDeletionPolicy `json:"deletionPolicy,omitempty"`
138+
139+
// BackupMode defines the backup mode that should be used for the backup. When the BackupMode is set to
140+
// BackupModeOneTime, the backup will create a single snapshot and then stop. When set to BackupModeContinuous,
141+
// the backup will run continuously, creating snapshots at regular intervals defined by SnapshotPeriodSeconds.
142+
// Default: "Continuous".
143+
// +kubebuilder:validation:Optional
144+
// +kubebuilder:validation:Enum=continuous;oneTime
145+
// +kubebuilder:default:=continuous
146+
BackupMode *BackupMode `json:"backupMode,omitempty"`
137147
}
138148

139149
// BackupType defines the backup type that should be used for the backup.
@@ -165,6 +175,18 @@ const (
165175
BackupDeletionPolicyCleanup BackupDeletionPolicy = "cleanup"
166176
)
167177

178+
// BackupMode defines the mode of backup operation.
179+
// +kubebuilder:validation:MaxLength=64
180+
type BackupMode string
181+
182+
const (
183+
// BackupModeContinuous indicates that the backup should run continuously, taking snapshots at regular intervals.
184+
BackupModeContinuous BackupMode = "continuous"
185+
186+
// BackupModeOneTime indicates that the backup should create a single snapshot and then stop.
187+
BackupModeOneTime BackupMode = "oneTime"
188+
)
189+
168190
// FoundationDBBackupStatus describes the current status of the backup for a cluster.
169191
type FoundationDBBackupStatus struct {
170192
// AgentCount provides the number of agents that are up-to-date, ready,
@@ -191,6 +213,7 @@ type FoundationDBBackupStatusBackupDetails struct {
191213
Running bool `json:"running,omitempty"`
192214
Paused bool `json:"paused,omitempty"`
193215
SnapshotPeriodSeconds int `json:"snapshotTime,omitempty"`
216+
Restorable bool `json:"restorable,omitempty"`
194217
}
195218

196219
// BackupGenerationStatus stores information on which generations have reached
@@ -265,6 +288,13 @@ type BlobStoreConfiguration struct {
265288

266289
// ShouldRun determines whether a backup should be running.
267290
func (backup *FoundationDBBackup) ShouldRun() bool {
291+
// For one-time backups, don't run if already completed
292+
backupDetails := backup.Status.BackupDetails
293+
if backup.GetBackupMode() == BackupModeOneTime && backupDetails != nil &&
294+
backupDetails.Restorable {
295+
return false
296+
}
297+
268298
return backup.Spec.BackupState == "" || backup.Spec.BackupState == BackupStateRunning ||
269299
backup.Spec.BackupState == BackupStatePaused
270300
}
@@ -318,19 +348,19 @@ type FoundationDBLiveBackupStatus struct {
318348

319349
// BackupAgentsPaused describes whether the backup agents are paused.
320350
BackupAgentsPaused bool `json:"BackupAgentsPaused,omitempty"`
351+
352+
// Restorable if true, the backup can be restored
353+
Restorable *bool `json:"Restorable,omitempty"`
354+
355+
// LatestRestorablePoint contains information about the latest restorable point if any exists.
356+
LatestRestorablePoint *LatestRestorablePoint `json:"LatestRestorablePoint,omitempty"`
321357
}
322358

323359
// FoundationDBLiveBackupStatusState provides the state of a backup in the
324360
// backup status.
325361
type FoundationDBLiveBackupStatusState struct {
326362
// Running determines whether the backup is currently running.
327363
Running bool `json:"Running,omitempty"`
328-
329-
// Restorable if true, the backup can be restored
330-
Restorable *bool `json:"Restorable,omitempty"`
331-
332-
// LatestRestorablePoint contains information about the latest restorable point if any exists.
333-
LatestRestorablePoint *LatestRestorablePoint `json:"LatestRestorablePoint,omitempty"`
334364
}
335365

336366
// LatestRestorablePoint contains information about the latest restorable point if any exists.
@@ -429,6 +459,11 @@ func (backup *FoundationDBBackup) GetDeletionPolicy() BackupDeletionPolicy {
429459
return ptr.Deref(backup.Spec.DeletionPolicy, BackupDeletionPolicyNoop)
430460
}
431461

462+
// GetBackupMode will return the backup mode for this backup.
463+
func (backup *FoundationDBBackup) GetBackupMode() BackupMode {
464+
return ptr.Deref(backup.Spec.BackupMode, BackupModeContinuous)
465+
}
466+
432467
// UseUnifiedImage returns true if the unified image should be used.
433468
func (backup *FoundationDBBackup) UseUnifiedImage() bool {
434469
imageType := ImageTypeUnified

api/v1beta2/foundationdbbackup_types_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,4 +471,52 @@ var _ = Describe("[api] FoundationDBBackup", func() {
471471
),
472472
)
473473
})
474+
475+
When("testing backup mode functionality", func() {
476+
Context("GetBackupMode method", func() {
477+
It("should return continuous as default when BackupMode is nil", func() {
478+
backup.Spec.BackupMode = nil
479+
Expect(backup.GetBackupMode()).To(Equal(BackupModeContinuous))
480+
})
481+
482+
It("should return continuous when explicitly set", func() {
483+
mode := BackupModeContinuous
484+
backup.Spec.BackupMode = &mode
485+
Expect(backup.GetBackupMode()).To(Equal(BackupModeContinuous))
486+
})
487+
488+
It("should return one-time when explicitly set", func() {
489+
mode := BackupModeOneTime
490+
backup.Spec.BackupMode = &mode
491+
Expect(backup.GetBackupMode()).To(Equal(BackupModeOneTime))
492+
})
493+
})
494+
495+
Context("ShouldRun method for different backup modes", func() {
496+
It("should run continuous backup by default", func() {
497+
backup.Spec.BackupState = BackupStateRunning
498+
Expect(backup.ShouldRun()).To(BeTrue())
499+
})
500+
501+
It("should not run completed one-time backup", func() {
502+
mode := BackupModeOneTime
503+
backup.Spec.BackupMode = &mode
504+
backup.Spec.BackupState = BackupStateRunning
505+
backup.Status.BackupDetails = &FoundationDBBackupStatusBackupDetails{
506+
Restorable: true,
507+
}
508+
Expect(backup.ShouldRun()).To(BeFalse())
509+
})
510+
511+
It("should run uncompleted one-time backup", func() {
512+
mode := BackupModeOneTime
513+
backup.Spec.BackupMode = &mode
514+
backup.Spec.BackupState = BackupStateRunning
515+
backup.Status.BackupDetails = &FoundationDBBackupStatusBackupDetails{
516+
Restorable: false,
517+
}
518+
Expect(backup.ShouldRun()).To(BeTrue())
519+
})
520+
})
521+
})
474522
})

api/v1beta2/foundationdbcluster_types_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,7 @@ var _ = Describe("[api] FoundationDBCluster", func() {
837837
Status: FoundationDBLiveBackupStatusState{
838838
Running: true,
839839
},
840+
Restorable: ptr.To(false),
840841
}))
841842
})
842843
})

api/v1beta2/zz_generated.deepcopy.go

Lines changed: 16 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/apps.foundationdb.org_foundationdbbackups.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ spec:
2626
jsonPath: .status.generations.reconciled
2727
name: Reconciled
2828
type: integer
29+
- description: If the backup is restorable
30+
jsonPath: .status.backupDetails.restorable
31+
name: Restorable
32+
type: boolean
2933
- jsonPath: .metadata.creationTimestamp
3034
name: Age
3135
type: date
@@ -65,6 +69,13 @@ spec:
6569
namespace:
6670
type: string
6771
type: object
72+
backupMode:
73+
default: continuous
74+
enum:
75+
- continuous
76+
- oneTime
77+
maxLength: 64
78+
type: string
6879
backupState:
6980
enum:
7081
- Running
@@ -3869,6 +3880,8 @@ spec:
38693880
properties:
38703881
paused:
38713882
type: boolean
3883+
restorable:
3884+
type: boolean
38723885
running:
38733886
type: boolean
38743887
snapshotTime:

controllers/modify_backup.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ func (s modifyBackup) reconcile(
4141
return nil
4242
}
4343

44-
if backup.NeedsBackupReconfiguration() {
44+
// The modify command is only required for continuous backups.
45+
if backup.NeedsBackupReconfiguration() &&
46+
backup.GetBackupMode() == fdbv1beta2.BackupModeContinuous {
4547
adminClient, err := r.adminClientForBackup(ctx, backup)
4648
if err != nil {
4749
return &requeue{curError: err}

controllers/update_backup_status.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ package controllers
2323
import (
2424
"context"
2525

26-
"github.com/FoundationDB/fdb-kubernetes-operator/v2/internal"
27-
"k8s.io/apimachinery/pkg/api/equality"
28-
k8serrors "k8s.io/apimachinery/pkg/api/errors"
26+
"k8s.io/utils/ptr"
2927

3028
fdbv1beta2 "github.com/FoundationDB/fdb-kubernetes-operator/v2/api/v1beta2"
29+
"github.com/FoundationDB/fdb-kubernetes-operator/v2/internal"
3130
appsv1 "k8s.io/api/apps/v1"
31+
"k8s.io/apimachinery/pkg/api/equality"
32+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
3233
"sigs.k8s.io/controller-runtime/pkg/client"
3334
)
3435

@@ -115,6 +116,7 @@ func (s updateBackupStatus) reconcile(
115116
Running: liveStatus.Status.Running,
116117
Paused: liveStatus.BackupAgentsPaused,
117118
SnapshotPeriodSeconds: liveStatus.SnapshotIntervalSeconds,
119+
Restorable: ptr.Deref(liveStatus.Restorable, false),
118120
}
119121

120122
originalStatus := backup.Status.DeepCopy()

docs/backup_spec.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ BackupGenerationStatus stores information on which generations have reached diff
3838

3939
[Back to TOC](#table-of-contents)
4040

41+
## BackupMode
42+
43+
BackupMode defines the mode of backup operation.
44+
45+
[Back to TOC](#table-of-contents)
46+
4147
## BackupState
4248

4349
BackupState defines the desired state of a backup
@@ -108,6 +114,7 @@ FoundationDBBackupSpec describes the desired state of the backup for a cluster.
108114
| imageType | ImageType defines the image type that should be used for the FoundationDBCluster deployment. When the type is set to \"unified\" the deployment will use the new fdb-kubernetes-monitor. Otherwise the main container and the sidecar container will use different images. Default: split | *ImageType | false |
109115
| backupType | BackupType defines the backup type that should be used for the backup. When the BackupType is set to BackupTypePartitionedLog, it's expected that the FoundationDBCluster creates and manages the additional backup worker processes. A migration to a different backup type is not yet supported in the operator. Default: \"backup_agent\". | *[BackupType](#backuptype) | false |
110116
| deletionPolicy | DeletionPolicy defines the deletion policy for this backup. The BackupDeletionPolicy defines the actions that should be taken when the FoundationDBBackup resource has a deletion timestamp. | *[BackupDeletionPolicy](#backupdeletionpolicy) | false |
117+
| backupMode | BackupMode defines the backup mode that should be used for the backup. When the BackupMode is set to BackupModeOneTime, the backup will create a single snapshot and then stop. When set to BackupModeContinuous, the backup will run continuously, creating snapshots at regular intervals defined by SnapshotPeriodSeconds. Default: \"Continuous\". | *[BackupMode](#backupmode) | false |
111118

112119
[Back to TOC](#table-of-contents)
113120

@@ -134,6 +141,7 @@ FoundationDBBackupStatusBackupDetails provides information about the state of th
134141
| running | | bool | false |
135142
| paused | | bool | false |
136143
| snapshotTime | | int | false |
144+
| restorable | | bool | false |
137145

138146
[Back to TOC](#table-of-contents)
139147

@@ -147,6 +155,8 @@ FoundationDBLiveBackupStatus describes the live status of the backup for a clust
147155
| SnapshotIntervalSeconds | SnapshotIntervalSeconds provides the interval of the snapshots. | int | false |
148156
| Status | Status provides the current state of the backup. | [FoundationDBLiveBackupStatusState](#foundationdblivebackupstatusstate) | false |
149157
| BackupAgentsPaused | BackupAgentsPaused describes whether the backup agents are paused. | bool | false |
158+
| Restorable | Restorable if true, the backup can be restored | *bool | false |
159+
| LatestRestorablePoint | LatestRestorablePoint contains information about the latest restorable point if any exists. | *[LatestRestorablePoint](#latestrestorablepoint) | false |
150160

151161
[Back to TOC](#table-of-contents)
152162

@@ -157,8 +167,6 @@ FoundationDBLiveBackupStatusState provides the state of a backup in the backup s
157167
| Field | Description | Scheme | Required |
158168
| ----- | ----------- | ------ | -------- |
159169
| Running | Running determines whether the backup is currently running. | bool | false |
160-
| Restorable | Restorable if true, the backup can be restored | *bool | false |
161-
| LatestRestorablePoint | LatestRestorablePoint contains information about the latest restorable point if any exists. | *[LatestRestorablePoint](#latestrestorablepoint) | false |
162170

163171
[Back to TOC](#table-of-contents)
164172

0 commit comments

Comments
 (0)