Create path categories for metadata folders (#1718)
## Description Corso needs to store some transient information between backups so that it can perform more efficient incremental backups. This transient information will live at a path `tenant-id/service/user-id/categoryMetadata`. This patch adds an initializer, category enums, and tests for these new path locations ## Type of change <!--- Please check the type of change your PR introduces: ---> - [x] 🌻 Feature - [ ] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Test - [ ] 💻 CI/Deployment - [ ] 🐹 Trivial/Minor ## Issue(s) * #1685 ## Test Plan <!-- How will this be tested prior to merging.--> - [ ] 💪 Manual - [x] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
24f60af404
commit
5c7d2168fc
@ -250,7 +250,7 @@ func (pb Builder) join(start, end int) string {
|
||||
return join(pb.elements[start:end])
|
||||
}
|
||||
|
||||
func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
||||
func verifyInputValues(tenant, resourceOwner string) error {
|
||||
if len(tenant) == 0 {
|
||||
return errors.Wrap(errMissingSegment, "tenant")
|
||||
}
|
||||
@ -259,6 +259,14 @@ func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
||||
return errors.Wrap(errMissingSegment, "resourceOwner")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
||||
if err := verifyInputValues(tenant, resourceOwner); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(pb.elements) == 0 {
|
||||
return errors.New("missing path beyond prefix")
|
||||
}
|
||||
@ -273,6 +281,48 @@ func (pb Builder) withPrefix(elements ...string) *Builder {
|
||||
return res
|
||||
}
|
||||
|
||||
func (pb Builder) ToServiceCategoryMetadataPath(
|
||||
tenant, user string,
|
||||
service ServiceType,
|
||||
category CategoryType,
|
||||
isItem bool,
|
||||
) (Path, error) {
|
||||
if err := validateServiceAndCategory(service, category); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := verifyInputValues(tenant, user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isItem && len(pb.elements) == 0 {
|
||||
return nil, errors.New("missing path beyond prefix")
|
||||
}
|
||||
|
||||
metadataService := UnknownService
|
||||
|
||||
switch service {
|
||||
case ExchangeService:
|
||||
metadataService = ExchangeMetadataService
|
||||
case OneDriveService:
|
||||
metadataService = OneDriveMetadataService
|
||||
case SharePointService:
|
||||
metadataService = SharePointMetadataService
|
||||
}
|
||||
|
||||
return &dataLayerResourcePath{
|
||||
Builder: *pb.withPrefix(
|
||||
tenant,
|
||||
metadataService.String(),
|
||||
user,
|
||||
category.String(),
|
||||
),
|
||||
service: metadataService,
|
||||
category: category,
|
||||
hasItem: isItem,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (pb Builder) ToDataLayerExchangePathForCategory(
|
||||
tenant, user string,
|
||||
category CategoryType,
|
||||
|
||||
@ -6,14 +6,27 @@ import (
|
||||
|
||||
var ErrorUnknownService = errors.New("unknown service string")
|
||||
|
||||
// ServiceType denotes what service the path corresponds to. Metadata services
|
||||
// are also included though they are only used for paths that house metadata for
|
||||
// Corso backups.
|
||||
//
|
||||
// Metadata services are not considered valid service types for resource paths
|
||||
// though they can be used for metadata paths.
|
||||
//
|
||||
// The order of the enums below can be changed, but the string representation of
|
||||
// each enum must remain the same or migration code needs to be added to handle
|
||||
// changes to the string format.
|
||||
type ServiceType int
|
||||
|
||||
//go:generate stringer -type=ServiceType -linecomment
|
||||
const (
|
||||
UnknownService ServiceType = iota
|
||||
ExchangeService // exchange
|
||||
OneDriveService // onedrive
|
||||
SharePointService // sharepoint
|
||||
UnknownService ServiceType = iota
|
||||
ExchangeService // exchange
|
||||
OneDriveService // onedrive
|
||||
SharePointService // sharepoint
|
||||
ExchangeMetadataService // exchangeMetadata
|
||||
OneDriveMetadataService // onedriveMetadata
|
||||
SharePointMetadataService // sharepointMetadata
|
||||
)
|
||||
|
||||
func toServiceType(service string) ServiceType {
|
||||
@ -24,6 +37,12 @@ func toServiceType(service string) ServiceType {
|
||||
return OneDriveService
|
||||
case SharePointService.String():
|
||||
return SharePointService
|
||||
case ExchangeMetadataService.String():
|
||||
return ExchangeMetadataService
|
||||
case OneDriveMetadataService.String():
|
||||
return OneDriveMetadataService
|
||||
case SharePointMetadataService.String():
|
||||
return SharePointMetadataService
|
||||
default:
|
||||
return UnknownService
|
||||
}
|
||||
@ -31,6 +50,10 @@ func toServiceType(service string) ServiceType {
|
||||
|
||||
var ErrorUnknownCategory = errors.New("unknown category string")
|
||||
|
||||
// CategoryType denotes what category of data the path corresponds to. The order
|
||||
// of the enums below can be changed, but the string representation of each enum
|
||||
// must remain the same or migration code needs to be added to handle changes to
|
||||
// the string format.
|
||||
type CategoryType int
|
||||
|
||||
//go:generate stringer -type=CategoryType -linecomment
|
||||
@ -63,7 +86,8 @@ func ToCategoryType(category string) CategoryType {
|
||||
}
|
||||
}
|
||||
|
||||
// serviceCategories is a mapping of all valid service/category pairs.
|
||||
// serviceCategories is a mapping of all valid service/category pairs for
|
||||
// non-metadata paths.
|
||||
var serviceCategories = map[ServiceType]map[CategoryType]struct{}{
|
||||
ExchangeService: {
|
||||
EmailCategory: {},
|
||||
|
||||
@ -233,6 +233,101 @@ func (suite *DataLayerResourcePath) TestDir() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *DataLayerResourcePath) TestToServiceCategoryMetadataPath() {
|
||||
tenant := "a-tenant"
|
||||
user := "a-user"
|
||||
table := []struct {
|
||||
name string
|
||||
service path.ServiceType
|
||||
category path.CategoryType
|
||||
postfix []string
|
||||
expectedService path.ServiceType
|
||||
check assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "NoPostfixPasses",
|
||||
service: path.ExchangeService,
|
||||
category: path.EmailCategory,
|
||||
expectedService: path.ExchangeMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "PostfixPasses",
|
||||
service: path.ExchangeService,
|
||||
category: path.EmailCategory,
|
||||
postfix: []string{"a", "b"},
|
||||
expectedService: path.ExchangeMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "Fails",
|
||||
service: path.ExchangeService,
|
||||
category: path.FilesCategory,
|
||||
check: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "Passes",
|
||||
service: path.ExchangeService,
|
||||
category: path.ContactsCategory,
|
||||
expectedService: path.ExchangeMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "Passes",
|
||||
service: path.ExchangeService,
|
||||
category: path.EventsCategory,
|
||||
expectedService: path.ExchangeMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "Passes",
|
||||
service: path.OneDriveService,
|
||||
category: path.FilesCategory,
|
||||
expectedService: path.OneDriveMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "Passes",
|
||||
service: path.SharePointService,
|
||||
category: path.LibrariesCategory,
|
||||
expectedService: path.SharePointMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "Passes",
|
||||
service: path.SharePointService,
|
||||
category: path.ListsCategory,
|
||||
expectedService: path.SharePointMetadataService,
|
||||
check: assert.NoError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
suite.T().Run(strings.Join([]string{
|
||||
test.name,
|
||||
test.service.String(),
|
||||
test.category.String(),
|
||||
}, "_"), func(t *testing.T) {
|
||||
pb := path.Builder{}.Append(test.postfix...)
|
||||
p, err := pb.ToServiceCategoryMetadataPath(
|
||||
tenant,
|
||||
user,
|
||||
test.service,
|
||||
test.category,
|
||||
false,
|
||||
)
|
||||
|
||||
test.check(t, err)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, test.expectedService, p.Service())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *DataLayerResourcePath) TestToExchangePathForCategory() {
|
||||
b := path.Builder{}.Append(rest...)
|
||||
table := []struct {
|
||||
|
||||
@ -12,11 +12,14 @@ func _() {
|
||||
_ = x[ExchangeService-1]
|
||||
_ = x[OneDriveService-2]
|
||||
_ = x[SharePointService-3]
|
||||
_ = x[ExchangeMetadataService-4]
|
||||
_ = x[OneDriveMetadataService-5]
|
||||
_ = x[SharePointMetadataService-6]
|
||||
}
|
||||
|
||||
const _ServiceType_name = "UnknownServiceexchangeonedrivesharepoint"
|
||||
const _ServiceType_name = "UnknownServiceexchangeonedrivesharepointexchangeMetadataonedriveMetadatasharepointMetadata"
|
||||
|
||||
var _ServiceType_index = [...]uint8{0, 14, 22, 30, 40}
|
||||
var _ServiceType_index = [...]uint8{0, 14, 22, 30, 40, 56, 72, 90}
|
||||
|
||||
func (i ServiceType) String() string {
|
||||
if i < 0 || i >= ServiceType(len(_ServiceType_index)-1) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user