diff --git a/changelogs/unreleased/5429-reasonerjt b/changelogs/unreleased/5429-reasonerjt new file mode 100644 index 000000000..2fdd8fe8d --- /dev/null +++ b/changelogs/unreleased/5429-reasonerjt @@ -0,0 +1 @@ +Skip the exclusion check for additional resources returned by BIA \ No newline at end of file diff --git a/pkg/backup/backup.go b/pkg/backup/backup.go index 0b00417fd..ba20ed0d4 100644 --- a/pkg/backup/backup.go +++ b/pkg/backup/backup.go @@ -416,7 +416,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers(log logrus.FieldLogger, } func (kb *kubernetesBackupper) backupItem(log logrus.FieldLogger, gr schema.GroupResource, itemBackupper *itemBackupper, unstructured *unstructured.Unstructured, preferredGVR schema.GroupVersionResource) bool { - backedUpItem, err := itemBackupper.backupItem(log, unstructured, gr, preferredGVR) + backedUpItem, err := itemBackupper.backupItem(log, unstructured, gr, preferredGVR, false) if aggregate, ok := err.(kubeerrs.Aggregate); ok { log.WithField("name", unstructured.GetName()).Infof("%d errors encountered backup up item", len(aggregate.Errors())) // log each error separately so we get error location info in the log, and an diff --git a/pkg/backup/item_backupper.go b/pkg/backup/item_backupper.go index 879f4d70c..0e24fb32c 100644 --- a/pkg/backup/item_backupper.go +++ b/pkg/backup/item_backupper.go @@ -24,6 +24,8 @@ import ( "strings" "time" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "github.com/pkg/errors" "github.com/sirupsen/logrus" corev1api "k8s.io/api/core/v1" @@ -47,6 +49,11 @@ import ( "github.com/vmware-tanzu/velero/pkg/volume" ) +const ( + mustIncludeAdditionalItemAnnotation = "backup.velero.io/must-include-additional-items" + excludeFromBackupLabel = "velero.io/exclude-from-backup" +) + // itemBackupper can back up individual items to a tar writer. type itemBackupper struct { backupRequest *Request @@ -61,16 +68,11 @@ type itemBackupper struct { snapshotLocationVolumeSnapshotters map[string]vsv1.VolumeSnapshotter } -const ( - // veleroExcludeFromBackupLabel labeled item should be exclude by velero in backup job. - veleroExcludeFromBackupLabel = "velero.io/exclude-from-backup" -) - // backupItem backs up an individual item to tarWriter. The item may be excluded based on the // namespaces IncludesExcludes list. // In addition to the error return, backupItem also returns a bool indicating whether the item // was actually backed up. -func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, preferredGVR schema.GroupVersionResource) (bool, error) { +func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, preferredGVR schema.GroupVersionResource, mustInclude bool) (bool, error) { metadata, err := meta.Accessor(obj) if err != nil { return false, err @@ -83,28 +85,30 @@ func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstr log = log.WithField("resource", groupResource.String()) log = log.WithField("namespace", namespace) - if metadata.GetLabels()[veleroExcludeFromBackupLabel] == "true" { - log.Infof("Excluding item because it has label %s=true", veleroExcludeFromBackupLabel) - return false, nil - } + if mustInclude { + log.Infof("Skipping the exclusion checks for this resource") + } else { + if metadata.GetLabels()[excludeFromBackupLabel] == "true" { + log.Infof("Excluding item because it has label %s=true", excludeFromBackupLabel) + return false, nil + } + // NOTE: we have to re-check namespace & resource includes/excludes because it's possible that + // backupItem can be invoked by a custom action. + if namespace != "" && !ib.backupRequest.NamespaceIncludesExcludes.ShouldInclude(namespace) { + log.Info("Excluding item because namespace is excluded") + return false, nil + } + // NOTE: we specifically allow namespaces to be backed up even if IncludeClusterResources is + // false. + if namespace == "" && groupResource != kuberesource.Namespaces && ib.backupRequest.Spec.IncludeClusterResources != nil && !*ib.backupRequest.Spec.IncludeClusterResources { + log.Info("Excluding item because resource is cluster-scoped and backup.spec.includeClusterResources is false") + return false, nil + } - // NOTE: we have to re-check namespace & resource includes/excludes because it's possible that - // backupItem can be invoked by a custom action. - if namespace != "" && !ib.backupRequest.NamespaceIncludesExcludes.ShouldInclude(namespace) { - log.Info("Excluding item because namespace is excluded") - return false, nil - } - - // NOTE: we specifically allow namespaces to be backed up even if IncludeClusterResources is - // false. - if namespace == "" && groupResource != kuberesource.Namespaces && ib.backupRequest.Spec.IncludeClusterResources != nil && !*ib.backupRequest.Spec.IncludeClusterResources { - log.Info("Excluding item because resource is cluster-scoped and backup.spec.includeClusterResources is false") - return false, nil - } - - if !ib.backupRequest.ResourceIncludesExcludes.ShouldInclude(groupResource.String()) { - log.Info("Excluding item because resource is excluded") - return false, nil + if !ib.backupRequest.ResourceIncludesExcludes.ShouldInclude(groupResource.String()) { + log.Info("Excluding item because resource is excluded") + return false, nil + } } if metadata.GetDeletionTimestamp() != nil { @@ -320,7 +324,8 @@ func (ib *itemBackupper) executeActions( if err != nil { return nil, errors.Wrapf(err, "error executing custom action (groupResource=%s, namespace=%s, name=%s)", groupResource.String(), namespace, name) } - obj = updatedItem + u := &unstructured.Unstructured{Object: updatedItem.UnstructuredContent()} + mustInclude := u.GetAnnotations()[mustIncludeAdditionalItemAnnotation] == "true" for _, additionalItem := range additionalItemIdentifiers { gvr, resource, err := ib.discoveryHelper.ResourceFor(additionalItem.GroupResource.WithVersion("")) @@ -334,6 +339,7 @@ func (ib *itemBackupper) executeActions( } item, err := client.Get(additionalItem.Name, metav1.GetOptions{}) + if apierrors.IsNotFound(err) { log.WithFields(logrus.Fields{ "groupResource": additionalItem.GroupResource, @@ -346,12 +352,17 @@ func (ib *itemBackupper) executeActions( return nil, errors.WithStack(err) } - if _, err = ib.backupItem(log, item, gvr.GroupResource(), gvr); err != nil { + if _, err = ib.backupItem(log, item, gvr.GroupResource(), gvr, mustInclude); err != nil { return nil, err } } + // remove the annotation as it's for communication between BIA and velero server, + // we don't want the resource be restored with this annotation. + if _, ok := u.GetAnnotations()[mustIncludeAdditionalItemAnnotation]; ok { + delete(u.GetAnnotations(), mustIncludeAdditionalItemAnnotation) + } + obj = u } - return obj, nil }