mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-08-25 00:26:08 +00:00
Double check the label for backup when deleting VSC (#10346)
e2e-test-kind.yaml / extract (push) Failing after 8s
Run the E2E test on kind / get-go-version (push) Failing after 9s
Run the E2E test on kind / build (push) Skipped
Run the E2E test on kind / setup-test-matrix (push) Successful in 3s
Run the E2E test on kind / run-e2e-test (push) Skipped
push.yml / extract (push) Failing after 7s
Main CI / get-go-version (push) Failing after 8s
Main CI / Build (push) Skipped
e2e-test-kind.yaml / extract (push) Failing after 8s
Run the E2E test on kind / get-go-version (push) Failing after 9s
Run the E2E test on kind / build (push) Skipped
Run the E2E test on kind / setup-test-matrix (push) Successful in 3s
Run the E2E test on kind / run-e2e-test (push) Skipped
push.yml / extract (push) Failing after 7s
Main CI / get-go-version (push) Failing after 8s
Main CI / Build (push) Skipped
This commit double checks the label of the VSC on the cluster before deleting it to avoid mis-deletion. Signed-off-by: Daniel Jiang <daniel.jiang@broadcom.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Double check the label for backup when deleting VSC- #10346
|
||||
@@ -86,7 +86,7 @@ func (p *volumeSnapshotContentDeleteItemAction) Execute(
|
||||
// This handles legacy (pre-1.15) backups where the original VSC
|
||||
// with DeletionPolicy=Retain still exists in the cluster.
|
||||
originalVSCName := snapCont.Name
|
||||
if cleaned := p.tryDeleteOriginalVSC(context.TODO(), originalVSCName); cleaned {
|
||||
if cleaned := p.tryDeleteOriginalVSC(context.TODO(), originalVSCName, input.Backup.Name); cleaned {
|
||||
p.log.Infof("Successfully deleted original VolumeSnapshotContent %s from cluster, skipping temp VSC creation", originalVSCName)
|
||||
return nil
|
||||
}
|
||||
@@ -149,10 +149,11 @@ func (p *volumeSnapshotContentDeleteItemAction) Execute(
|
||||
// the cluster (legacy pre-1.15 backups). It patches the DeletionPolicy to
|
||||
// Delete so the CSI driver also removes the cloud snapshot, then deletes
|
||||
// the VSC object itself.
|
||||
// Returns true if the original VSC was found and deletion was initiated.
|
||||
// Returns true if the original VSC was found, carries the backup label, and deletion was initiated.
|
||||
func (p *volumeSnapshotContentDeleteItemAction) tryDeleteOriginalVSC(
|
||||
ctx context.Context,
|
||||
vscName string,
|
||||
backupName string,
|
||||
) bool {
|
||||
existing := new(snapshotv1api.VolumeSnapshotContent)
|
||||
if err := p.crClient.Get(ctx, crclient.ObjectKey{Name: vscName}, existing); err != nil {
|
||||
@@ -164,6 +165,15 @@ func (p *volumeSnapshotContentDeleteItemAction) tryDeleteOriginalVSC(
|
||||
return false
|
||||
}
|
||||
|
||||
if !kubeutil.HasBackupLabel(&existing.ObjectMeta, backupName) {
|
||||
p.log.Warnf(
|
||||
"Original VolumeSnapshotContent %s in cluster does not belong to backup %s, skipping direct deletion",
|
||||
vscName,
|
||||
backupName,
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
p.log.Debugf("Found original VolumeSnapshotContent %s in cluster (legacy backup), cleaning up directly", vscName)
|
||||
|
||||
// Patch DeletionPolicy to Delete so the CSI driver removes the cloud snapshot
|
||||
|
||||
@@ -122,7 +122,29 @@ func TestVSCExecute(t *testing.T) {
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
preExistingVSC: &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Labels: map[string]string{
|
||||
velerov1api.BackupNameLabel: "backup",
|
||||
},
|
||||
},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentRetain,
|
||||
Driver: "disk.csi.azure.com",
|
||||
Source: snapshotv1api.VolumeSnapshotContentSource{SnapshotHandle: stringPtr("snap-123")},
|
||||
VolumeSnapshotRef: corev1api.ObjectReference{Name: "vs-1", Namespace: "default"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Original VSC exists in cluster without backup label, falls through to temp VSC flow",
|
||||
vsc: builder.ForVolumeSnapshotContent("bar").ObjectMeta(builder.WithLabelsMap(map[string]string{velerov1api.BackupNameLabel: "backup"})).Status(&snapshotv1api.VolumeSnapshotContentStatus{SnapshotHandle: &snapshotHandleStr}).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
preExistingVSC: &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentRetain,
|
||||
Driver: "disk.csi.azure.com",
|
||||
@@ -200,22 +222,51 @@ func TestNewVolumeSnapshotContentDeleteItemAction(t *testing.T) {
|
||||
|
||||
func TestTryDeleteOriginalVSC(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
vscName string
|
||||
existing *snapshotv1api.VolumeSnapshotContent
|
||||
createIt bool
|
||||
expectRet bool
|
||||
name string
|
||||
vscName string
|
||||
backupName string
|
||||
existing *snapshotv1api.VolumeSnapshotContent
|
||||
createIt bool
|
||||
expectRet bool
|
||||
}{
|
||||
{
|
||||
name: "VSC not found in cluster, returns false",
|
||||
vscName: "not-found",
|
||||
name: "VSC not found in cluster, returns false",
|
||||
vscName: "not-found",
|
||||
backupName: "test-backup",
|
||||
expectRet: false,
|
||||
},
|
||||
{
|
||||
name: "VSC found in cluster without backup label, returns false",
|
||||
vscName: "unlabeled-vsc",
|
||||
backupName: "test-backup",
|
||||
existing: &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "unlabeled-vsc"},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentRetain,
|
||||
Driver: "disk.csi.azure.com",
|
||||
Source: snapshotv1api.VolumeSnapshotContentSource{
|
||||
SnapshotHandle: stringPtr("snap-123"),
|
||||
},
|
||||
VolumeSnapshotRef: corev1api.ObjectReference{
|
||||
Name: "vs-1",
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
createIt: true,
|
||||
expectRet: false,
|
||||
},
|
||||
{
|
||||
name: "VSC found with Retain policy, patches and deletes",
|
||||
vscName: "legacy-vsc",
|
||||
name: "VSC found with Retain policy and matching backup label, patches and deletes",
|
||||
vscName: "legacy-vsc",
|
||||
backupName: "test-backup",
|
||||
existing: &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "legacy-vsc"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "legacy-vsc",
|
||||
Labels: map[string]string{
|
||||
velerov1api.BackupNameLabel: "test-backup",
|
||||
},
|
||||
},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentRetain,
|
||||
Driver: "disk.csi.azure.com",
|
||||
@@ -232,10 +283,16 @@ func TestTryDeleteOriginalVSC(t *testing.T) {
|
||||
expectRet: true,
|
||||
},
|
||||
{
|
||||
name: "VSC found with Delete policy already, just deletes",
|
||||
vscName: "already-delete-vsc",
|
||||
name: "VSC found with Delete policy and matching backup label, just deletes",
|
||||
vscName: "already-delete-vsc",
|
||||
backupName: "test-backup",
|
||||
existing: &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "already-delete-vsc"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "already-delete-vsc",
|
||||
Labels: map[string]string{
|
||||
velerov1api.BackupNameLabel: "test-backup",
|
||||
},
|
||||
},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentDelete,
|
||||
Driver: "disk.csi.azure.com",
|
||||
@@ -266,7 +323,7 @@ func TestTryDeleteOriginalVSC(t *testing.T) {
|
||||
require.NoError(t, crClient.Create(t.Context(), test.existing))
|
||||
}
|
||||
|
||||
result := p.tryDeleteOriginalVSC(t.Context(), test.vscName)
|
||||
result := p.tryDeleteOriginalVSC(t.Context(), test.vscName, test.backupName)
|
||||
require.Equal(t, test.expectRet, result)
|
||||
|
||||
// If cleanup succeeded, verify the VSC is gone
|
||||
@@ -289,13 +346,18 @@ func TestTryDeleteOriginalVSC(t *testing.T) {
|
||||
log: logrus.StandardLogger(),
|
||||
crClient: errClient,
|
||||
}
|
||||
require.False(t, p.tryDeleteOriginalVSC(t.Context(), "some-vsc"))
|
||||
require.False(t, p.tryDeleteOriginalVSC(t.Context(), "some-vsc", "test-backup"))
|
||||
})
|
||||
|
||||
t.Run("Patch fails, returns false", func(t *testing.T) {
|
||||
realClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
vsc := &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "patch-fail-vsc"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "patch-fail-vsc",
|
||||
Labels: map[string]string{
|
||||
velerov1api.BackupNameLabel: "test-backup",
|
||||
},
|
||||
},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentRetain,
|
||||
Driver: "disk.csi.azure.com",
|
||||
@@ -313,13 +375,18 @@ func TestTryDeleteOriginalVSC(t *testing.T) {
|
||||
log: logrus.StandardLogger(),
|
||||
crClient: errClient,
|
||||
}
|
||||
require.False(t, p.tryDeleteOriginalVSC(t.Context(), "patch-fail-vsc"))
|
||||
require.False(t, p.tryDeleteOriginalVSC(t.Context(), "patch-fail-vsc", "test-backup"))
|
||||
})
|
||||
|
||||
t.Run("Delete fails, returns false", func(t *testing.T) {
|
||||
realClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
vsc := &snapshotv1api.VolumeSnapshotContent{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "delete-fail-vsc"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "delete-fail-vsc",
|
||||
Labels: map[string]string{
|
||||
velerov1api.BackupNameLabel: "test-backup",
|
||||
},
|
||||
},
|
||||
Spec: snapshotv1api.VolumeSnapshotContentSpec{
|
||||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentDelete,
|
||||
Driver: "disk.csi.azure.com",
|
||||
@@ -337,7 +404,7 @@ func TestTryDeleteOriginalVSC(t *testing.T) {
|
||||
log: logrus.StandardLogger(),
|
||||
crClient: errClient,
|
||||
}
|
||||
require.False(t, p.tryDeleteOriginalVSC(t.Context(), "delete-fail-vsc"))
|
||||
require.False(t, p.tryDeleteOriginalVSC(t.Context(), "delete-fail-vsc", "test-backup"))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user