Switch empty-folder cleanup to bucket policy (#8292)
* Fix Spark _temporary cleanup and add issue #8285 regression test * Generalize empty folder cleanup for Spark temp artifacts * Revert synchronous folder pruning and add cleanup diagnostics * Add actionable empty-folder cleanup diagnostics * Fix Spark temp marker cleanup in async folder cleaner * Fix Spark temp cleanup with implicit directory markers * Keep explicit directory markers non-implicit * logging * more logs * Switch empty-folder cleanup to bucket policy * Seaweed-X-Amz-Allow-Empty-Folders * less logs * go vet * less logs * refactoring
This commit is contained in:
33
weed/util/buckets.go
Normal file
33
weed/util/buckets.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package util
|
||||
|
||||
import "strings"
|
||||
|
||||
// ExtractBucketPath returns the bucket path under basePath that contains target.
|
||||
// If requireChild is true, the target must include additional segments beyond the bucket itself.
|
||||
func ExtractBucketPath(basePath, target string, requireChild bool) (string, bool) {
|
||||
cleanBase := strings.TrimSuffix(basePath, "/")
|
||||
if cleanBase == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
prefix := cleanBase + "/"
|
||||
if !strings.HasPrefix(target, prefix) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
rest := strings.TrimPrefix(target, prefix)
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
bucketName, _, found := strings.Cut(rest, "/")
|
||||
if bucketName == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if requireChild && !found {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return prefix + bucketName, true
|
||||
}
|
||||
63
weed/util/buckets_test.go
Normal file
63
weed/util/buckets_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package util
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestExtractBucketPath(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
base string
|
||||
target string
|
||||
requireChild bool
|
||||
expected string
|
||||
ok bool
|
||||
}{
|
||||
{
|
||||
name: "child paths return bucket",
|
||||
base: "/buckets",
|
||||
target: "/buckets/test/folder/file",
|
||||
requireChild: true,
|
||||
expected: "/buckets/test",
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
name: "bucket root without child fails when required",
|
||||
base: "/buckets",
|
||||
target: "/buckets/test",
|
||||
requireChild: true,
|
||||
ok: false,
|
||||
},
|
||||
{
|
||||
name: "bucket root allowed when not required",
|
||||
base: "/buckets",
|
||||
target: "/buckets/test",
|
||||
requireChild: false,
|
||||
expected: "/buckets/test",
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
name: "path outside buckets fails",
|
||||
base: "/buckets",
|
||||
target: "/data/test/folder",
|
||||
requireChild: true,
|
||||
ok: false,
|
||||
},
|
||||
{
|
||||
name: "trailing slash on base is normalized",
|
||||
base: "/buckets/",
|
||||
target: "/buckets/test/sub",
|
||||
requireChild: true,
|
||||
expected: "/buckets/test",
|
||||
ok: true,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, ok := ExtractBucketPath(tt.base, tt.target, tt.requireChild)
|
||||
if ok != tt.ok {
|
||||
t.Fatalf("expected ok=%v, got %v", tt.ok, ok)
|
||||
}
|
||||
if got != tt.expected {
|
||||
t.Fatalf("expected path %q, got %q", tt.expected, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user