mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-07-19 22:42:44 +00:00
Add BackupType in backup.spec.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Add BackupType in backup.spec
|
||||
@@ -41,6 +41,13 @@ spec:
|
||||
spec:
|
||||
description: BackupSpec defines the specification for a Velero backup.
|
||||
properties:
|
||||
backupType:
|
||||
description: BackupType specifies how volume data is backed up, with
|
||||
possible values including Full and Incremental.
|
||||
enum:
|
||||
- Full
|
||||
- Incremental
|
||||
type: string
|
||||
csiSnapshotTimeout:
|
||||
description: |-
|
||||
CSISnapshotTimeout specifies the time used to wait for CSI VolumeSnapshot status turns to
|
||||
|
||||
@@ -80,6 +80,13 @@ spec:
|
||||
Template is the definition of the Backup to be run
|
||||
on the provided schedule
|
||||
properties:
|
||||
backupType:
|
||||
description: BackupType specifies how volume data is backed up,
|
||||
with possible values including Full and Incremental.
|
||||
enum:
|
||||
- Full
|
||||
- Incremental
|
||||
type: string
|
||||
csiSnapshotTimeout:
|
||||
description: |-
|
||||
CSISnapshotTimeout specifies the time used to wait for CSI VolumeSnapshot status turns to
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -184,6 +184,10 @@ type BackupSpec struct {
|
||||
// +optional
|
||||
// +nullable
|
||||
UploaderConfig *UploaderConfigForBackup `json:"uploaderConfig,omitempty"`
|
||||
|
||||
// BackupType specifies how volume data is backed up, with possible values including Full and Incremental.
|
||||
// +optional
|
||||
BackupType BackupType `json:"backupType,omitempty"`
|
||||
}
|
||||
|
||||
// UploaderConfigForBackup defines the configuration for the uploader when doing backup.
|
||||
@@ -357,6 +361,15 @@ const (
|
||||
BackupPhaseDeleting BackupPhase = "Deleting"
|
||||
)
|
||||
|
||||
// BackupType specifies how volume data is backed up, with possible values including Full and Incremental.
|
||||
// +kubebuilder:validation:Enum=Full;Incremental
|
||||
type BackupType string
|
||||
|
||||
const (
|
||||
BackupTypeFull BackupType = "Full"
|
||||
BackupTypeIncremental BackupType = "Incremental"
|
||||
)
|
||||
|
||||
// BackupStatus captures the current status of a Velero backup.
|
||||
type BackupStatus struct {
|
||||
// Version is the backup format major version.
|
||||
|
||||
@@ -321,6 +321,11 @@ func (b *BackupBuilder) ParallelFilesUpload(parallel int) *BackupBuilder {
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *BackupBuilder) BackupType(backupType velerov1api.BackupType) *BackupBuilder {
|
||||
b.object.Spec.BackupType = backupType
|
||||
return b
|
||||
}
|
||||
|
||||
// WithStatus sets the Backup's status.
|
||||
func (b *BackupBuilder) WithStatus(status velerov1api.BackupStatus) *BackupBuilder {
|
||||
b.object.Status = status
|
||||
|
||||
@@ -108,6 +108,7 @@ type CreateOptions struct {
|
||||
ResPoliciesConfigmap string
|
||||
client kbclient.WithWatch
|
||||
ParallelFilesUpload int
|
||||
BackupType string
|
||||
}
|
||||
|
||||
func NewCreateOptions() *CreateOptions {
|
||||
@@ -156,6 +157,7 @@ func (o *CreateOptions) BindFlags(flags *pflag.FlagSet) {
|
||||
flags.StringVar(&o.ResPoliciesConfigmap, "resource-policies-configmap", "", "Reference to the resource policies configmap that backup should use")
|
||||
flags.StringVar(&o.DataMover, "data-mover", "", "Specify the data mover to be used by the backup. If the parameter is not set or set as 'velero', the built-in data mover will be used")
|
||||
flags.IntVar(&o.ParallelFilesUpload, "parallel-files-upload", 0, "Number of files uploads simultaneously when running a backup. This is only applicable for the kopia uploader")
|
||||
flags.StringVar(&o.BackupType, "backup-type", "", "Specify how volume data is backed up, with possible values including Full and Incremental.")
|
||||
}
|
||||
|
||||
// BindWait binds the wait flag separately so it is not called by other create
|
||||
@@ -217,6 +219,10 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto
|
||||
}
|
||||
}
|
||||
|
||||
if err := o.validateBackupType(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -231,6 +237,18 @@ func (o *CreateOptions) validateFromScheduleFlag(c *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CreateOptions) validateBackupType() error {
|
||||
backupType := strings.TrimSpace(o.BackupType)
|
||||
|
||||
switch backupType {
|
||||
case "", "Incremental", "Full":
|
||||
default:
|
||||
return fmt.Errorf("invalid backup type %s - valid values are 'Incremental', and 'Full'", backupType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *CreateOptions) Complete(args []string, f client.Factory) error {
|
||||
// If an explicit name is specified, use that name
|
||||
if len(args) > 0 {
|
||||
@@ -393,7 +411,8 @@ func (o *CreateOptions) BuildBackup(namespace string) (*velerov1api.Backup, erro
|
||||
VolumeSnapshotLocations(o.SnapshotLocations...).
|
||||
CSISnapshotTimeout(o.CSISnapshotTimeout).
|
||||
ItemOperationTimeout(o.ItemOperationTimeout).
|
||||
DataMover(o.DataMover)
|
||||
DataMover(o.DataMover).
|
||||
BackupType(velerov1api.BackupType(o.BackupType))
|
||||
if len(o.OrderedResources) > 0 {
|
||||
orders, err := ParseOrderedResources(o.OrderedResources)
|
||||
if err != nil {
|
||||
|
||||
@@ -122,6 +122,42 @@ func TestCreateOptions_ValidateFromScheduleFlag(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateOptions_ValidateBackupType(t *testing.T) {
|
||||
t.Run("valid backup types", func(t *testing.T) {
|
||||
o := NewCreateOptions()
|
||||
|
||||
o.BackupType = ""
|
||||
err := o.validateBackupType()
|
||||
require.NoError(t, err)
|
||||
|
||||
o.BackupType = "Incremental"
|
||||
err = o.validateBackupType()
|
||||
require.NoError(t, err)
|
||||
|
||||
o.BackupType = "Full"
|
||||
err = o.validateBackupType()
|
||||
require.NoError(t, err)
|
||||
|
||||
o.BackupType = " Incremental "
|
||||
err = o.validateBackupType()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("invalid backup type", func(t *testing.T) {
|
||||
o := NewCreateOptions()
|
||||
|
||||
o.BackupType = "incremental"
|
||||
err := o.validateBackupType()
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "invalid backup type incremental - valid values are 'Incremental', and 'Full'", err.Error())
|
||||
|
||||
o.BackupType = "invalid"
|
||||
err = o.validateBackupType()
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "invalid backup type invalid - valid values are 'Incremental', and 'Full'", err.Error())
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateOptions_BuildBackupFromSchedule(t *testing.T) {
|
||||
o := NewCreateOptions()
|
||||
o.FromSchedule = "test"
|
||||
@@ -231,6 +267,7 @@ func TestCreateCommand(t *testing.T) {
|
||||
resPoliciesConfigmap := "cm-name-2"
|
||||
dataMover := "velero"
|
||||
parallelFilesUpload := 10
|
||||
backupType := "Incremental"
|
||||
flags := new(flag.FlagSet)
|
||||
o := NewCreateOptions()
|
||||
o.BindFlags(flags)
|
||||
@@ -260,6 +297,7 @@ func TestCreateCommand(t *testing.T) {
|
||||
flags.Parse([]string{"--resource-policies-configmap", resPoliciesConfigmap})
|
||||
flags.Parse([]string{"--data-mover", dataMover})
|
||||
flags.Parse([]string{"--parallel-files-upload", strconv.Itoa(parallelFilesUpload)})
|
||||
flags.Parse([]string{"--backup-type", backupType})
|
||||
//flags.Parse([]string{"--wait"})
|
||||
|
||||
client := velerotest.NewFakeControllerRuntimeClient(t).(kbclient.WithWatch)
|
||||
@@ -310,6 +348,7 @@ func TestCreateCommand(t *testing.T) {
|
||||
require.Equal(t, resPoliciesConfigmap, o.ResPoliciesConfigmap)
|
||||
require.Equal(t, dataMover, o.DataMover)
|
||||
require.Equal(t, parallelFilesUpload, o.ParallelFilesUpload)
|
||||
require.Equal(t, backupType, o.BackupType)
|
||||
//assert.Equal(t, true, o.Wait)
|
||||
|
||||
// verify oldAndNewFilterParametersUsedTogether
|
||||
|
||||
@@ -410,6 +410,11 @@ func (b *backupReconciler) prepareBackupRequest(ctx context.Context, backup *vel
|
||||
request.Spec.ItemOperationTimeout.Duration = b.defaultItemOperationTimeout
|
||||
}
|
||||
|
||||
if len(request.Spec.BackupType) == 0 {
|
||||
// default backup type to incremental if not specified
|
||||
request.Spec.BackupType = velerov1api.BackupTypeIncremental
|
||||
}
|
||||
|
||||
// calculate expiration
|
||||
request.Status.Expiration = &metav1.Time{Time: b.clock.Now().Add(request.Spec.TTL.Duration)}
|
||||
|
||||
|
||||
@@ -524,6 +524,63 @@ func TestDefaultBackupTTL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareBackupRequest_SetBackupType(t *testing.T) {
|
||||
now, err := time.Parse(time.RFC1123Z, time.RFC1123Z)
|
||||
require.NoError(t, err)
|
||||
now = now.Local()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
backup *velerov1api.Backup
|
||||
expectedBackupType velerov1api.BackupType
|
||||
}{
|
||||
{
|
||||
name: "default backup type is Incremental",
|
||||
backup: defaultBackup().Result(),
|
||||
expectedBackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
{
|
||||
name: "backup type is set to Full",
|
||||
backup: defaultBackup().BackupType(velerov1api.BackupTypeFull).Result(),
|
||||
expectedBackupType: velerov1api.BackupTypeFull,
|
||||
},
|
||||
{
|
||||
name: "backup type is set to Incremental",
|
||||
backup: defaultBackup().BackupType(velerov1api.BackupTypeIncremental).Result(),
|
||||
expectedBackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
formatFlag := logging.FormatText
|
||||
var (
|
||||
fakeClient kbclient.Client
|
||||
logger = logging.DefaultLogger(logrus.DebugLevel, formatFlag)
|
||||
)
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
apiServer := velerotest.NewAPIServer(t)
|
||||
discoveryHelper, err := discovery.NewHelper(apiServer.DiscoveryClient, logger)
|
||||
require.NoError(t, err)
|
||||
// add the test's backup storage location if it's different than the default
|
||||
fakeClient = velerotest.NewFakeControllerRuntimeClient(t)
|
||||
c := &backupReconciler{
|
||||
logger: logger,
|
||||
discoveryHelper: discoveryHelper,
|
||||
kbClient: fakeClient,
|
||||
formatFlag: formatFlag,
|
||||
clock: testclocks.NewFakeClock(now),
|
||||
}
|
||||
|
||||
res := c.prepareBackupRequest(ctx, test.backup, logger)
|
||||
defer res.WorkerPool.Stop()
|
||||
assert.NotNil(t, res)
|
||||
|
||||
assert.Equal(t, test.expectedBackupType, res.Spec.BackupType)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareBackupRequest_SetsVGSLabelKey(t *testing.T) {
|
||||
now, err := time.Parse(time.RFC1123Z, time.RFC1123Z)
|
||||
require.NoError(t, err)
|
||||
@@ -746,6 +803,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -786,6 +844,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -830,6 +889,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -871,6 +931,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -912,6 +973,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -954,6 +1016,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -996,6 +1059,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1038,6 +1102,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1080,6 +1145,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1123,6 +1189,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFailed,
|
||||
@@ -1166,6 +1233,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFailed,
|
||||
@@ -1209,6 +1277,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1253,6 +1322,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1297,6 +1367,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1341,6 +1412,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1386,6 +1458,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.False(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1430,6 +1503,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
SnapshotMoveData: boolptr.True(),
|
||||
ExcludedClusterScopedResources: autoExcludeClusterScopedResources,
|
||||
ExcludedNamespaceScopedResources: autoExcludeNamespaceScopedResources,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1480,6 +1554,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
ExcludedClusterScopedResources: append([]string{"clusterroles"}, autoExcludeClusterScopedResources...),
|
||||
IncludedNamespaceScopedResources: []string{"pods"},
|
||||
ExcludedNamespaceScopedResources: append([]string{"secrets"}, autoExcludeNamespaceScopedResources...),
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
@@ -1530,6 +1605,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
||||
ExcludedClusterScopedResources: append([]string{"clusterroles"}, autoExcludeClusterScopedResources...),
|
||||
IncludedNamespaceScopedResources: []string{"pods"},
|
||||
ExcludedNamespaceScopedResources: append([]string{"secrets"}, autoExcludeNamespaceScopedResources...),
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
},
|
||||
Status: velerov1api.BackupStatus{
|
||||
Phase: velerov1api.BackupPhaseFinalizing,
|
||||
|
||||
@@ -178,6 +178,13 @@ spec:
|
||||
# processed. Only "exec" hooks are supported.
|
||||
post:
|
||||
# Same content as pre above.
|
||||
# BackupType specifies how volume data is backed up, with possible values including Full and Incremental.
|
||||
# BackupType is optional. If it's not set, it will default to Full.
|
||||
# BackupType is only meaningful for data mover backup, including CSI snapshot fs backup, CSI snapshot block backup, and fs backup.
|
||||
# For CSI only backup and Velero native backup, backupType doesn't take effect.
|
||||
# Full means data mover will forcefully upload all data in volumes.
|
||||
# Incremental means data mover will only upload data change since last snapshot.
|
||||
backupType: Full
|
||||
# Status about the Backup. Users should not set any data here.
|
||||
status:
|
||||
# The version of this Backup. The only version supported is 1.
|
||||
|
||||
Reference in New Issue
Block a user