Skip to content

Commit 94dd98d

Browse files
authored
S3: deprecate PrefixFolders and introduce HideFolders (#62)
* s3: deprecate PrefixFolders and introduce HideFolders * s3: check suffix only for HideFolders * s3: add separate test func for HideFolders * s3: add details about use of folders in HideFolders doc comment
1 parent 223250b commit 94dd98d

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

backends/s3/s3.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,22 @@ type Options struct {
7878

7979
// PrefixFolders can be enabled to make List operations show nested prefixes as folders
8080
// instead of recursively listing all contents of nested prefixes
81+
//
82+
// Deprecated: This option does not reflect our desire to treat blob names as keys.
83+
// Please do not use it.
8184
PrefixFolders bool `yaml:"prefix_folders"`
8285

86+
// HideFolders is an S3-specific optimization, allowing to hide all keys that
87+
// have a separator '/' in their names.
88+
// In case a prefix representing a folder is provided to List,
89+
// that folder will be explored, and its subfolders hidden.
90+
//
91+
// Moreover, please note that regardless of this option,
92+
// working with folders with S3 is flaky,
93+
// because a `foo` key will shadow all `foo/*` keys while listing,
94+
// even though those `foo/*` keys exist and they hold the values they're expected to.
95+
HideFolders bool `yaml:"hide_folders"`
96+
8397
// EndpointURL can be set to something like "http://localhost:9000" when using Minio
8498
// or "https://s3.amazonaws.com" for AWS S3.
8599
EndpointURL string `yaml:"endpoint_url"`
@@ -201,7 +215,7 @@ func (b *Backend) doList(ctx context.Context, prefix string) (simpleblob.BlobLis
201215

202216
objCh := b.client.ListObjects(ctx, b.opt.Bucket, minio.ListObjectsOptions{
203217
Prefix: prefix,
204-
Recursive: !b.opt.PrefixFolders,
218+
Recursive: !b.opt.PrefixFolders && !b.opt.HideFolders,
205219
})
206220
for obj := range objCh {
207221
// Handle error returned by MinIO client
@@ -216,6 +230,10 @@ func (b *Backend) doList(ctx context.Context, prefix string) (simpleblob.BlobLis
216230
continue
217231
}
218232

233+
if b.opt.HideFolders && strings.HasSuffix(obj.Key, "/") {
234+
continue
235+
}
236+
219237
// Strip global prefix from blob
220238
blobName := obj.Key
221239
if gpEndIndex > 0 {

backends/s3/s3_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ func TestBackend_globalPrefixAndMarker(t *testing.T) {
127127
}
128128

129129
func TestBackend_recursive(t *testing.T) {
130+
// NB: Those tests are for PrefixFolders, a deprecated option.
131+
130132
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
131133
defer cancel()
132134

@@ -166,3 +168,40 @@ func TestBackend_recursive(t *testing.T) {
166168

167169
assert.Len(t, b.lastMarker, 0)
168170
}
171+
172+
func TestHideFolders(t *testing.T) {
173+
// NB: working with folders with S3 is flaky, because a `foo` key
174+
// will shadow all `foo/*` keys while listing,
175+
// even though those `foo/*` keys exist and they hold the values they're expected to.
176+
177+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
178+
defer cancel()
179+
180+
b := getBackend(ctx, t)
181+
b.opt.HideFolders = true
182+
183+
p := []byte("123")
184+
err := b.Store(ctx, "foo", p)
185+
assert.NoError(t, err)
186+
err = b.Store(ctx, "bar/baz", p)
187+
assert.NoError(t, err)
188+
189+
t.Run("at root", func(t *testing.T) {
190+
ls, err := b.List(ctx, "")
191+
assert.NoError(t, err)
192+
assert.Equal(t, []string{"foo"}, ls.Names())
193+
})
194+
195+
t.Run("with List prefix", func(t *testing.T) {
196+
ls, err := b.List(ctx, "bar/")
197+
assert.NoError(t, err)
198+
assert.Equal(t, []string{"bar/baz"}, ls.Names())
199+
})
200+
201+
t.Run("with global prefix", func(t *testing.T) {
202+
b.setGlobalPrefix("bar/")
203+
ls, err := b.List(ctx, "")
204+
assert.NoError(t, err)
205+
assert.Equal(t, []string{"baz"}, ls.Names())
206+
})
207+
}

0 commit comments

Comments
 (0)