Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List dirs #56

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
603cdbf
[google] refactor object fetching code into an iterator
alice-sawatzky Aug 7, 2020
ab24eea
[google] add listFolders code
alice-sawatzky Aug 8, 2020
88b260a
[google] refactor the logic of ListObjects, ListFolders into generic …
alice-sawatzky Aug 8, 2020
108b03d
[google] add ListFolders test
alice-sawatzky Aug 10, 2020
48c1eeb
[alibaba] add ListFolders, tests
alice-sawatzky Aug 10, 2020
5555f5c
[alibaba_test/ListFolders] fix
alice-sawatzky Aug 10, 2020
4869e06
[amazon] add ListFolders, tests
alice-sawatzky Aug 10, 2020
ffad978
[amazon] fix typos
alice-sawatzky Aug 10, 2020
4a82cb9
[baidu] add ListFolders, tests
alice-sawatzky Aug 10, 2020
996c50b
[etcd] add ListFolders, tests
alice-sawatzky Aug 10, 2020
2c09f47
[etcd] remove ListFolders test
alice-sawatzky Aug 10, 2020
d3f46e8
[microsoft] add ListFolders, tests
alice-sawatzky Aug 10, 2020
431fa1f
[netease] add ListFolders, tests
alice-sawatzky Aug 10, 2020
70b198f
[oracle] add ListFolders, tests
alice-sawatzky Aug 10, 2020
42b2b13
[tencent] add ListFolders, tests
alice-sawatzky Aug 10, 2020
98d0da7
[local] add ListFolders, tests
alice-sawatzky Aug 10, 2020
bd59038
[storage/Backend] add ListFolder to interface
alice-sawatzky Aug 10, 2020
bdf4cb4
Revert "[etcd] remove ListFolders test"
alice-sawatzky Aug 10, 2020
af918bc
[openstack] add ListFolders, tests
alice-sawatzky Aug 10, 2020
adf7db8
[*/objectIter] close channel and exit goroutine promptly on error
alice-sawatzky Aug 10, 2020
17b5448
[alibaba_test] improve folder tests
alice-sawatzky Aug 10, 2020
784db0d
[amazon_test] improve ListFolder, ListObject tests
alice-sawatzky Aug 10, 2020
d6ed0ac
[baidu_test] improve ListFolder test
alice-sawatzky Aug 10, 2020
42828b0
[google] improve ListFolder, ListObject tests
alice-sawatzky Aug 10, 2020
34e68c3
[microsoft] improve ListFolder, ListObject tests
alice-sawatzky Aug 10, 2020
7d1b9ac
[netease] improve ListFolder test
alice-sawatzky Aug 10, 2020
ddadabf
[openstack] improve ListObject test, add missing ListFolder test
alice-sawatzky Aug 10, 2020
dc4810f
[oracle] improve ListFolder, ListObject tests
alice-sawatzky Aug 10, 2020
8f0f3c0
[tencent] improve ListFolder test
alice-sawatzky Aug 10, 2020
2b4d04f
[local] improve tests
alice-sawatzky Aug 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 37 additions & 27 deletions alibaba.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,38 +72,48 @@ func NewAlibabaCloudOSSBackend(bucket string, prefix string, endpoint string, ss
return b
}


