167 lines
4.4 KiB
Go
167 lines
4.4 KiB
Go
package onedrive
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/alcionai/clues"
|
|
|
|
"github.com/alcionai/corso/src/internal/common/prefixmatcher"
|
|
"github.com/alcionai/corso/src/internal/data"
|
|
"github.com/alcionai/corso/src/internal/m365/collection/drive"
|
|
"github.com/alcionai/corso/src/internal/m365/support"
|
|
"github.com/alcionai/corso/src/internal/observe"
|
|
"github.com/alcionai/corso/src/internal/operations/inject"
|
|
"github.com/alcionai/corso/src/internal/version"
|
|
"github.com/alcionai/corso/src/pkg/account"
|
|
"github.com/alcionai/corso/src/pkg/count"
|
|
"github.com/alcionai/corso/src/pkg/fault"
|
|
"github.com/alcionai/corso/src/pkg/logger"
|
|
"github.com/alcionai/corso/src/pkg/path"
|
|
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
|
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
|
|
)
|
|
|
|
type oneDriveBackup struct{}
|
|
|
|
// NewBackup provides a struct that matches standard apis
|
|
// across m365/service handlers.
|
|
func NewBackup() *oneDriveBackup {
|
|
return &oneDriveBackup{}
|
|
}
|
|
|
|
func (oneDriveBackup) ProduceBackupCollections(
|
|
ctx context.Context,
|
|
bpc inject.BackupProducerConfig,
|
|
ac api.Client,
|
|
creds account.M365Config,
|
|
su support.StatusUpdater,
|
|
counter *count.Bus,
|
|
errs *fault.Bus,
|
|
) ([]data.BackupCollection, *prefixmatcher.StringSetMatcher, bool, error) {
|
|
odb, err := bpc.Selector.ToOneDriveBackup()
|
|
if err != nil {
|
|
return nil, nil, false, clues.WrapWC(ctx, err, "parsing selector")
|
|
}
|
|
|
|
var (
|
|
el = errs.Local()
|
|
tenantID = creds.AzureTenantID
|
|
categories = map[path.CategoryType]struct{}{}
|
|
collections = []data.BackupCollection{}
|
|
ssmb = prefixmatcher.NewStringSetBuilder()
|
|
odcs []data.BackupCollection
|
|
canUsePreviousBackup bool
|
|
)
|
|
|
|
// for each scope that includes oneDrive items, get all
|
|
for _, scope := range odb.Scopes() {
|
|
if el.Failure() != nil {
|
|
break
|
|
}
|
|
|
|
logger.Ctx(ctx).Debug("creating OneDrive collections")
|
|
|
|
nc := drive.NewCollections(
|
|
drive.NewUserDriveBackupHandler(ac.Drives(), bpc.ProtectedResource.ID(), scope),
|
|
tenantID,
|
|
bpc.ProtectedResource,
|
|
su,
|
|
bpc.Options,
|
|
counter)
|
|
|
|
progressMessage := observe.MessageWithCompletion(
|
|
ctx,
|
|
observe.ProgressCfg{
|
|
Indent: 1,
|
|
CompletionMessage: func() string { return fmt.Sprintf("(found %d files)", nc.NumFiles) },
|
|
},
|
|
path.FilesCategory.HumanString())
|
|
defer close(progressMessage)
|
|
|
|
odcs, canUsePreviousBackup, err = nc.Get(ctx, bpc.MetadataCollections, ssmb, errs)
|
|
if err != nil {
|
|
el.AddRecoverable(ctx, clues.Stack(err).Label(fault.LabelForceNoBackupCreation))
|
|
}
|
|
|
|
categories[scope.Category().PathType()] = struct{}{}
|
|
|
|
collections = append(collections, odcs...)
|
|
}
|
|
|
|
mcs, err := migrationCollections(bpc, tenantID, su, counter)
|
|
if err != nil {
|
|
return nil, nil, false, err
|
|
}
|
|
|
|
collections = append(collections, mcs...)
|
|
|
|
if len(collections) > 0 {
|
|
baseCols, err := graph.BaseCollections(
|
|
ctx,
|
|
collections,
|
|
tenantID,
|
|
bpc.ProtectedResource.ID(),
|
|
path.OneDriveService,
|
|
categories,
|
|
su,
|
|
counter,
|
|
errs)
|
|
if err != nil {
|
|
return nil, nil, false, err
|
|
}
|
|
|
|
collections = append(collections, baseCols...)
|
|
}
|
|
|
|
logger.Ctx(ctx).Infow("produced collections", "stats", counter.Values())
|
|
|
|
return collections, ssmb.ToReader(), canUsePreviousBackup, el.Failure()
|
|
}
|
|
|
|
// adds data migrations to the collection set.
|
|
func migrationCollections(
|
|
bpc inject.BackupProducerConfig,
|
|
tenant string,
|
|
su support.StatusUpdater,
|
|
counter *count.Bus,
|
|
) ([]data.BackupCollection, error) {
|
|
// assume a version < 0 implies no prior backup, thus nothing to migrate.
|
|
if version.IsNoBackup(bpc.LastBackupVersion) {
|
|
return nil, nil
|
|
}
|
|
|
|
if bpc.LastBackupVersion >= version.All8MigrateUserPNToID {
|
|
return nil, nil
|
|
}
|
|
|
|
counter.Inc(count.RequiresUserPnToIDMigration)
|
|
|
|
// unlike exchange, which enumerates all folders on every
|
|
// backup, onedrive needs to force the owner PN -> ID migration
|
|
mc, err := path.BuildPrefix(
|
|
tenant,
|
|
bpc.ProtectedResource.ID(),
|
|
path.OneDriveService,
|
|
path.FilesCategory)
|
|
if err != nil {
|
|
return nil, clues.Wrap(err, "creating user id migration path")
|
|
}
|
|
|
|
mpc, err := path.BuildPrefix(
|
|
tenant,
|
|
bpc.ProtectedResource.Name(),
|
|
path.OneDriveService,
|
|
path.FilesCategory)
|
|
if err != nil {
|
|
return nil, clues.Wrap(err, "creating user name migration path")
|
|
}
|
|
|
|
mgn, err := graph.NewPrefixCollection(mpc, mc, su, counter)
|
|
if err != nil {
|
|
return nil, clues.Wrap(err, "creating migration collection")
|
|
}
|
|
|
|
return []data.BackupCollection{mgn}, nil
|
|
}
|