Add a way to get lineage info from a backup

Add a helper function that deserializes persisted lineage information
and returns it in a nicer form.
This commit is contained in:
Ashlie Martinez 2023-10-04 15:55:18 -07:00
parent d1fba10aeb
commit 2295c5cc20
2 changed files with 99 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/alcionai/clues"
"github.com/dustin/go-humanize"
"github.com/alcionai/corso/src/cli/print"
@ -14,6 +15,7 @@ import (
"github.com/alcionai/corso/src/internal/common/str"
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/internal/stats"
"github.com/alcionai/corso/src/pkg/backup/identity"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/selectors"
)
@ -180,6 +182,66 @@ func New(
return b
}
// PersistedBaseSet contains information extracted from the backup model
// relating to its lineage. It only contains the backup ID and Reasons each
// base was selected instead of the full set of information contained in other
// structs like BackupBases.
type PersistedBaseSet struct {
Merge map[model.StableID][]identity.Reasoner
Assist map[model.StableID][]identity.Reasoner
}
func (b Backup) Bases() (PersistedBaseSet, error) {
res := PersistedBaseSet{
Merge: map[model.StableID][]identity.Reasoner{},
Assist: map[model.StableID][]identity.Reasoner{},
}
for id, reasons := range b.MergeBases {
for _, reason := range reasons {
service, cat, err := serviceCatStringToTypes(reason)
if err != nil {
return res, clues.Wrap(err, "getting Reason info").With(
"base_type", "merge",
"base_backup_id", id,
"input_string", reason)
}
res.Merge[id] = append(res.Merge[id], identity.NewReason(
// Tenant ID not currently stored in backup model.
"",
str.First(
b.ProtectedResourceID,
b.Selector.DiscreteOwner),
service,
cat))
}
}
for id, reasons := range b.AssistBases {
for _, reason := range reasons {
service, cat, err := serviceCatStringToTypes(reason)
if err != nil {
return res, clues.Wrap(err, "getting Reason info").With(
"base_type", "assist",
"base_backup_id", id,
"input_string", reason)
}
res.Assist[id] = append(res.Assist[id], identity.NewReason(
// Tenant ID not currently stored in backup model.
"",
str.First(
b.ProtectedResourceID,
b.Selector.DiscreteOwner),
service,
cat))
}
}
return res, nil
}
// --------------------------------------------------------------------------------
// CLI Output
// --------------------------------------------------------------------------------

View File

@ -2,7 +2,9 @@ package backup
import (
"context"
"strings"
"github.com/alcionai/clues"
"github.com/kopia/kopia/repo/manifest"
"github.com/kopia/kopia/snapshot"
@ -40,6 +42,41 @@ func serviceCatString(
return serviceCatPrefix + service.String() + separator + category.String()
}
func serviceCatStringToTypes(
input string,
) (path.ServiceType, path.CategoryType, error) {
trimmed := strings.TrimPrefix(input, serviceCatPrefix)
// No prefix found -> unexpected format.
if trimmed == input {
return path.UnknownService,
path.UnknownCategory,
clues.New("missing tag prefix")
}
parts := strings.Split(trimmed, separator)
if len(parts) != 2 {
return path.UnknownService,
path.UnknownCategory,
clues.New("missing tag separator")
}
cat := path.ToCategoryType(parts[1])
if cat == path.UnknownCategory {
return path.UnknownService,
path.UnknownCategory,
clues.New("parsing category").With("input_category", parts[1])
}
service := path.ToServiceType(parts[0])
if service == path.UnknownService {
return path.UnknownService,
path.UnknownCategory,
clues.New("parsing service").With("input_service", parts[0])
}
return service, cat, nil
}
// reasonTags returns the set of key-value pairs that can be used as tags to
// represent this Reason.
// nolint