Populators: Add to PVC' exclude velero backup label (#3526)

When backing up with Velero if a PVC is terminating
then the backup is marked as PartiallyFailed, while the
backup is still valid to use and its more of a warning,
PVC' should be transparent to the user so have the backup
partiallyFailed because of PVC' is a bad user experience.
To fix that added to all our PVC' an label so it will be
excluded from the Velero backup.
This is a fix for previous PR
https://github.com/kubevirt/containerized-data-importer/pull/3500
Which added an annotation instead of label by accident.

Signed-off-by: Shelly Kagan <skagan@redhat.com>
Co-authored-by: Shelly Kagan <skagan@redhat.com>
This commit is contained in:
kubevirt-bot 2024-11-11 09:40:00 +01:00 committed by GitHub
parent 620fedbcab
commit 8cf8cdc91f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 13 additions and 13 deletions

View File

@ -106,10 +106,10 @@ func (p *CSIClonePhase) createClaim(ctx context.Context) (*corev1.PersistentVolu
desiredClaim.Spec.Resources.Requests[corev1.ResourceStorage] = sourceSize desiredClaim.Spec.Resources.Requests[corev1.ResourceStorage] = sourceSize
cc.AddAnnotation(desiredClaim, cc.AnnPopulatorKind, cdiv1.VolumeCloneSourceRef) cc.AddAnnotation(desiredClaim, cc.AnnPopulatorKind, cdiv1.VolumeCloneSourceRef)
cc.AddAnnotation(desiredClaim, cc.AnnExcludeFromVeleroBackup, "true")
if p.OwnershipLabel != "" { if p.OwnershipLabel != "" {
AddOwnershipLabel(p.OwnershipLabel, desiredClaim, p.Owner) AddOwnershipLabel(p.OwnershipLabel, desiredClaim, p.Owner)
} }
cc.AddLabel(desiredClaim, cc.LabelExcludeFromVeleroBackup, "true")
if err := p.Client.Create(ctx, desiredClaim); err != nil { if err := p.Client.Create(ctx, desiredClaim); err != nil {
checkQuotaExceeded(p.Recorder, p.Owner, err) checkQuotaExceeded(p.Recorder, p.Owner, err)

View File

@ -155,10 +155,10 @@ var _ = Describe("CSIClonePhase test", func() {
Expect(pvc.Spec.DataSourceRef.Namespace).To(BeNil()) Expect(pvc.Spec.DataSourceRef.Namespace).To(BeNil())
Expect(pvc.Spec.DataSourceRef.Name).To(Equal(sourceClaim.Name)) Expect(pvc.Spec.DataSourceRef.Name).To(Equal(sourceClaim.Name))
Expect(pvc.Annotations[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeCloneSourceRef)) Expect(pvc.Annotations[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeCloneSourceRef))
Expect(pvc.Annotations[cc.AnnExcludeFromVeleroBackup]).To(Equal("true"))
Expect(pvc.Spec.Resources.Requests[corev1.ResourceStorage]). Expect(pvc.Spec.Resources.Requests[corev1.ResourceStorage]).
To(Equal(sourceClaim.Status.Capacity[corev1.ResourceStorage])) To(Equal(sourceClaim.Status.Capacity[corev1.ResourceStorage]))
Expect(pvc.Labels[p.OwnershipLabel]).To(Equal("uid")) Expect(pvc.Labels[p.OwnershipLabel]).To(Equal("uid"))
Expect(pvc.Labels[cc.LabelExcludeFromVeleroBackup]).To(Equal("true"))
}) })
Context("with desired claim created", func() { Context("with desired claim created", func() {

View File

@ -120,7 +120,6 @@ func (p *HostClonePhase) createClaim(ctx context.Context) (*corev1.PersistentVol
cc.AddAnnotation(claim, cc.AnnPodRestarts, "0") cc.AddAnnotation(claim, cc.AnnPodRestarts, "0")
cc.AddAnnotation(claim, cc.AnnCloneRequest, fmt.Sprintf("%s/%s", p.Namespace, p.SourceName)) cc.AddAnnotation(claim, cc.AnnCloneRequest, fmt.Sprintf("%s/%s", p.Namespace, p.SourceName))
cc.AddAnnotation(claim, cc.AnnPopulatorKind, cdiv1.VolumeCloneSourceRef) cc.AddAnnotation(claim, cc.AnnPopulatorKind, cdiv1.VolumeCloneSourceRef)
cc.AddAnnotation(claim, cc.AnnExcludeFromVeleroBackup, "true")
cc.AddAnnotation(claim, cc.AnnEventSourceKind, p.Owner.GetObjectKind().GroupVersionKind().Kind) cc.AddAnnotation(claim, cc.AnnEventSourceKind, p.Owner.GetObjectKind().GroupVersionKind().Kind)
cc.AddAnnotation(claim, cc.AnnEventSource, fmt.Sprintf("%s/%s", p.Owner.GetNamespace(), p.Owner.GetName())) cc.AddAnnotation(claim, cc.AnnEventSource, fmt.Sprintf("%s/%s", p.Owner.GetNamespace(), p.Owner.GetName()))
if p.OwnershipLabel != "" { if p.OwnershipLabel != "" {
@ -132,6 +131,7 @@ func (p *HostClonePhase) createClaim(ctx context.Context) (*corev1.PersistentVol
if p.PriorityClassName != "" { if p.PriorityClassName != "" {
cc.AddAnnotation(claim, cc.AnnPriorityClassName, p.PriorityClassName) cc.AddAnnotation(claim, cc.AnnPriorityClassName, p.PriorityClassName)
} }
cc.AddLabel(claim, cc.LabelExcludeFromVeleroBackup, "true")
if err := p.Client.Create(ctx, claim); err != nil { if err := p.Client.Create(ctx, claim); err != nil {
checkQuotaExceeded(p.Recorder, p.Owner, err) checkQuotaExceeded(p.Recorder, p.Owner, err)

View File

@ -105,8 +105,8 @@ var _ = Describe("HostClonePhase test", func() {
Expect(pvc.Annotations[cc.AnnPodRestarts]).To(Equal("0")) Expect(pvc.Annotations[cc.AnnPodRestarts]).To(Equal("0"))
Expect(pvc.Annotations[cc.AnnCloneRequest]).To(Equal("ns/source")) Expect(pvc.Annotations[cc.AnnCloneRequest]).To(Equal("ns/source"))
Expect(pvc.Annotations[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeCloneSourceRef)) Expect(pvc.Annotations[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeCloneSourceRef))
Expect(pvc.Annotations[cc.AnnExcludeFromVeleroBackup]).To(Equal("true"))
Expect(pvc.Labels[p.OwnershipLabel]).To(Equal("uid")) Expect(pvc.Labels[p.OwnershipLabel]).To(Equal("uid"))
Expect(pvc.Labels[cc.LabelExcludeFromVeleroBackup]).To(Equal("true"))
Expect(pvc.Annotations[cc.AnnImmediateBinding]).To(Equal("")) Expect(pvc.Annotations[cc.AnnImmediateBinding]).To(Equal(""))
_, ok := pvc.Annotations[cc.AnnPriorityClassName] _, ok := pvc.Annotations[cc.AnnPriorityClassName]
Expect(ok).To(BeFalse()) Expect(ok).To(BeFalse())

View File

@ -100,10 +100,10 @@ func (p *SnapshotClonePhase) createClaim(ctx context.Context, snapshot *snapshot
} }
cc.AddAnnotation(claim, cc.AnnPopulatorKind, cdiv1.VolumeCloneSourceRef) cc.AddAnnotation(claim, cc.AnnPopulatorKind, cdiv1.VolumeCloneSourceRef)
cc.AddAnnotation(claim, cc.AnnExcludeFromVeleroBackup, "true")
if p.OwnershipLabel != "" { if p.OwnershipLabel != "" {
AddOwnershipLabel(p.OwnershipLabel, claim, p.Owner) AddOwnershipLabel(p.OwnershipLabel, claim, p.Owner)
} }
cc.AddLabel(claim, cc.LabelExcludeFromVeleroBackup, "true")
if err := p.Client.Create(ctx, claim); err != nil { if err := p.Client.Create(ctx, claim); err != nil {
checkQuotaExceeded(p.Recorder, p.Owner, err) checkQuotaExceeded(p.Recorder, p.Owner, err)

View File

@ -175,9 +175,9 @@ var _ = Describe("SnapshotClonePhase test", func() {
Expect(pvc.Spec.DataSourceRef.Namespace).To(BeNil()) Expect(pvc.Spec.DataSourceRef.Namespace).To(BeNil())
Expect(pvc.Spec.DataSourceRef.Name).To(Equal(sourceName)) Expect(pvc.Spec.DataSourceRef.Name).To(Equal(sourceName))
Expect(pvc.Annotations[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeCloneSourceRef)) Expect(pvc.Annotations[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeCloneSourceRef))
Expect(pvc.Annotations[cc.AnnExcludeFromVeleroBackup]).To(Equal("true"))
Expect(pvc.Spec.Resources.Requests[corev1.ResourceStorage]).To(Equal(restoreSize)) Expect(pvc.Spec.Resources.Requests[corev1.ResourceStorage]).To(Equal(restoreSize))
Expect(pvc.Labels[p.OwnershipLabel]).To(Equal("uid")) Expect(pvc.Labels[p.OwnershipLabel]).To(Equal("uid"))
Expect(pvc.Labels[cc.LabelExcludeFromVeleroBackup]).To(Equal("true"))
}) })
Context("with desired claim created", func() { Context("with desired claim created", func() {

View File

@ -239,9 +239,6 @@ const (
// AnnImmediateBinding provides a const to indicate whether immediate binding should be performed on the PV (overrides global config) // AnnImmediateBinding provides a const to indicate whether immediate binding should be performed on the PV (overrides global config)
AnnImmediateBinding = AnnAPIGroup + "/storage.bind.immediate.requested" AnnImmediateBinding = AnnAPIGroup + "/storage.bind.immediate.requested"
//AnnExcludeFromVeleroBackup provides a const to indicate whether an object should be excluded from velero backup
AnnExcludeFromVeleroBackup = "velero.io/exclude-from-backup"
// AnnSelectedNode annotation is added to a PVC that has been triggered by scheduler to // AnnSelectedNode annotation is added to a PVC that has been triggered by scheduler to
// be dynamically provisioned. Its value is the name of the selected node. // be dynamically provisioned. Its value is the name of the selected node.
AnnSelectedNode = "volume.kubernetes.io/selected-node" AnnSelectedNode = "volume.kubernetes.io/selected-node"
@ -305,6 +302,9 @@ const (
// LabelDynamicCredentialSupport specifies if the OS supports updating credentials at runtime. // LabelDynamicCredentialSupport specifies if the OS supports updating credentials at runtime.
LabelDynamicCredentialSupport = "kubevirt.io/dynamic-credentials-support" LabelDynamicCredentialSupport = "kubevirt.io/dynamic-credentials-support"
// LabelExcludeFromVeleroBackup provides a const to indicate whether an object should be excluded from velero backup
LabelExcludeFromVeleroBackup = "velero.io/exclude-from-backup"
// ProgressDone this means we are DONE // ProgressDone this means we are DONE
ProgressDone = "100.0%" ProgressDone = "100.0%"

View File

@ -266,11 +266,11 @@ var _ = Describe("Import populator tests", func() {
Expect(pvcPrime.GetAnnotations()[AnnImmediateBinding]).To(Equal("")) Expect(pvcPrime.GetAnnotations()[AnnImmediateBinding]).To(Equal(""))
Expect(pvcPrime.GetAnnotations()[AnnUploadRequest]).To(Equal("")) Expect(pvcPrime.GetAnnotations()[AnnUploadRequest]).To(Equal(""))
Expect(pvcPrime.GetAnnotations()[AnnPopulatorKind]).To(Equal(cdiv1.VolumeImportSourceRef)) Expect(pvcPrime.GetAnnotations()[AnnPopulatorKind]).To(Equal(cdiv1.VolumeImportSourceRef))
Expect(pvcPrime.GetAnnotations()[AnnExcludeFromVeleroBackup]).To(Equal("true"))
Expect(pvcPrime.GetAnnotations()[AnnPreallocationRequested]).To(Equal("true")) Expect(pvcPrime.GetAnnotations()[AnnPreallocationRequested]).To(Equal("true"))
Expect(pvcPrime.GetAnnotations()[AnnEndpoint]).To(Equal("http://example.com/data")) Expect(pvcPrime.GetAnnotations()[AnnEndpoint]).To(Equal("http://example.com/data"))
Expect(pvcPrime.GetAnnotations()[AnnSource]).To(Equal(SourceHTTP)) Expect(pvcPrime.GetAnnotations()[AnnSource]).To(Equal(SourceHTTP))
Expect(pvcPrime.Annotations[key]).To(Equal(expectedValue)) Expect(pvcPrime.Annotations[key]).To(Equal(expectedValue))
Expect(pvcPrime.GetLabels()[LabelExcludeFromVeleroBackup]).To(Equal("true"))
}, },
table.Entry("No extra annotations", "", "", ""), table.Entry("No extra annotations", "", "", ""),
table.Entry("Invalid extra annotation is not passed", "invalid", "test", ""), table.Entry("Invalid extra annotation is not passed", "invalid", "test", ""),

View File

@ -171,8 +171,8 @@ func (r *ReconcilerBase) getPVCPrime(pvc *corev1.PersistentVolumeClaim) (*corev1
func (r *ReconcilerBase) createPVCPrime(pvc *corev1.PersistentVolumeClaim, source client.Object, waitForFirstConsumer bool, updatePVCForPopulation pvcModifierFunc) (*corev1.PersistentVolumeClaim, error) { func (r *ReconcilerBase) createPVCPrime(pvc *corev1.PersistentVolumeClaim, source client.Object, waitForFirstConsumer bool, updatePVCForPopulation pvcModifierFunc) (*corev1.PersistentVolumeClaim, error) {
labels := make(map[string]string) labels := make(map[string]string)
labels[common.CDILabelKey] = common.CDILabelValue labels[common.CDILabelKey] = common.CDILabelValue
labels[cc.LabelExcludeFromVeleroBackup] = "true"
annotations := make(map[string]string) annotations := make(map[string]string)
annotations[cc.AnnExcludeFromVeleroBackup] = "true"
annotations[cc.AnnImmediateBinding] = "" annotations[cc.AnnImmediateBinding] = ""
if waitForFirstConsumer { if waitForFirstConsumer {
annotations[cc.AnnSelectedNode] = pvc.Annotations[cc.AnnSelectedNode] annotations[cc.AnnSelectedNode] = pvc.Annotations[cc.AnnSelectedNode]

View File

@ -79,7 +79,7 @@ var _ = Describe("Datavolume controller reconcile loop", func() {
Expect(pvcPrime.GetAnnotations()[cc.AnnContentType]).To(Equal(contentType)) Expect(pvcPrime.GetAnnotations()[cc.AnnContentType]).To(Equal(contentType))
Expect(pvcPrime.GetAnnotations()[cc.AnnPreallocationRequested]).To(Equal(strconv.FormatBool(preallocation))) Expect(pvcPrime.GetAnnotations()[cc.AnnPreallocationRequested]).To(Equal(strconv.FormatBool(preallocation)))
Expect(pvcPrime.GetAnnotations()[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeUploadSourceRef)) Expect(pvcPrime.GetAnnotations()[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeUploadSourceRef))
Expect(pvcPrime.GetAnnotations()[cc.AnnExcludeFromVeleroBackup]).To(Equal("true")) Expect(pvcPrime.GetLabels()[cc.LabelExcludeFromVeleroBackup]).To(Equal("true"))
_, err = r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-pvc", Namespace: metav1.NamespaceDefault}}) _, err = r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "test-pvc", Namespace: metav1.NamespaceDefault}})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -326,8 +326,8 @@ var _ = Describe("Datavolume controller reconcile loop", func() {
Expect(pvcPrime.GetAnnotations()[cc.AnnImmediateBinding]).To(Equal("")) Expect(pvcPrime.GetAnnotations()[cc.AnnImmediateBinding]).To(Equal(""))
Expect(pvcPrime.GetAnnotations()[cc.AnnUploadRequest]).To(Equal("")) Expect(pvcPrime.GetAnnotations()[cc.AnnUploadRequest]).To(Equal(""))
Expect(pvcPrime.GetAnnotations()[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeUploadSourceRef)) Expect(pvcPrime.GetAnnotations()[cc.AnnPopulatorKind]).To(Equal(cdiv1.VolumeUploadSourceRef))
Expect(pvcPrime.GetAnnotations()[cc.AnnExcludeFromVeleroBackup]).To(Equal("true"))
Expect(pvcPrime.Annotations[key]).To(Equal(expectedValue)) Expect(pvcPrime.Annotations[key]).To(Equal(expectedValue))
Expect(pvcPrime.GetLabels()[cc.LabelExcludeFromVeleroBackup]).To(Equal("true"))
}, },
Entry("No extra annotations", "", "", ""), Entry("No extra annotations", "", "", ""),
Entry("Invalid extra annotation is not passed", "invalid", "test", ""), Entry("Invalid extra annotation is not passed", "invalid", "test", ""),