mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-09-13 03:24:39 +00:00
Merge branch 'main' into report-incremental-fallback
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Add block data mover support for Velero backup/restore describe CLI.
|
||||
@@ -29,13 +29,14 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/label"
|
||||
|
||||
veleroshared "github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
|
||||
"github.com/vmware-tanzu/velero/pkg/datamover"
|
||||
"github.com/vmware-tanzu/velero/pkg/features"
|
||||
"github.com/vmware-tanzu/velero/pkg/itemoperation"
|
||||
"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
"github.com/vmware-tanzu/velero/pkg/label"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/stringptr"
|
||||
)
|
||||
|
||||
@@ -89,11 +90,14 @@ type BackupVolumeInfo struct {
|
||||
// Whether the volume data is backed up successfully.
|
||||
Result VolumeResult `json:"result,omitempty"`
|
||||
|
||||
CSISnapshotInfo *CSISnapshotInfo `json:"csiSnapshotInfo,omitempty"`
|
||||
SnapshotDataMovementInfo *SnapshotDataMovementInfo `json:"snapshotDataMovementInfo,omitempty"`
|
||||
NativeSnapshotInfo *NativeSnapshotInfo `json:"nativeSnapshotInfo,omitempty"`
|
||||
PVBInfo *PodVolumeInfo `json:"pvbInfo,omitempty"`
|
||||
PVInfo *PVInfo `json:"pvInfo,omitempty"`
|
||||
// How volume data is backed up, with possible values including Full and Incremental.
|
||||
BackupType velerov1api.BackupType `json:"backupType,omitempty"`
|
||||
|
||||
CSISnapshotInfo *CSISnapshotInfo `json:"csiSnapshotInfo,omitempty"`
|
||||
SnapshotDataMovementInfo *BackupSnapshotDataMovementInfo `json:"snapshotDataMovementInfo,omitempty"`
|
||||
NativeSnapshotInfo *NativeSnapshotInfo `json:"nativeSnapshotInfo,omitempty"`
|
||||
PVBInfo *PodVolumeBackupInfo `json:"pvbInfo,omitempty"`
|
||||
PVInfo *PVInfo `json:"pvInfo,omitempty"`
|
||||
}
|
||||
|
||||
type VolumeResult string
|
||||
@@ -122,10 +126,10 @@ type RestoreVolumeInfo struct {
|
||||
// Whether the volume's data are restored via data movement
|
||||
SnapshotDataMoved bool `json:"snapshotDataMoved"`
|
||||
|
||||
CSISnapshotInfo *CSISnapshotInfo `json:"csiSnapshotInfo,omitempty"`
|
||||
SnapshotDataMovementInfo *SnapshotDataMovementInfo `json:"snapshotDataMovementInfo,omitempty"`
|
||||
NativeSnapshotInfo *NativeSnapshotInfo `json:"nativeSnapshotInfo,omitempty"`
|
||||
PVRInfo *PodVolumeInfo `json:"pvrInfo,omitempty"`
|
||||
CSISnapshotInfo *CSISnapshotInfo `json:"csiSnapshotInfo,omitempty"`
|
||||
SnapshotDataMovementInfo *RestoreSnapshotDataMovementInfo `json:"snapshotDataMovementInfo,omitempty"`
|
||||
NativeSnapshotInfo *NativeSnapshotInfo `json:"nativeSnapshotInfo,omitempty"`
|
||||
PVRInfo *PodVolumeRestoreInfo `json:"pvrInfo,omitempty"`
|
||||
}
|
||||
|
||||
// CSISnapshotInfo is used for displaying the CSI snapshot status
|
||||
@@ -146,15 +150,15 @@ type CSISnapshotInfo struct {
|
||||
OperationID string `json:"operationID,omitempty"`
|
||||
|
||||
// The VolumeSnapshot's Status.ReadyToUse value
|
||||
ReadyToUse *bool
|
||||
ReadyToUse *bool `json:"readyToUse,omitempty"`
|
||||
|
||||
// The VolumeGroupSnapshotHandle from VSC status, used to create stub VGSC during restore
|
||||
// for CSI drivers that populate this field (e.g., Ceph RBD).
|
||||
VolumeGroupSnapshotHandle string `json:"volumeGroupSnapshotHandle,omitempty"`
|
||||
}
|
||||
|
||||
// SnapshotDataMovementInfo is used for displaying the snapshot data mover status.
|
||||
type SnapshotDataMovementInfo struct {
|
||||
// BackupSnapshotDataMovementInfo is used for displaying the backup snapshot data mover status.
|
||||
type BackupSnapshotDataMovementInfo struct {
|
||||
// The data mover used by the backup. The valid values are `velero` and ``(equals to `velero`).
|
||||
DataMover string `json:"dataMover"`
|
||||
|
||||
@@ -181,8 +185,49 @@ type SnapshotDataMovementInfo struct {
|
||||
// incremental and must stay distinguishable from "unknown".
|
||||
IncrementalSize *int64 `json:"incrementalSize,omitempty"`
|
||||
|
||||
// ParentSnapshot specifies the parent snapshot that current backup is based on.
|
||||
// If its value is "" or "auto", the data mover finds the recent backup of the same volume as parent.
|
||||
// If its value is "none", the data mover will do a full backup
|
||||
// If its value is a specific snapshotID, the data mover finds the specific snapshot as parent.
|
||||
ParentSnapshot string `json:"parentSnapshot,omitempty"`
|
||||
|
||||
// The DataUpload's Status.Phase value
|
||||
Phase velerov2alpha1.DataUploadPhase
|
||||
Phase velerov2alpha1.DataUploadPhase `json:"phase"`
|
||||
}
|
||||
|
||||
// RestoreSnapshotDataMovementInfo is used for displaying the restore snapshot data mover status.
|
||||
type RestoreSnapshotDataMovementInfo struct {
|
||||
// The data mover used by the backup. The valid values are `velero` and ``(equals to `velero`).
|
||||
DataMover string `json:"dataMover"`
|
||||
|
||||
// The type of the uploader that uploads the snapshot data. The valid values are `kopia` and `restic`.
|
||||
UploaderType string `json:"uploaderType"`
|
||||
|
||||
// The name or ID of the snapshot associated object(SAO).
|
||||
// SAO is used to support local snapshots for the snapshot data mover,
|
||||
// e.g. it could be a VolumeSnapshot for CSI snapshot data movement.
|
||||
RetainedSnapshot string `json:"retainedSnapshot,omitempty"`
|
||||
|
||||
// It's the filesystem repository's snapshot ID.
|
||||
SnapshotHandle string `json:"snapshotHandle"`
|
||||
|
||||
// The Async Operation's ID.
|
||||
OperationID string `json:"operationID"`
|
||||
|
||||
// Moved snapshot data size.
|
||||
Size int64 `json:"size"`
|
||||
|
||||
// Moved snapshot incremental size, i.e. the bytes actually transferred. Nil means
|
||||
// the uploader reported no figure (including backups taken before this was
|
||||
// recorded); a pointer to 0 means it transferred nothing, which is the ideal
|
||||
// incremental and must stay distinguishable from "unknown".
|
||||
IncrementalSize *int64 `json:"incrementalSize,omitempty"`
|
||||
|
||||
// The DataDownload's Status.Phase value
|
||||
Phase velerov2alpha1.DataDownloadPhase `json:"phase"`
|
||||
|
||||
// Indicates the type of the restore, incremental or full.
|
||||
RestoreType string `json:"restoreType,omitempty"`
|
||||
}
|
||||
|
||||
// NativeSnapshotInfo is used for displaying the Velero native snapshot status.
|
||||
@@ -203,7 +248,7 @@ type NativeSnapshotInfo struct {
|
||||
IOPS string `json:"iops"`
|
||||
|
||||
// The NativeSnapshot's Status.Phase value
|
||||
Phase SnapshotPhase
|
||||
Phase SnapshotPhase `json:"phase,omitempty"`
|
||||
}
|
||||
|
||||
func newNativeSnapshotInfo(s *Snapshot) *NativeSnapshotInfo {
|
||||
@@ -220,9 +265,9 @@ func newNativeSnapshotInfo(s *Snapshot) *NativeSnapshotInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// PodVolumeInfo is used for displaying the PodVolumeBackup/PodVolumeRestore snapshot status.
|
||||
type PodVolumeInfo struct {
|
||||
// It's the file-system uploader's snapshot ID for PodVolumeBackup/PodVolumeRestore.
|
||||
// PodVolumeBackupInfo is used for displaying the PodVolumeBackup snapshot status.
|
||||
type PodVolumeBackupInfo struct {
|
||||
// It's the file-system uploader's snapshot ID for PodVolumeBackup.
|
||||
SnapshotHandle string `json:"snapshotHandle,omitempty"`
|
||||
|
||||
// The snapshot corresponding volume size.
|
||||
@@ -250,11 +295,47 @@ type PodVolumeInfo struct {
|
||||
NodeName string `json:"nodeName,omitempty"`
|
||||
|
||||
// The PVB's Status.Phase value
|
||||
Phase velerov1api.PodVolumeBackupPhase
|
||||
Phase velerov1api.PodVolumeBackupPhase `json:"phase,omitempty"`
|
||||
}
|
||||
|
||||
func newPodVolumeInfoFromPVB(pvb *velerov1api.PodVolumeBackup) *PodVolumeInfo {
|
||||
return &PodVolumeInfo{
|
||||
// PodVolumeRestoreInfo is used for displaying the PodVolumeRestore snapshot status.
|
||||
type PodVolumeRestoreInfo struct {
|
||||
// It's the file-system uploader's snapshot ID for PodVolumeRestore.
|
||||
SnapshotHandle string `json:"snapshotHandle,omitempty"`
|
||||
|
||||
// The snapshot corresponding volume size.
|
||||
Size int64 `json:"size,omitempty"`
|
||||
|
||||
// The incremental snapshot size, i.e. the bytes actually transferred. Nil means
|
||||
// the uploader reported no figure; a pointer to 0 means it transferred nothing.
|
||||
IncrementalSize *int64 `json:"incrementalSize,omitempty"`
|
||||
|
||||
// The type of the uploader that uploads the data. The valid values are `kopia` and `restic`.
|
||||
UploaderType string `json:"uploaderType"`
|
||||
|
||||
// The PVC's corresponding volume name used by Pod
|
||||
// https://github.com/kubernetes/kubernetes/blob/e4b74dd12fa8cb63c174091d5536a10b8ec19d34/pkg/apis/core/types.go#L48
|
||||
VolumeName string `json:"volumeName"`
|
||||
|
||||
// The Pod name mounting this PVC.
|
||||
PodName string `json:"podName"`
|
||||
|
||||
// The Pod namespace
|
||||
PodNamespace string `json:"podNamespace"`
|
||||
|
||||
// The PVB-taken k8s node's name.
|
||||
// This field will be empty when the struct is used to represent a podvolumerestore.
|
||||
NodeName string `json:"nodeName,omitempty"`
|
||||
|
||||
// The PVR's Status.Phase value
|
||||
Phase velerov1api.PodVolumeRestorePhase `json:"phase,omitempty"`
|
||||
|
||||
// Indicates the type of the restore, incremental or full.
|
||||
RestoreType string `json:"restoreType,omitempty"`
|
||||
}
|
||||
|
||||
func newPodVolumeInfoFromPVB(pvb *velerov1api.PodVolumeBackup) *PodVolumeBackupInfo {
|
||||
return &PodVolumeBackupInfo{
|
||||
SnapshotHandle: pvb.Status.SnapshotID,
|
||||
Size: pvb.Status.Progress.TotalBytes,
|
||||
IncrementalSize: pvb.Status.IncrementalBytes,
|
||||
@@ -267,14 +348,16 @@ func newPodVolumeInfoFromPVB(pvb *velerov1api.PodVolumeBackup) *PodVolumeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
func newPodVolumeInfoFromPVR(pvr *velerov1api.PodVolumeRestore) *PodVolumeInfo {
|
||||
return &PodVolumeInfo{
|
||||
func newPodVolumeInfoFromPVR(pvr *velerov1api.PodVolumeRestore) *PodVolumeRestoreInfo {
|
||||
return &PodVolumeRestoreInfo{
|
||||
SnapshotHandle: pvr.Spec.SnapshotID,
|
||||
Size: pvr.Status.Progress.TotalBytes,
|
||||
UploaderType: pvr.Spec.UploaderType,
|
||||
VolumeName: pvr.Spec.Volume,
|
||||
PodName: pvr.Spec.Pod.Name,
|
||||
PodNamespace: pvr.Spec.Pod.Namespace,
|
||||
Phase: pvr.Status.Phase,
|
||||
RestoreType: pvr.Spec.RestoreType,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,6 +553,11 @@ func (v *BackupVolumesInformation) generateVolumeInfoForCSIVolumeSnapshot() {
|
||||
volumeGroupSnapshotHandle = *volumeSnapshotContent.Status.VolumeGroupSnapshotHandle
|
||||
}
|
||||
if pvcPVInfo := v.pvMap.retrieve("", *volumeSnapshot.Spec.Source.PersistentVolumeClaimName, volumeSnapshot.Namespace); pvcPVInfo != nil {
|
||||
volumeResult := VolumeResultFailed
|
||||
if volumeSnapshot.Status != nil && volumeSnapshot.Status.ReadyToUse != nil && *volumeSnapshot.Status.ReadyToUse {
|
||||
volumeResult = VolumeResultSucceeded
|
||||
}
|
||||
|
||||
volumeInfo := &BackupVolumeInfo{
|
||||
BackupMethod: CSISnapshot,
|
||||
PVCName: pvcPVInfo.PVCName,
|
||||
@@ -478,6 +566,7 @@ func (v *BackupVolumesInformation) generateVolumeInfoForCSIVolumeSnapshot() {
|
||||
Skipped: false,
|
||||
SnapshotDataMoved: false,
|
||||
PreserveLocalSnapshot: true,
|
||||
Result: volumeResult,
|
||||
CSISnapshotInfo: &CSISnapshotInfo{
|
||||
VSCName: *volumeSnapshot.Status.BoundVolumeSnapshotContentName,
|
||||
Size: size,
|
||||
@@ -519,6 +608,11 @@ func (v *BackupVolumesInformation) generateVolumeInfoFromPVB() {
|
||||
StartTimestamp: pvb.Status.StartTimestamp,
|
||||
CompletionTimestamp: pvb.Status.CompletionTimestamp,
|
||||
PVBInfo: newPodVolumeInfoFromPVB(pvb),
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
}
|
||||
|
||||
if pvb.Spec.ParentSnapshot == veleroshared.ParentSnapshotNone {
|
||||
volumeInfo.BackupType = velerov1api.BackupTypeFull
|
||||
}
|
||||
|
||||
// Only set Succeeded to true when the PVB's phase is Completed.
|
||||
@@ -622,6 +716,11 @@ func (v *BackupVolumesInformation) generateVolumeInfoFromDataUpload() {
|
||||
dataMover = dataUpload.Spec.DataMover
|
||||
}
|
||||
|
||||
volumeResult := VolumeResultFailed
|
||||
if dataUpload.Status.Phase == velerov2alpha1.DataUploadPhaseCompleted {
|
||||
volumeResult = VolumeResultSucceeded
|
||||
}
|
||||
|
||||
volumeInfo := &BackupVolumeInfo{
|
||||
BackupMethod: CSISnapshot,
|
||||
PVCName: pvcPVInfo.PVCName,
|
||||
@@ -629,17 +728,22 @@ func (v *BackupVolumesInformation) generateVolumeInfoFromDataUpload() {
|
||||
PVName: pvcPVInfo.PV.Name,
|
||||
SnapshotDataMoved: true,
|
||||
Skipped: false,
|
||||
Result: volumeResult,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
CSISnapshotInfo: &CSISnapshotInfo{
|
||||
SnapshotHandle: FieldValueIsUnknown,
|
||||
VSCName: FieldValueIsUnknown,
|
||||
OperationID: FieldValueIsUnknown,
|
||||
Driver: dataUpload.Spec.CSISnapshot.Driver,
|
||||
},
|
||||
SnapshotDataMovementInfo: &SnapshotDataMovementInfo{
|
||||
DataMover: dataMover,
|
||||
UploaderType: velerov1api.BackupRepositoryTypeKopia,
|
||||
OperationID: operation.Spec.OperationID,
|
||||
Phase: dataUpload.Status.Phase,
|
||||
SnapshotDataMovementInfo: &BackupSnapshotDataMovementInfo{
|
||||
DataMover: dataMover,
|
||||
UploaderType: datamover.GetUploaderType(dataMover),
|
||||
OperationID: operation.Spec.OperationID,
|
||||
Phase: dataUpload.Status.Phase,
|
||||
ParentSnapshot: dataUpload.Spec.ParentSnapshot,
|
||||
Size: dataUpload.Status.Progress.TotalBytes,
|
||||
SnapshotHandle: dataUpload.Status.SnapshotID,
|
||||
},
|
||||
PVInfo: &PVInfo{
|
||||
ReclaimPolicy: string(pvcPVInfo.PV.Spec.PersistentVolumeReclaimPolicy),
|
||||
@@ -647,10 +751,22 @@ func (v *BackupVolumesInformation) generateVolumeInfoFromDataUpload() {
|
||||
},
|
||||
}
|
||||
|
||||
if dataUpload.Spec.ParentSnapshot == veleroshared.ParentSnapshotNone {
|
||||
volumeInfo.BackupType = velerov1api.BackupTypeFull
|
||||
}
|
||||
|
||||
if dataUpload.Status.StartTimestamp != nil {
|
||||
volumeInfo.StartTimestamp = dataUpload.Status.StartTimestamp
|
||||
}
|
||||
|
||||
if dataUpload.Status.CompletionTimestamp != nil {
|
||||
volumeInfo.CompletionTimestamp = dataUpload.Status.CompletionTimestamp
|
||||
}
|
||||
|
||||
if dataUpload.Status.IncrementalBytes != nil {
|
||||
volumeInfo.SnapshotDataMovementInfo.IncrementalSize = dataUpload.Status.IncrementalBytes
|
||||
}
|
||||
|
||||
tmpVolumeInfos = append(tmpVolumeInfos, volumeInfo)
|
||||
} else {
|
||||
v.logger.Warnf("Cannot find info for PVC %s/%s", operation.Spec.ResourceIdentifier.Namespace, operation.Spec.ResourceIdentifier.Name)
|
||||
@@ -878,14 +994,21 @@ func (t *RestoreVolumeInfoTracker) Result() []*RestoreVolumeInfo {
|
||||
// the datadownload was initiated in CSI plugin
|
||||
// For the same reason, no CSI snapshot info will be populated into volumeInfo
|
||||
RestoreMethod: CSISnapshot,
|
||||
SnapshotDataMovementInfo: &SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &RestoreSnapshotDataMovementInfo{
|
||||
DataMover: dataMover,
|
||||
UploaderType: velerov1api.BackupRepositoryTypeKopia,
|
||||
UploaderType: datamover.GetUploaderType(dataMover),
|
||||
SnapshotHandle: dd.Spec.SnapshotID,
|
||||
OperationID: operationID,
|
||||
RestoreType: dd.Spec.RestoreType,
|
||||
Size: dd.Status.Progress.TotalBytes,
|
||||
Phase: dd.Status.Phase,
|
||||
},
|
||||
}
|
||||
|
||||
if dd.Status.IncrementalBytes != nil {
|
||||
volumeInfo.SnapshotDataMovementInfo.IncrementalSize = dd.Status.IncrementalBytes
|
||||
}
|
||||
|
||||
volumeInfos = append(volumeInfos, volumeInfo)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package volume
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -30,7 +31,9 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
veleroshared "github.com/vmware-tanzu/velero/pkg/apis/velero/shared"
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
@@ -474,6 +477,7 @@ func TestGenerateVolumeInfoForCSIVolumeSnapshot(t *testing.T) {
|
||||
PVCNamespace: "velero",
|
||||
PVName: "testPV",
|
||||
BackupMethod: CSISnapshot,
|
||||
Result: VolumeResultSucceeded,
|
||||
StartTimestamp: &now,
|
||||
PreserveLocalSnapshot: true,
|
||||
CSISnapshotInfo: &CSISnapshotInfo{
|
||||
@@ -562,8 +566,9 @@ func TestGenerateVolumeInfoFromPVB(t *testing.T) {
|
||||
PVCNamespace: "",
|
||||
PVName: "",
|
||||
BackupMethod: PodVolumeBackup,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
Result: VolumeResultFailed,
|
||||
PVBInfo: &PodVolumeInfo{
|
||||
PVBInfo: &PodVolumeBackupInfo{
|
||||
PodName: "testPod",
|
||||
PodNamespace: "velero",
|
||||
},
|
||||
@@ -641,10 +646,11 @@ func TestGenerateVolumeInfoFromPVB(t *testing.T) {
|
||||
PVCNamespace: "velero",
|
||||
PVName: "testPV",
|
||||
BackupMethod: PodVolumeBackup,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
StartTimestamp: &now,
|
||||
CompletionTimestamp: &now,
|
||||
Result: VolumeResultFailed,
|
||||
PVBInfo: &PodVolumeInfo{
|
||||
PVBInfo: &PodVolumeBackupInfo{
|
||||
PodName: "testPod",
|
||||
PodNamespace: "velero",
|
||||
Phase: velerov1api.PodVolumeBackupPhaseFailed,
|
||||
@@ -704,10 +710,11 @@ func TestGenerateVolumeInfoFromPVB(t *testing.T) {
|
||||
PVCNamespace: "velero",
|
||||
PVName: "testPV",
|
||||
BackupMethod: PodVolumeBackup,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
StartTimestamp: &now,
|
||||
CompletionTimestamp: &now,
|
||||
Result: VolumeResultSucceeded,
|
||||
PVBInfo: &PodVolumeInfo{
|
||||
PVBInfo: &PodVolumeBackupInfo{
|
||||
PodName: "testPod",
|
||||
PodNamespace: "velero",
|
||||
Phase: velerov1api.PodVolumeBackupPhaseCompleted,
|
||||
@@ -838,6 +845,9 @@ func TestGenerateVolumeInfoFromDataUpload(t *testing.T) {
|
||||
Driver: "pd.csi.storage.gke.io",
|
||||
}).SnapshotID("testSnapshotHandle").
|
||||
StartTimestamp(&now).
|
||||
CompletionTimestamp(&now).
|
||||
TotalBytes(1024).
|
||||
IncrementalBytes(512).
|
||||
Phase(velerov2alpha1.DataUploadPhaseCompleted).
|
||||
Result(),
|
||||
vs: builder.ForVolumeSnapshot(velerov1api.DefaultNamespace, "vs-01").Status().BoundVolumeSnapshotContentName("vsc-01").Result(),
|
||||
@@ -882,12 +892,15 @@ func TestGenerateVolumeInfoFromDataUpload(t *testing.T) {
|
||||
},
|
||||
expectedVolumeInfos: []*BackupVolumeInfo{
|
||||
{
|
||||
PVCName: "testPVC",
|
||||
PVCNamespace: "velero",
|
||||
PVName: "testPV",
|
||||
BackupMethod: CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
StartTimestamp: &now,
|
||||
PVCName: "testPVC",
|
||||
PVCNamespace: "velero",
|
||||
PVName: "testPV",
|
||||
BackupMethod: CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
Result: VolumeResultSucceeded,
|
||||
StartTimestamp: &now,
|
||||
CompletionTimestamp: &now,
|
||||
CSISnapshotInfo: &CSISnapshotInfo{
|
||||
VSCName: FieldValueIsUnknown,
|
||||
SnapshotHandle: FieldValueIsUnknown,
|
||||
@@ -895,11 +908,14 @@ func TestGenerateVolumeInfoFromDataUpload(t *testing.T) {
|
||||
Size: 0,
|
||||
Driver: "pd.csi.storage.gke.io",
|
||||
},
|
||||
SnapshotDataMovementInfo: &SnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
OperationID: "testOperation",
|
||||
Phase: velerov2alpha1.DataUploadPhaseCompleted,
|
||||
SnapshotDataMovementInfo: &BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
OperationID: "testOperation",
|
||||
Phase: velerov2alpha1.DataUploadPhaseCompleted,
|
||||
SnapshotHandle: "testSnapshotHandle",
|
||||
Size: 1024,
|
||||
IncrementalSize: ptr.To(int64(512)),
|
||||
},
|
||||
PVInfo: &PVInfo{
|
||||
ReclaimPolicy: string(corev1api.PersistentVolumeReclaimDelete),
|
||||
@@ -947,6 +963,19 @@ func TestGenerateVolumeInfoFromDataUpload(t *testing.T) {
|
||||
require.Equal(t, tc.expectedVolumeInfos[0].PVInfo, volumesInfo.volumeInfos[0].PVInfo)
|
||||
require.Equal(t, tc.expectedVolumeInfos[0].SnapshotDataMovementInfo, volumesInfo.volumeInfos[0].SnapshotDataMovementInfo)
|
||||
require.Equal(t, tc.expectedVolumeInfos[0].CSISnapshotInfo, volumesInfo.volumeInfos[0].CSISnapshotInfo)
|
||||
require.Equal(t, tc.expectedVolumeInfos[0].Result, volumesInfo.volumeInfos[0].Result)
|
||||
if tc.expectedVolumeInfos[0].StartTimestamp != nil {
|
||||
require.NotNil(t, volumesInfo.volumeInfos[0].StartTimestamp)
|
||||
require.True(t, tc.expectedVolumeInfos[0].StartTimestamp.Equal(volumesInfo.volumeInfos[0].StartTimestamp))
|
||||
} else {
|
||||
require.Nil(t, volumesInfo.volumeInfos[0].StartTimestamp)
|
||||
}
|
||||
if tc.expectedVolumeInfos[0].CompletionTimestamp != nil {
|
||||
require.NotNil(t, volumesInfo.volumeInfos[0].CompletionTimestamp)
|
||||
require.True(t, tc.expectedVolumeInfos[0].CompletionTimestamp.Equal(volumesInfo.volumeInfos[0].CompletionTimestamp))
|
||||
} else {
|
||||
require.Nil(t, volumesInfo.volumeInfos[0].CompletionTimestamp)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1057,7 +1086,7 @@ func TestRestoreVolumeInfoResult(t *testing.T) {
|
||||
PVName: "testPV2",
|
||||
RestoreMethod: PodVolumeRestore,
|
||||
SnapshotDataMoved: false,
|
||||
PVRInfo: &PodVolumeInfo{
|
||||
PVRInfo: &PodVolumeRestoreInfo{
|
||||
SnapshotHandle: "pvr-snap-001",
|
||||
PodName: "testPod",
|
||||
PodNamespace: "testNS",
|
||||
@@ -1127,7 +1156,7 @@ func TestRestoreVolumeInfoResult(t *testing.T) {
|
||||
PVName: "testPV2",
|
||||
RestoreMethod: PodVolumeRestore,
|
||||
SnapshotDataMoved: false,
|
||||
PVRInfo: &PodVolumeInfo{
|
||||
PVRInfo: &PodVolumeRestoreInfo{
|
||||
SnapshotHandle: "pvr-snap-001",
|
||||
PodName: "testPod",
|
||||
PodNamespace: "testNS",
|
||||
@@ -1182,6 +1211,9 @@ func TestRestoreVolumeInfoResult(t *testing.T) {
|
||||
PVC: "testPVC",
|
||||
Namespace: "testNS",
|
||||
}).
|
||||
Phase(velerov2alpha1.DataDownloadPhaseCompleted).
|
||||
Progress(veleroshared.DataMoveOperationProgress{TotalBytes: 2048}).
|
||||
RestoreType("Incremental").
|
||||
Result(),
|
||||
*builder.ForDataDownload("velero", "testDataDownload-2").
|
||||
ObjectMeta(builder.WithLabels(velerov1api.AsyncOperationIDLabel, "dd-operation-002")).
|
||||
@@ -1190,6 +1222,9 @@ func TestRestoreVolumeInfoResult(t *testing.T) {
|
||||
PVC: "testPVC2",
|
||||
Namespace: "testNS",
|
||||
}).
|
||||
Phase(velerov2alpha1.DataDownloadPhaseCompleted).
|
||||
Progress(veleroshared.DataMoveOperationProgress{TotalBytes: 4096}).
|
||||
RestoreType("Full").
|
||||
Result(),
|
||||
},
|
||||
},
|
||||
@@ -1202,11 +1237,14 @@ func TestRestoreVolumeInfoResult(t *testing.T) {
|
||||
PVName: "testPV",
|
||||
RestoreMethod: CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &RestoreSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: velerov1api.BackupRepositoryTypeKopia,
|
||||
SnapshotHandle: "dd-snap-001",
|
||||
OperationID: "dd-operation-001",
|
||||
Phase: velerov2alpha1.DataDownloadPhaseCompleted,
|
||||
Size: 2048,
|
||||
RestoreType: "Incremental",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -1215,11 +1253,14 @@ func TestRestoreVolumeInfoResult(t *testing.T) {
|
||||
PVName: "testPV2",
|
||||
RestoreMethod: CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &RestoreSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: velerov1api.BackupRepositoryTypeKopia,
|
||||
SnapshotHandle: "dd-snap-002",
|
||||
OperationID: "dd-operation-002",
|
||||
Phase: velerov2alpha1.DataDownloadPhaseCompleted,
|
||||
Size: 4096,
|
||||
RestoreType: "Full",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1262,3 +1303,174 @@ func TestGetVolumeSnapshotClasses(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []snapshotv1api.VolumeSnapshotClass{*class}, result)
|
||||
}
|
||||
|
||||
func TestBackupVolumeInfoJSONRoundTrip(t *testing.T) {
|
||||
orig := BackupVolumeInfo{
|
||||
PVCName: "pvc-1",
|
||||
PVCNamespace: "ns-1",
|
||||
PVName: "pv-1",
|
||||
BackupMethod: CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
PreserveLocalSnapshot: false,
|
||||
Skipped: false,
|
||||
Result: VolumeResultSucceeded,
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
CSISnapshotInfo: &CSISnapshotInfo{
|
||||
SnapshotHandle: "csi-snap-1",
|
||||
Size: 2000,
|
||||
Driver: "csi.driver.com",
|
||||
VSCName: "vsc-1",
|
||||
OperationID: "op-2",
|
||||
VolumeGroupSnapshotHandle: "vgsh-1",
|
||||
},
|
||||
SnapshotDataMovementInfo: &BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
RetainedSnapshot: "retain-1",
|
||||
SnapshotHandle: "snap-1",
|
||||
OperationID: "op-1",
|
||||
Size: 1000,
|
||||
IncrementalSize: int64Ptr(200),
|
||||
ParentSnapshot: "parent-1",
|
||||
Phase: velerov2alpha1.DataUploadPhaseCompleted,
|
||||
},
|
||||
NativeSnapshotInfo: &NativeSnapshotInfo{
|
||||
SnapshotHandle: "native-snap-1",
|
||||
VolumeType: "gp3",
|
||||
VolumeAZ: "us-west-2a",
|
||||
IOPS: "3000",
|
||||
},
|
||||
PVBInfo: &PodVolumeBackupInfo{
|
||||
SnapshotHandle: "pvb-snap-1",
|
||||
Size: 500,
|
||||
IncrementalSize: int64Ptr(50),
|
||||
UploaderType: "kopia",
|
||||
VolumeName: "vol-1",
|
||||
PodName: "pod-1",
|
||||
PodNamespace: "ns-1",
|
||||
NodeName: "node-1",
|
||||
Phase: velerov1api.PodVolumeBackupPhaseCompleted,
|
||||
},
|
||||
PVInfo: &PVInfo{
|
||||
ReclaimPolicy: "Delete",
|
||||
Labels: map[string]string{"env": "test"},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonStr := string(data)
|
||||
assert.Contains(t, jsonStr, `"pvcName":"pvc-1"`)
|
||||
assert.Contains(t, jsonStr, `"pvcNamespace":"ns-1"`)
|
||||
assert.Contains(t, jsonStr, `"pvName":"pv-1"`)
|
||||
assert.Contains(t, jsonStr, `"backupMethod":"CSISnapshot"`)
|
||||
assert.Contains(t, jsonStr, `"snapshotDataMoved":true`)
|
||||
assert.Contains(t, jsonStr, `"result":"succeeded"`)
|
||||
assert.Contains(t, jsonStr, `"backupType":"Incremental"`)
|
||||
assert.Contains(t, jsonStr, `"snapshotDataMovementInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"dataMover":"velero"`)
|
||||
assert.Contains(t, jsonStr, `"uploaderType":"kopia"`)
|
||||
assert.Contains(t, jsonStr, `"retainedSnapshot":"retain-1"`)
|
||||
assert.Contains(t, jsonStr, `"snapshotHandle":"snap-1"`)
|
||||
assert.Contains(t, jsonStr, `"operationID":"op-1"`)
|
||||
assert.Contains(t, jsonStr, `"size":1000`)
|
||||
assert.Contains(t, jsonStr, `"incrementalSize":200`)
|
||||
assert.Contains(t, jsonStr, `"parentSnapshot":"parent-1"`)
|
||||
assert.Contains(t, jsonStr, `"phase":"Completed"`)
|
||||
assert.Contains(t, jsonStr, `"pvbInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"podName":"pod-1"`)
|
||||
assert.Contains(t, jsonStr, `"podNamespace":"ns-1"`)
|
||||
assert.Contains(t, jsonStr, `"nodeName":"node-1"`)
|
||||
assert.Contains(t, jsonStr, `"csiSnapshotInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"driver":"csi.driver.com"`)
|
||||
assert.Contains(t, jsonStr, `"vscName":"vsc-1"`)
|
||||
assert.Contains(t, jsonStr, `"volumeGroupSnapshotHandle":"vgsh-1"`)
|
||||
assert.Contains(t, jsonStr, `"nativeSnapshotInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"volumeType":"gp3"`)
|
||||
assert.Contains(t, jsonStr, `"volumeAZ":"us-west-2a"`)
|
||||
assert.Contains(t, jsonStr, `"iops":"3000"`)
|
||||
assert.Contains(t, jsonStr, `"pvInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"reclaimPolicy":"Delete"`)
|
||||
|
||||
var unmarshaled BackupVolumeInfo
|
||||
err = json.Unmarshal(data, &unmarshaled)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, orig, unmarshaled)
|
||||
}
|
||||
|
||||
func TestRestoreVolumeInfoJSONRoundTrip(t *testing.T) {
|
||||
orig := RestoreVolumeInfo{
|
||||
PVCName: "pvc-2",
|
||||
PVCNamespace: "ns-2",
|
||||
PVName: "pv-2",
|
||||
RestoreMethod: CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &RestoreSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
RetainedSnapshot: "retain-2",
|
||||
SnapshotHandle: "snap-2",
|
||||
OperationID: "op-3",
|
||||
Size: 3000,
|
||||
IncrementalSize: int64Ptr(300),
|
||||
Phase: velerov2alpha1.DataDownloadPhaseCompleted,
|
||||
RestoreType: "Incremental",
|
||||
},
|
||||
PVRInfo: &PodVolumeRestoreInfo{
|
||||
SnapshotHandle: "pvr-snap-1",
|
||||
Size: 600,
|
||||
IncrementalSize: int64Ptr(60),
|
||||
UploaderType: "kopia",
|
||||
VolumeName: "vol-2",
|
||||
PodName: "pod-2",
|
||||
PodNamespace: "ns-2",
|
||||
NodeName: "node-2",
|
||||
Phase: velerov1api.PodVolumeRestorePhaseCompleted,
|
||||
RestoreType: "Incremental",
|
||||
},
|
||||
CSISnapshotInfo: &CSISnapshotInfo{
|
||||
SnapshotHandle: "csi-snap-2",
|
||||
Size: 4000,
|
||||
Driver: "csi.driver.com",
|
||||
VSCName: "vsc-2",
|
||||
},
|
||||
NativeSnapshotInfo: &NativeSnapshotInfo{
|
||||
SnapshotHandle: "native-snap-2",
|
||||
VolumeType: "ebs",
|
||||
VolumeAZ: "us-east-1a",
|
||||
IOPS: "1000",
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(orig)
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonStr := string(data)
|
||||
assert.Contains(t, jsonStr, `"pvcName":"pvc-2"`)
|
||||
assert.Contains(t, jsonStr, `"pvcNamespace":"ns-2"`)
|
||||
assert.Contains(t, jsonStr, `"pvName":"pv-2"`)
|
||||
assert.Contains(t, jsonStr, `"restoreMethod":"CSISnapshot"`)
|
||||
assert.Contains(t, jsonStr, `"snapshotDataMoved":true`)
|
||||
assert.Contains(t, jsonStr, `"snapshotDataMovementInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"dataMover":"velero"`)
|
||||
assert.Contains(t, jsonStr, `"uploaderType":"kopia"`)
|
||||
assert.Contains(t, jsonStr, `"retainedSnapshot":"retain-2"`)
|
||||
assert.Contains(t, jsonStr, `"snapshotHandle":"snap-2"`)
|
||||
assert.Contains(t, jsonStr, `"operationID":"op-3"`)
|
||||
assert.Contains(t, jsonStr, `"size":3000`)
|
||||
assert.Contains(t, jsonStr, `"incrementalSize":300`)
|
||||
assert.Contains(t, jsonStr, `"phase":"Completed"`)
|
||||
assert.Contains(t, jsonStr, `"restoreType":"Incremental"`)
|
||||
assert.Contains(t, jsonStr, `"pvrInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"podName":"pod-2"`)
|
||||
assert.Contains(t, jsonStr, `"podNamespace":"ns-2"`)
|
||||
assert.Contains(t, jsonStr, `"nodeName":"node-2"`)
|
||||
assert.Contains(t, jsonStr, `"csiSnapshotInfo":{`)
|
||||
assert.Contains(t, jsonStr, `"nativeSnapshotInfo":{`)
|
||||
|
||||
var unmarshaled RestoreVolumeInfo
|
||||
err = json.Unmarshal(data, &unmarshaled)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, orig, unmarshaled)
|
||||
}
|
||||
|
||||
@@ -5666,7 +5666,7 @@ func TestUpdateVolumeInfos(t *testing.T) {
|
||||
PVCName: "pvc-1",
|
||||
PVCNamespace: "ns-1",
|
||||
CompletionTimestamp: &metav1.Time{},
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
},
|
||||
},
|
||||
@@ -5677,7 +5677,7 @@ func TestUpdateVolumeInfos(t *testing.T) {
|
||||
PVCNamespace: "ns-1",
|
||||
CompletionTimestamp: &now,
|
||||
Result: volume.VolumeResultFailed,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
RetainedSnapshot: "vs-1",
|
||||
SnapshotHandle: "snapshot-id",
|
||||
@@ -5706,7 +5706,7 @@ func TestUpdateVolumeInfos(t *testing.T) {
|
||||
PVCName: "pvc-1",
|
||||
PVCNamespace: "ns-1",
|
||||
CompletionTimestamp: &metav1.Time{},
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
},
|
||||
},
|
||||
@@ -5717,7 +5717,7 @@ func TestUpdateVolumeInfos(t *testing.T) {
|
||||
PVCNamespace: "ns-1",
|
||||
CompletionTimestamp: &now,
|
||||
Result: volume.VolumeResultSucceeded,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
RetainedSnapshot: "vs-1",
|
||||
SnapshotHandle: "snapshot-id",
|
||||
|
||||
@@ -61,6 +61,12 @@ func (d *DataDownloadBuilder) Phase(phase velerov2alpha1api.DataDownloadPhase) *
|
||||
return d
|
||||
}
|
||||
|
||||
// RestoreType sets the DataDownload's RestoreType.
|
||||
func (d *DataDownloadBuilder) RestoreType(restoreType string) *DataDownloadBuilder {
|
||||
d.object.Spec.RestoreType = restoreType
|
||||
return d
|
||||
}
|
||||
|
||||
// SnapshotID sets the DataDownload's SnapshotID.
|
||||
func (d *DataDownloadBuilder) SnapshotID(id string) *DataDownloadBuilder {
|
||||
d.object.Spec.SnapshotID = id
|
||||
|
||||
@@ -249,6 +249,10 @@ func DescribeBackupSpec(d *Describer, spec velerov1api.BackupSpec) {
|
||||
}
|
||||
d.Printf("Data Mover:\t%s\n", s)
|
||||
|
||||
if string(spec.BackupType) != "" {
|
||||
d.Printf("Backup Type:\t%s\n", spec.BackupType)
|
||||
}
|
||||
|
||||
d.Println()
|
||||
d.Printf("TTL:\t%s\n", spec.TTL.Duration)
|
||||
|
||||
@@ -746,6 +750,10 @@ func describeDataMovement(d *Describer, details bool, info *volume.BackupVolumeI
|
||||
if info.SnapshotDataMovementInfo.IncrementalSize != nil {
|
||||
d.Printf("\t\t\t\tIncremental data Size (bytes): %d\n", *info.SnapshotDataMovementInfo.IncrementalSize)
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.ParentSnapshot != "" {
|
||||
d.Printf("\t\t\t\tParent Snapshot: %s\n", info.SnapshotDataMovementInfo.ParentSnapshot)
|
||||
}
|
||||
|
||||
d.Printf("\t\t\t\tResult: %s\n", info.Result)
|
||||
} else {
|
||||
d.Printf("\t\t\tData Movement: %s\n", "included, specify --details for more information")
|
||||
|
||||
@@ -108,6 +108,7 @@ func TestDescribeBackupSpec(t *testing.T) {
|
||||
TTL(72 * time.Hour).
|
||||
CSISnapshotTimeout(10 * time.Minute).
|
||||
DataMover("mover").
|
||||
BackupType(velerov1api.BackupTypeFull).
|
||||
Hooks(velerov1api.BackupHooks{
|
||||
Resources: []velerov1api.BackupResourceHookSpec{
|
||||
{
|
||||
@@ -156,6 +157,7 @@ Storage Location: backup-location
|
||||
Velero-Native Snapshot PVs: auto
|
||||
Snapshot Move Data: auto
|
||||
Data Mover: mover
|
||||
Backup Type: Full
|
||||
|
||||
TTL: 72h0m0s
|
||||
|
||||
@@ -575,7 +577,7 @@ func TestCSISnapshots(t *testing.T) {
|
||||
PVCNamespace: "pvc-ns-3",
|
||||
PVCName: "pvc-3",
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-3",
|
||||
@@ -597,7 +599,7 @@ func TestCSISnapshots(t *testing.T) {
|
||||
PVCName: "pvc-4",
|
||||
SnapshotDataMoved: true,
|
||||
Result: volume.VolumeResultSucceeded,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-4",
|
||||
@@ -625,13 +627,15 @@ func TestCSISnapshots(t *testing.T) {
|
||||
PVCName: "pvc-5",
|
||||
Result: volume.VolumeResultFailed,
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-5",
|
||||
OperationID: "fake-operation-5",
|
||||
Size: 100,
|
||||
IncrementalSize: ptr.To(int64(50)),
|
||||
Phase: velerov2alpha1.DataUploadPhaseFailed,
|
||||
ParentSnapshot: "fake-parent-snapshot",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -644,6 +648,7 @@ func TestCSISnapshots(t *testing.T) {
|
||||
Uploader Type: fake-uploader
|
||||
Moved data Size (bytes): 100
|
||||
Incremental data Size (bytes): 50
|
||||
Parent Snapshot: fake-parent-snapshot
|
||||
Result: failed
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -136,6 +136,9 @@ func DescribeBackupSpecInSF(d *StructuredDescriber, spec velerov1api.BackupSpec)
|
||||
s = spec.DataMover
|
||||
}
|
||||
backupSpecInfo["dataMover"] = s
|
||||
if string(spec.BackupType) != "" {
|
||||
backupSpecInfo["backupType"] = spec.BackupType
|
||||
}
|
||||
|
||||
// describe TTL
|
||||
backupSpecInfo["TTL"] = spec.TTL.Duration.String()
|
||||
@@ -475,6 +478,9 @@ func describeDataMovementInSF(details bool, info *volume.BackupVolumeInfo, snaps
|
||||
if info.SnapshotDataMovementInfo.IncrementalSize != nil {
|
||||
dataMovement["incrementalSize"] = *info.SnapshotDataMovementInfo.IncrementalSize
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.ParentSnapshot != "" {
|
||||
dataMovement["parentSnapshot"] = info.SnapshotDataMovementInfo.ParentSnapshot
|
||||
}
|
||||
|
||||
snapshotDetail["dataMovement"] = dataMovement
|
||||
} else {
|
||||
|
||||
@@ -24,9 +24,11 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1api "k8s.io/api/core/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"github.com/vmware-tanzu/velero/internal/volume"
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/results"
|
||||
)
|
||||
@@ -45,6 +47,7 @@ func TestDescribeBackupInSF(t *testing.T) {
|
||||
TTL(72 * time.Hour).
|
||||
CSISnapshotTimeout(10 * time.Minute).
|
||||
DataMover("mover").
|
||||
BackupType(velerov1api.BackupTypeFull).
|
||||
Hooks(velerov1api.BackupHooks{
|
||||
Resources: []velerov1api.BackupResourceHookSpec{
|
||||
{
|
||||
@@ -87,6 +90,7 @@ func TestDescribeBackupInSF(t *testing.T) {
|
||||
"clusterScoped": "auto",
|
||||
},
|
||||
"dataMover": "mover",
|
||||
"backupType": velerov1api.BackupTypeFull,
|
||||
"labelSelector": emptyDisplay,
|
||||
"storageLocation": "backup-location",
|
||||
"veleroNativeSnapshotPVs": "auto",
|
||||
@@ -517,7 +521,7 @@ func TestDescribeCSISnapshotsInSF(t *testing.T) {
|
||||
PVCNamespace: "pvc-ns-3",
|
||||
PVCName: "pvc-3",
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-3",
|
||||
@@ -542,7 +546,7 @@ func TestDescribeCSISnapshotsInSF(t *testing.T) {
|
||||
PVCName: "pvc-4",
|
||||
SnapshotDataMoved: true,
|
||||
Result: volume.VolumeResultSucceeded,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-4",
|
||||
@@ -573,10 +577,15 @@ func TestDescribeCSISnapshotsInSF(t *testing.T) {
|
||||
Result: volume.VolumeResultFailed,
|
||||
PVCName: "pvc-4",
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-4",
|
||||
OperationID: "fake-operation-4",
|
||||
BackupType: velerov1api.BackupTypeIncremental,
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
UploaderType: "fake-uploader",
|
||||
SnapshotHandle: "fake-repo-id-4",
|
||||
OperationID: "fake-operation-4",
|
||||
Size: 100,
|
||||
IncrementalSize: ptr.To(int64(50)),
|
||||
Phase: velerov2alpha1.DataUploadPhaseFailed,
|
||||
ParentSnapshot: "fake-parent-snapshot",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -585,10 +594,13 @@ func TestDescribeCSISnapshotsInSF(t *testing.T) {
|
||||
"csiSnapshots": map[string]any{
|
||||
"pvc-ns-4/pvc-4": map[string]any{
|
||||
"dataMovement": map[string]any{
|
||||
"operationID": "fake-operation-4",
|
||||
"dataMover": "velero",
|
||||
"uploaderType": "fake-uploader",
|
||||
"result": "failed",
|
||||
"operationID": "fake-operation-4",
|
||||
"dataMover": "velero",
|
||||
"uploaderType": "fake-uploader",
|
||||
"size": int64(100),
|
||||
"incrementalSize": int64(50),
|
||||
"result": "failed",
|
||||
"parentSnapshot": "fake-parent-snapshot",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -209,6 +209,11 @@ func DescribeRestore(
|
||||
s = string(restore.Spec.ExistingResourcePolicy)
|
||||
}
|
||||
d.Printf("Existing Resource Policy: \t%s\n", s)
|
||||
s = emptyDisplay
|
||||
if restore.Spec.ExistingVolumeDataPolicy != "" {
|
||||
s = string(restore.Spec.ExistingVolumeDataPolicy)
|
||||
}
|
||||
d.Printf("Existing Volume Data Policy: \t%s\n", s)
|
||||
d.Printf("ItemOperationTimeout:\t%s\n", restore.Spec.ItemOperationTimeout.Duration)
|
||||
|
||||
d.Println()
|
||||
@@ -468,6 +473,15 @@ func describeCSISnapshotsRestores(d *Describer, restoreVolInfo []volume.RestoreV
|
||||
d.Printf("\t\t\tOperation ID: %s\n", info.SnapshotDataMovementInfo.OperationID)
|
||||
d.Printf("\t\t\tData Mover: %s\n", info.SnapshotDataMovementInfo.DataMover)
|
||||
d.Printf("\t\t\tUploader Type: %s\n", info.SnapshotDataMovementInfo.UploaderType)
|
||||
if info.SnapshotDataMovementInfo.RestoreType != "" {
|
||||
d.Printf("\t\t\tRestore Type: %s\n", info.SnapshotDataMovementInfo.RestoreType)
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.Size > 0 {
|
||||
d.Printf("\t\t\tRestored data Size (bytes): %d\n", info.SnapshotDataMovementInfo.Size)
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.IncrementalSize != nil {
|
||||
d.Printf("\t\t\tIncremental data Size (bytes): %d\n", *info.SnapshotDataMovementInfo.IncrementalSize)
|
||||
}
|
||||
} else {
|
||||
d.Printf("\t\tData Movement: specify --details for more information\n")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package output
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"text/tabwriter"
|
||||
@@ -10,11 +11,13 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1api "k8s.io/api/core/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"github.com/vmware-tanzu/velero/internal/volume"
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/itemoperation"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/results"
|
||||
)
|
||||
@@ -309,11 +312,13 @@ CSI Snapshot Restores:
|
||||
PVName: "pv-3",
|
||||
RestoreMethod: volume.CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
OperationID: "op-3",
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
Size: 1234,
|
||||
SnapshotDataMovementInfo: &volume.RestoreSnapshotDataMovementInfo{
|
||||
OperationID: "op-3",
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
Size: 1234,
|
||||
IncrementalSize: ptr.To(int64(500)),
|
||||
RestoreType: "Incremental",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -325,6 +330,9 @@ CSI Snapshot Restores:
|
||||
Operation ID: op-3
|
||||
Data Mover: velero
|
||||
Uploader Type: kopia
|
||||
Restore Type: Incremental
|
||||
Restored data Size (bytes): 1234
|
||||
Incremental data Size (bytes): 500
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -336,7 +344,7 @@ CSI Snapshot Restores:
|
||||
PVName: "pv-3",
|
||||
RestoreMethod: volume.CSISnapshot,
|
||||
SnapshotDataMoved: true,
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.RestoreSnapshotDataMovementInfo{
|
||||
OperationID: "op-3",
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
@@ -415,3 +423,16 @@ func TestDescribeResourceModifier(t *testing.T) {
|
||||
fmt.Println(d.buf.String())
|
||||
require.Equal(t, expectOutput, d.buf.String())
|
||||
}
|
||||
|
||||
func TestDescribeRestore(t *testing.T) {
|
||||
kbClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
restore := builder.ForRestore("velero", "test-restore").
|
||||
Backup("test-backup").
|
||||
ExistingResourcePolicy(string(velerov1api.ResourcePolicyTypeUpdate)).
|
||||
ExistingVolumeDataPolicy(string(velerov1api.VolumeDataPolicyTypeFull)).
|
||||
Result()
|
||||
|
||||
out := DescribeRestore(context.Background(), kbClient, restore, nil, false, false, "")
|
||||
assert.Contains(t, out, "Existing Resource Policy: update")
|
||||
assert.Contains(t, out, "Existing Volume Data Policy: full")
|
||||
}
|
||||
|
||||
@@ -196,6 +196,13 @@ func describeRestoreSpecInSF(d *StructuredDescriber, spec velerov1api.RestoreSpe
|
||||
specInfo["existingResourcePolicy"] = emptyDisplay
|
||||
}
|
||||
|
||||
// existing volume data policy
|
||||
if spec.ExistingVolumeDataPolicy != "" {
|
||||
specInfo["existingVolumeDataPolicy"] = string(spec.ExistingVolumeDataPolicy)
|
||||
} else {
|
||||
specInfo["existingVolumeDataPolicy"] = emptyDisplay
|
||||
}
|
||||
|
||||
specInfo["itemOperationTimeout"] = spec.ItemOperationTimeout.Duration.String()
|
||||
specInfo["preserveNodePorts"] = BoolPointerString(spec.PreserveNodePorts, "false", "true", "auto")
|
||||
|
||||
@@ -360,12 +367,22 @@ func describeCSISnapshotsRestoresInSF(d *StructuredDescriber, restoreVolInfo []v
|
||||
}
|
||||
continue
|
||||
}
|
||||
dmInfo := map[string]any{
|
||||
"operationID": info.SnapshotDataMovementInfo.OperationID,
|
||||
"dataMover": info.SnapshotDataMovementInfo.DataMover,
|
||||
"uploaderType": info.SnapshotDataMovementInfo.UploaderType,
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.RestoreType != "" {
|
||||
dmInfo["restoreType"] = info.SnapshotDataMovementInfo.RestoreType
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.Size > 0 {
|
||||
dmInfo["size"] = info.SnapshotDataMovementInfo.Size
|
||||
}
|
||||
if info.SnapshotDataMovementInfo.IncrementalSize != nil {
|
||||
dmInfo["incrementalSize"] = *info.SnapshotDataMovementInfo.IncrementalSize
|
||||
}
|
||||
csiRestores[key] = map[string]any{
|
||||
"dataMovement": map[string]any{
|
||||
"operationID": info.SnapshotDataMovementInfo.OperationID,
|
||||
"dataMover": info.SnapshotDataMovementInfo.DataMover,
|
||||
"uploaderType": info.SnapshotDataMovementInfo.UploaderType,
|
||||
},
|
||||
"dataMovement": dmInfo,
|
||||
}
|
||||
} else {
|
||||
csiRestores[key] = map[string]any{
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1api "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/ptr"
|
||||
|
||||
"github.com/vmware-tanzu/velero/internal/volume"
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
@@ -156,25 +157,27 @@ func TestDescribeRestoreSpecInSF(t *testing.T) {
|
||||
"excluded": emptyDisplay,
|
||||
"clusterScoped": "auto",
|
||||
},
|
||||
"namespaceMappings": emptyDisplay,
|
||||
"labelSelector": emptyDisplay,
|
||||
"orLabelSelectors": emptyDisplay,
|
||||
"restorePVs": "auto",
|
||||
"existingResourcePolicy": emptyDisplay,
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "auto",
|
||||
"namespaceMappings": emptyDisplay,
|
||||
"labelSelector": emptyDisplay,
|
||||
"orLabelSelectors": emptyDisplay,
|
||||
"restorePVs": "auto",
|
||||
"existingResourcePolicy": emptyDisplay,
|
||||
"existingVolumeDataPolicy": emptyDisplay,
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "included namespaces wildcard treated as all",
|
||||
spec: velerov1api.RestoreSpec{
|
||||
BackupName: "backup-2",
|
||||
IncludedNamespaces: []string{"*"},
|
||||
ExcludedNamespaces: []string{"kube-system"},
|
||||
IncludedResources: []string{"pods", "configmaps"},
|
||||
ExcludedResources: []string{"secrets"},
|
||||
ExistingResourcePolicy: velerov1api.ResourcePolicyTypeUpdate,
|
||||
BackupName: "backup-2",
|
||||
IncludedNamespaces: []string{"*"},
|
||||
ExcludedNamespaces: []string{"kube-system"},
|
||||
IncludedResources: []string{"pods", "configmaps"},
|
||||
ExcludedResources: []string{"secrets"},
|
||||
ExistingResourcePolicy: velerov1api.ResourcePolicyTypeUpdate,
|
||||
ExistingVolumeDataPolicy: velerov1api.VolumeDataPolicyTypeFull,
|
||||
},
|
||||
expect: map[string]any{
|
||||
"spec": map[string]any{
|
||||
@@ -188,13 +191,14 @@ func TestDescribeRestoreSpecInSF(t *testing.T) {
|
||||
"excluded": "secrets",
|
||||
"clusterScoped": "auto",
|
||||
},
|
||||
"namespaceMappings": emptyDisplay,
|
||||
"labelSelector": emptyDisplay,
|
||||
"orLabelSelectors": emptyDisplay,
|
||||
"restorePVs": "auto",
|
||||
"existingResourcePolicy": string(velerov1api.ResourcePolicyTypeUpdate),
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "auto",
|
||||
"namespaceMappings": emptyDisplay,
|
||||
"labelSelector": emptyDisplay,
|
||||
"orLabelSelectors": emptyDisplay,
|
||||
"restorePVs": "auto",
|
||||
"existingResourcePolicy": string(velerov1api.ResourcePolicyTypeUpdate),
|
||||
"existingVolumeDataPolicy": string(velerov1api.VolumeDataPolicyTypeFull),
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "auto",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -223,13 +227,14 @@ func TestDescribeRestoreSpecInSF(t *testing.T) {
|
||||
"excluded": emptyDisplay,
|
||||
"clusterScoped": "auto",
|
||||
},
|
||||
"namespaceMappings": emptyDisplay,
|
||||
"labelSelector": emptyDisplay,
|
||||
"orLabelSelectors": emptyDisplay,
|
||||
"restorePVs": "auto",
|
||||
"existingResourcePolicy": emptyDisplay,
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "auto",
|
||||
"namespaceMappings": emptyDisplay,
|
||||
"labelSelector": emptyDisplay,
|
||||
"orLabelSelectors": emptyDisplay,
|
||||
"restorePVs": "auto",
|
||||
"existingResourcePolicy": emptyDisplay,
|
||||
"existingVolumeDataPolicy": emptyDisplay,
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "auto",
|
||||
"resourceModifier": map[string]any{
|
||||
"type": "ConfigMap",
|
||||
"name": "my-modifier",
|
||||
@@ -272,13 +277,14 @@ func TestDescribeRestoreSpecInSF(t *testing.T) {
|
||||
"excluded": emptyDisplay,
|
||||
"clusterScoped": "included",
|
||||
},
|
||||
"namespaceMappings": map[string]string{"ns-a": "ns-a-new"},
|
||||
"labelSelector": "app=nginx",
|
||||
"orLabelSelectors": "env=prod or env=stage",
|
||||
"restorePVs": "true",
|
||||
"existingResourcePolicy": emptyDisplay,
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "false",
|
||||
"namespaceMappings": map[string]string{"ns-a": "ns-a-new"},
|
||||
"labelSelector": "app=nginx",
|
||||
"orLabelSelectors": "env=prod or env=stage",
|
||||
"restorePVs": "true",
|
||||
"existingResourcePolicy": emptyDisplay,
|
||||
"existingVolumeDataPolicy": emptyDisplay,
|
||||
"itemOperationTimeout": "0s",
|
||||
"preserveNodePorts": "false",
|
||||
"resourcePolicy": map[string]any{
|
||||
"type": "configmap",
|
||||
"name": "volume-policy",
|
||||
@@ -467,10 +473,13 @@ func TestDescribeRestoreCSISnapshotsInSF_NoData(t *testing.T) {
|
||||
SnapshotDataMoved: true,
|
||||
PVCName: "pvc-3",
|
||||
PVCNamespace: "ns-3",
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
OperationID: "op-3",
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
SnapshotDataMovementInfo: &volume.RestoreSnapshotDataMovementInfo{
|
||||
OperationID: "op-3",
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
Size: 1234,
|
||||
IncrementalSize: ptr.To(int64(500)),
|
||||
RestoreType: "Incremental",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -479,9 +488,12 @@ func TestDescribeRestoreCSISnapshotsInSF_NoData(t *testing.T) {
|
||||
"csiSnapshotRestores": map[string]any{
|
||||
"ns-3/pvc-3": map[string]any{
|
||||
"dataMovement": map[string]any{
|
||||
"operationID": "op-3",
|
||||
"dataMover": "velero",
|
||||
"uploaderType": "kopia",
|
||||
"operationID": "op-3",
|
||||
"dataMover": "velero",
|
||||
"uploaderType": "kopia",
|
||||
"size": int64(1234),
|
||||
"incrementalSize": int64(500),
|
||||
"restoreType": "Incremental",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -495,7 +507,7 @@ func TestDescribeRestoreCSISnapshotsInSF_NoData(t *testing.T) {
|
||||
SnapshotDataMoved: true,
|
||||
PVCName: "pvc-3",
|
||||
PVCNamespace: "ns-3",
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.RestoreSnapshotDataMovementInfo{
|
||||
OperationID: "op-3",
|
||||
DataMover: "velero",
|
||||
UploaderType: "kopia",
|
||||
|
||||
@@ -118,7 +118,7 @@ func TestRestorePVWithVolumeInfo(t *testing.T) {
|
||||
"pv-1": {
|
||||
BackupMethod: volume.PodVolumeBackup,
|
||||
PVName: "pv-1",
|
||||
PVBInfo: &volume.PodVolumeInfo{
|
||||
PVBInfo: &volume.PodVolumeBackupInfo{
|
||||
SnapshotHandle: "testSnapshotHandle",
|
||||
Size: 100,
|
||||
NodeName: "testNode",
|
||||
@@ -173,7 +173,7 @@ func TestRestorePVWithVolumeInfo(t *testing.T) {
|
||||
CSISnapshotInfo: &volume.CSISnapshotInfo{
|
||||
Driver: "pd.csi.storage.gke.io",
|
||||
},
|
||||
SnapshotDataMovementInfo: &volume.SnapshotDataMovementInfo{
|
||||
SnapshotDataMovementInfo: &volume.BackupSnapshotDataMovementInfo{
|
||||
DataMover: "velero",
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user