corso/src/pkg/store/backup.go
2023-10-06 11:36:00 -07:00

158 lines
3.5 KiB
Go

package store
import (
"context"
"github.com/alcionai/clues"
"github.com/kopia/kopia/repo/manifest"
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/path"
)
type queryFilters struct {
tags map[string]string
}
type FilterOption func(*queryFilters)
func (q *queryFilters) populate(qf ...FilterOption) {
if len(qf) == 0 {
return
}
q.tags = map[string]string{}
for _, fn := range qf {
fn(q)
}
}
// Service ensures the retrieved backups only match
// the specified service.
func Service(pst path.ServiceType) FilterOption {
return func(qf *queryFilters) {
qf.tags[model.ServiceTag] = pst.String()
}
}
func Reason(service path.ServiceType, category path.CategoryType) FilterOption {
return func(qf *queryFilters) {
qf.tags[backup.ServiceCatString(service, category)] = backup.DefaultTagValue
}
}
func Tenant(tenant string) FilterOption {
return func(qf *queryFilters) {
qf.tags[backup.TenantIDKey] = tenant
}
}
func ProtectedResource(resourceID string) FilterOption {
return func(qf *queryFilters) {
qf.tags[backup.ResourceIDKey] = resourceID
}
}
type (
BackupWrapper interface {
BackupGetterDeleter
GetBackups(
ctx context.Context,
filters ...FilterOption,
) ([]*backup.Backup, error)
}
BackupGetterDeleter interface {
BackupGetter
BackupDeleter
}
BackupGetter interface {
GetBackup(ctx context.Context, backupID model.StableID) (*backup.Backup, error)
}
BackupDeleter interface {
DeleteBackup(ctx context.Context, backupID model.StableID) error
}
ModelDeleter interface {
DeleteWithModelStoreIDs(ctx context.Context, ids ...manifest.ID) error
}
BackupGetterModelDeleter interface {
BackupGetter
ModelDeleter
}
Storer interface {
Delete(ctx context.Context, s model.Schema, id model.StableID) error
Get(ctx context.Context, s model.Schema, id model.StableID, data model.Model) error
GetIDsForType(ctx context.Context, s model.Schema, tags map[string]string) ([]*model.BaseModel, error)
GetWithModelStoreID(ctx context.Context, s model.Schema, id manifest.ID, data model.Model) error
Put(ctx context.Context, s model.Schema, m model.Model) error
Update(ctx context.Context, s model.Schema, m model.Model) error
ModelDeleter
}
BackupStorer interface {
Storer
BackupWrapper
}
)
type wrapper struct {
Storer
}
func NewWrapper(s Storer) *wrapper {
return &wrapper{Storer: s}
}
// GetBackup gets a single backup by id.
func (w wrapper) GetBackup(ctx context.Context, backupID model.StableID) (*backup.Backup, error) {
b := backup.Backup{}
err := w.Get(ctx, model.BackupSchema, backupID, &b)
if err != nil {
return nil, clues.Wrap(err, "getting backup")
}
return &b, nil
}
// GetDetailsFromBackupID retrieves all backups in the model store.
func (w wrapper) GetBackups(
ctx context.Context,
filters ...FilterOption,
) ([]*backup.Backup, error) {
q := &queryFilters{}
q.populate(filters...)
bms, err := w.GetIDsForType(ctx, model.BackupSchema, q.tags)
if err != nil {
return nil, err
}
bs := make([]*backup.Backup, len(bms))
for i, bm := range bms {
b := &backup.Backup{}
err := w.GetWithModelStoreID(ctx, model.BackupSchema, bm.ModelStoreID, b)
if err != nil {
return nil, err
}
bs[i] = b
}
return bs, nil
}
// DeleteBackup deletes the backup and its details entry from the model store.
func (w wrapper) DeleteBackup(ctx context.Context, backupID model.StableID) error {
return w.Delete(ctx, model.BackupSchema, backupID)
}