// ListObjects lists all objects in Alibaba Cloud OSS bucket, at prefix
func (b AlibabaCloudOSSBackend) ListObjects(prefix string) ([]Object, error) {
var objects []Object

prefix = pathutil.Join(b.Prefix, prefix)
ossPrefix := oss.Prefix(prefix)
marker := oss.Marker("")
for {
lor, err := b.Bucket.ListObjects(oss.MaxKeys(50), marker, ossPrefix)
if err != nil {
return objects, err
}
for _, obj := range lor.Objects {
path := removePrefixFromObjectPath(prefix, obj.Key)
if objectPathIsInvalid(path) {
continue
return getObjects(b, prefix)
}

// ListFolders lists all folders in Alibaba Cloud OSS bucket, at prefix
func (b AlibabaCloudOSSBackend) ListFolders(prefix string) ([]Folder, error) {
return getFolders(b, prefix)
}

func (b AlibabaCloudOSSBackend) ObjectIter(prefix string) <-chan Item {
ch := make(chan(Item))
go func() {
prefix = pathutil.Join(b.Prefix, prefix)
ossPrefix := oss.Prefix(prefix)
marker := oss.Marker("")
for {
lor, err := b.Bucket.ListObjects(oss.MaxKeys(50), marker, ossPrefix)
if err != nil {
ch <- Item{nil, err}
close(ch)
return
}
object := Object{
Path: path,
Content: []byte{},
LastModified: obj.LastModified,
for _, obj := range lor.Objects {
path := removePrefixFromObjectPath(prefix, obj.Key)
ch <- Item{
&Object{
Path: path,
Content: []byte{},
LastModified: obj.LastModified,
}, nil }
}
objects = append(objects, object)
}
if !lor.IsTruncated {
break
if !lor.IsTruncated {
break
}
ossPrefix = oss.Prefix(lor.Prefix)
marker = oss.Marker(lor.NextMarker)
}
ossPrefix = oss.Prefix(lor.Prefix)
marker = oss.Marker(lor.NextMarker)
}

return objects, nil
close(ch)
} ()
return ch
}

// GetObject retrieves an object from Alibaba Cloud OSS bucket, at prefix
Expand Down
41 changes: 34 additions & 7 deletions alibaba_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ limitations under the License.
package storage

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/suite"
"strconv"
)

type AlibabaTestSuite struct {
Expand Down Expand Up @@ -49,25 +49,39 @@ func (suite *AlibabaTestSuite) SetupSuite() {
path := "deleteme.txt"

for i := 0; i < testCount; i++ {
newPath := strconv.Itoa(i) + path
err := suite.NoPrefixAlibabaOSSBackend.PutObject(newPath, data)
testFilePath := fmt.Sprintf("%d%s", i, path)
testDirFilePath := fmt.Sprintf("testdir%d/%s", i, path)
err := suite.NoPrefixAlibabaOSSBackend.PutObject(testFilePath, data)
suite.Nil(err, "no error putting deleteme.txt using Alibaba Cloud OSS backend")

err = suite.SSEAlibabaOSSBackend.PutObject(newPath, data)
err = suite.NoPrefixAlibabaOSSBackend.PutObject(testDirFilePath, data)
suite.Nil(err, "no error putting testdir/deleteme.txt using Alibaba Cloud OSS backend")

err = suite.SSEAlibabaOSSBackend.PutObject(testFilePath, data)
suite.Nil(err, "no error putting deleteme.txt using Alibaba Cloud OSS backend (SSE)")

err = suite.SSEAlibabaOSSBackend.PutObject(testDirFilePath, data)
suite.Nil(err, "no error putting testdir/deleteme.txt using Alibaba Cloud OSS backend (SSE)")
}
}

func (suite *AlibabaTestSuite) TearDownSuite() {
path := "deleteme.txt"
for i := 0; i < testCount; i++ {
newPath := strconv.Itoa(i) + path
testFilePath := fmt.Sprintf("%d%s", i, path)
testDirFilePath := fmt.Sprintf("testdir%d/%s", i, path)

err := suite.NoPrefixAlibabaOSSBackend.DeleteObject(newPath)
err := suite.NoPrefixAlibabaOSSBackend.DeleteObject(testFilePath)
suite.Nil(err, "no error deleting deleteme.txt using AlibabaOSS backend")

err = suite.SSEAlibabaOSSBackend.DeleteObject(newPath)
err = suite.NoPrefixAlibabaOSSBackend.DeleteObject(testDirFilePath)
suite.Nil(err, "no error deleting testdir/deleteme.txt using AlibabaOSS backend")

err = suite.SSEAlibabaOSSBackend.DeleteObject(testFilePath)
suite.Nil(err, "no error deleting deleteme.txt using AlibabaOSS backend")

err = suite.SSEAlibabaOSSBackend.DeleteObject(testDirFilePath)
suite.Nil(err, "no error deleting testdir/deleteme.txt using AlibabaOSS backend")
}
}

Expand All @@ -84,6 +98,19 @@ func (suite *AlibabaTestSuite) TestListObjects() {
suite.Equal(len(objs), testCount, "able to list objects")
}

func (suite *AlibabaTestSuite) TestListFolders() {
_, err := suite.BrokenAlibabaOSSBackend.ListFolders("")
suite.NotNil(err, "cannot list folders with bad bucket")

folders, err := suite.NoPrefixAlibabaOSSBackend.ListFolders("")
suite.Nil(err, "can list folders with good bucket, no prefix")
suite.Equal(len(folders), testCount, "able to list folders")

folders, err = suite.SSEAlibabaOSSBackend.ListFolders("")
suite.Nil(err, "can list objects with good bucket, SSE")
suite.Equal(len(folders), testCount, "able to list folders")
}

func (suite *AlibabaTestSuite) TestGetObject() {
_, err := suite.BrokenAlibabaOSSBackend.GetObject("this-file-cannot-possibly-exist.tgz")
suite.NotNil(err, "cannot get objects with bad bucket")
Expand Down
61 changes: 36 additions & 25 deletions amazon.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,35 +80,46 @@ func NewAmazonS3BackendWithCredentials(bucket string, prefix string, region stri

// ListObjects lists all objects in Amazon S3 bucket, at prefix
func (b AmazonS3Backend) ListObjects(prefix string) ([]Object, error) {
var objects []Object
prefix = pathutil.Join(b.Prefix, prefix)
s3Input := &s3.ListObjectsInput{
Bucket: aws.String(b.Bucket),
Prefix: aws.String(prefix),
}
for {
s3Result, err := b.Client.ListObjects(s3Input)
if err != nil {
return objects, err
return getObjects(b, prefix)
}

// ListFolders lists all folders in Amazon S3 bucket, at prefix
func (b AmazonS3Backend) ListFolders(prefix string) ([]Folder, error) {
return getFolders(b, prefix)
}

func (b AmazonS3Backend) ObjectIter(prefix string) <-chan Item {
ch := make(chan(Item))
go func() {
prefix = pathutil.Join(b.Prefix, prefix)
s3Input := &s3.ListObjectsInput{
Bucket: aws.String(b.Bucket),
Prefix: aws.String(prefix),
}
for _, obj := range s3Result.Contents {
path := removePrefixFromObjectPath(prefix, *obj.Key)
if objectPathIsInvalid(path) {
continue
for {
s3Result, err := b.Client.ListObjects(s3Input)
if err != nil {
ch <- Item{nil, err}
close(ch)
return
}
object := Object{
Path: path,
Content: []byte{},
LastModified: *obj.LastModified,
for _, obj := range s3Result.Contents {
path := removePrefixFromObjectPath(prefix, *obj.Key)
ch <- Item{
&Object{
Path: path,
Content: []byte{},
LastModified: *obj.LastModified,
}, nil }
}
objects = append(objects, object)
}
if !*s3Result.IsTruncated {
break
if !*s3Result.IsTruncated {
break
}
s3Input.Marker = s3Result.Contents[len(s3Result.Contents)-1].Key
}
s3Input.Marker = s3Result.Contents[len(s3Result.Contents)-1].Key
}
return objects, nil
close(ch)
} ()
return ch
}

// GetObject retrieves an object from Amazon S3 bucket, at prefix
Expand Down
32 changes: 30 additions & 2 deletions amazon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,19 @@ func (suite *AmazonTestSuite) SetupSuite() {

data := []byte("some object")
path := "deleteme.txt"
dirFilePath := "testdir/deleteme.txt"

err := suite.NoPrefixAmazonS3Backend.PutObject(path, data)
suite.Nil(err, "no error putting deleteme.txt using AmazonS3 backend")

err = suite.SSEAmazonS3Backend.PutObject(path, data)
suite.Nil(err, "no error putting deleteme.txt using AmazonS3 backend (SSE)")

err = suite.NoPrefixAmazonS3Backend.PutObject(dirFilePath, data)
suite.Nil(err, "no error putting testdir/deleteme.txt using AmazonS3 backend")

err = suite.SSEAmazonS3Backend.PutObject(dirFilePath, data)
suite.Nil(err, "no error putting testdir/deleteme.txt using AmazonS3 backend (SSE)")
}

func (suite *AmazonTestSuite) TearDownSuite() {
Expand All @@ -58,17 +65,38 @@ func (suite *AmazonTestSuite) TearDownSuite() {

err = suite.SSEAmazonS3Backend.DeleteObject("deleteme.txt")
suite.Nil(err, "no error deleting deleteme.txt using AmazonS3 backend")

err = suite.NoPrefixAmazonS3Backend.DeleteObject("testdir/deleteme.txt")
suite.Nil(err, "no error deleting testdir/deleteme.txt using AmazonS3 backend")

err = suite.SSEAmazonS3Backend.DeleteObject("testdir/deleteme.txt")
suite.Nil(err, "no error deleting testdir/deleteme.txt using AmazonS3 backend")
}

func (suite *AmazonTestSuite) TestListObjects() {
_, err := suite.BrokenAmazonS3Backend.ListObjects("")
suite.NotNil(err, "cannot list objects with bad bucket")

_, err = suite.NoPrefixAmazonS3Backend.ListObjects("")
objs, err := suite.NoPrefixAmazonS3Backend.ListObjects("")
suite.Nil(err, "can list objects with good bucket, no prefix")
suite.Equal(len(objs), 1, "able to list objects")

_, err = suite.SSEAmazonS3Backend.ListObjects("")
objs, err = suite.SSEAmazonS3Backend.ListObjects("")
suite.Nil(err, "can list objects with good bucket, SSE")
suite.Equal(len(objs), 1, "able to list objects")
}

func (suite *AmazonTestSuite) TestListFolders() {
_, err := suite.BrokenAmazonS3Backend.ListFolders("")
suite.NotNil(err, "cannot list folders with bad bucket")

folders, err := suite.NoPrefixAmazonS3Backend.ListFolders("")
suite.Nil(err, "can list folders with good bucket, no prefix")
suite.Equal(len(folders), 1, "able to list folders")

folders, err = suite.SSEAmazonS3Backend.ListFolders("")
suite.Nil(err, "can list folders with good bucket, SSE")
suite.Equal(len(folders), 1, "able to list folders")
}

func (suite *AmazonTestSuite) TestGetObject() {
Expand Down
85 changes: 47 additions & 38 deletions baidu.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,44 +67,53 @@ func NewBaiDuBOSBackend(bucket string, prefix string, endpoint string) *BaiduBOS

// ListObjects lists all objects in Baidu Cloud BOS bucket, at prefix
func (b BaiduBOSBackend) ListObjects(prefix string) ([]Object, error) {
var objects []Object

prefix = pathutil.Join(b.Prefix, prefix)
listObjectsArgs := &api.ListObjectsArgs{
Prefix: prefix,
Marker: "",
MaxKeys: 1000,
}
for {
lor, err := b.Client.ListObjects(b.Bucket, listObjectsArgs)
if err != nil {
return objects, err
}

for _, obj := range lor.Contents {
path := removePrefixFromObjectPath(prefix, obj.Key)
if objectPathIsInvalid(path) {
continue
}
lastModified, err := time.Parse(time.RFC3339, obj.LastModified)
if err != nil {
continue
}
object := Object{
Path: path,
Content: []byte{},
LastModified: lastModified,
}
objects = append(objects, object)
}
if !lor.IsTruncated {
break
}
listObjectsArgs.Prefix = lor.Prefix
listObjectsArgs.Marker = lor.NextMarker
}

return objects, nil
return getObjects(b, prefix)
}

// ListFolders lists all folders in Baidu Cloud BOS bucket, at prefix
func (b BaiduBOSBackend) ListFolders(prefix string) ([]Folder, error) {
return getFolders(b, prefix)
}

func (b BaiduBOSBackend) ObjectIter(prefix string) <-chan Item {
ch := make(chan(Item))
go func() {
prefix = pathutil.Join(b.Prefix, prefix)
listObjectsArgs := &api.ListObjectsArgs{
Prefix: prefix,
Marker: "",
MaxKeys: 1000,
}
for {
lor, err := b.Client.ListObjects(b.Bucket, listObjectsArgs)
if err != nil {
ch <- Item{nil, err}
close(ch)
return
}

for _, obj := range lor.Contents {
path := removePrefixFromObjectPath(prefix, obj.Key)
lastModified, err := time.Parse(time.RFC3339, obj.LastModified)
if err != nil {
continue
}
ch <- Item{
&Object{
Path: path,
Content: []byte{},
LastModified: lastModified,
}, nil }
}
if !lor.IsTruncated {
break
}
listObjectsArgs.Prefix = lor.Prefix
listObjectsArgs.Marker = lor.NextMarker
}
close(ch)
} ()
return ch
}

// GetObject retrieves an object from Baidu Cloud BOS bucket, at prefix
Expand Down
Loading