Allow getting a path prefix from a string (#4132)

Will be required for selective subtree pruning since hierarchy merging starts at the category directory.

---

#### Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No

#### Type of change

- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #4117

#### Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2023-09-18 16:05:10 -07:00 committed by GitHub
parent 4a9951b876
commit 8b9f63879b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 8 deletions

View File

@ -185,11 +185,7 @@ func BuildPrefix(
}, nil
}
// FromDataLayerPath parses the escaped path p, validates the elements in p
// match a resource-specific path format, and returns a Path struct for that
// resource-specific type. If p does not match any resource-specific paths or
// is malformed returns an error.
func FromDataLayerPath(p string, isItem bool) (Path, error) {
func pathFromDataLayerPath(p string, isItem bool, minElements int) (Path, error) {
p = TrimTrailingSlash(p)
// If p was just the path separator then it will be empty now.
if len(p) == 0 {
@ -202,15 +198,21 @@ func FromDataLayerPath(p string, isItem bool) (Path, error) {
return nil, clues.Stack(errParsingPath, err).With("path_string", p)
}
if len(pb.elements) < 5 {
return nil, clues.New("path has too few segments").With("path_string", p)
if len(pb.elements) < minElements {
return nil, clues.New(
"missing required tenant, service, category, protected resource ID, or non-prefix segment").
With("path_string", pb)
}
service, category, err := validateServiceAndCategoryStrings(
pb.elements[1],
pb.elements[3])
if err != nil {
return nil, clues.Stack(errParsingPath, err).With("path_string", p)
return nil, clues.Stack(errParsingPath, err).With("path_string", pb)
}
if err := verifyInputValues(pb.elements[0], pb.elements[2]); err != nil {
return nil, clues.Stack(err).With("path_string", pb)
}
return &dataLayerResourcePath{
@ -221,6 +223,20 @@ func FromDataLayerPath(p string, isItem bool) (Path, error) {
}, nil
}
func PrefixOrPathFromDataLayerPath(p string, isItem bool) (Path, error) {
res, err := pathFromDataLayerPath(p, isItem, 4)
return res, clues.Stack(err).OrNil()
}
// FromDataLayerPath parses the escaped path p, validates the elements in p
// match a resource-specific path format, and returns a Path struct for that
// resource-specific type. If p does not match any resource-specific paths or
// is malformed returns an error.
func FromDataLayerPath(p string, isItem bool) (Path, error) {
res, err := pathFromDataLayerPath(p, isItem, 5)
return res, clues.Stack(err).OrNil()
}
// TrimTrailingSlash takes an escaped path element and returns an escaped path
// element with the trailing path separator character(s) removed if they were not
// escaped. If there were no trailing path separator character(s) or the separator(s)

View File

@ -426,6 +426,26 @@ func (suite *PathUnitSuite) TestFromDataLayerPath() {
}
}
func (suite *PathUnitSuite) TestPrefixOrPathFromDataLayerPath() {
t := suite.T()
input := fmt.Sprintf(
"%s/%s/%s/%s",
"tenant",
ExchangeService.String(),
"user",
EmailCategory.String())
// Check that we can make a valid prefix path.
p, err := PrefixOrPathFromDataLayerPath(input, false)
assert.NoError(t, err, clues.ToCore(err))
assert.Equal(t, input, p.String())
// Check we can't make a regular path with the same input since it doesn't
// have enough segments.
_, err = FromDataLayerPath(input, false)
assert.Error(t, err)
}
func (suite *PathUnitSuite) TestBuildPrefix() {
table := []struct {
name string