diff --git a/pkg/cloudprovider/aws/object_storage_adapter.go b/pkg/cloudprovider/aws/object_storage_adapter.go index aad00cdeb..cb493daa6 100644 --- a/pkg/cloudprovider/aws/object_storage_adapter.go +++ b/pkg/cloudprovider/aws/object_storage_adapter.go @@ -109,8 +109,8 @@ func (op *objectStorageAdapter) ListCommonPrefixes(bucket string, delimiter stri } var ret []string - err := op.s3.ListObjectsV2Pages(req, func(res *s3.ListObjectsV2Output, lastPage bool) bool { - for _, prefix := range res.CommonPrefixes { + err := op.s3.ListObjectsV2Pages(req, func(page *s3.ListObjectsV2Output, lastPage bool) bool { + for _, prefix := range page.CommonPrefixes { ret = append(ret, *prefix.Prefix) } return !lastPage @@ -123,6 +123,27 @@ func (op *objectStorageAdapter) ListCommonPrefixes(bucket string, delimiter stri return ret, nil } +func (op *objectStorageAdapter) ListObjects(bucket, prefix string) ([]string, error) { + req := &s3.ListObjectsV2Input{ + Bucket: &bucket, + Prefix: &prefix, + } + + var ret []string + err := op.s3.ListObjectsV2Pages(req, func(page *s3.ListObjectsV2Output, lastPage bool) bool { + for _, obj := range page.Contents { + ret = append(ret, *obj.Key) + } + return !lastPage + }) + + if err != nil { + return nil, err + } + + return ret, nil +} + func (op *objectStorageAdapter) DeleteObject(bucket string, key string) error { req := &s3.DeleteObjectInput{ Bucket: &bucket, diff --git a/pkg/cloudprovider/azure/object_storage_adapter.go b/pkg/cloudprovider/azure/object_storage_adapter.go index baf368346..daaca2b71 100644 --- a/pkg/cloudprovider/azure/object_storage_adapter.go +++ b/pkg/cloudprovider/azure/object_storage_adapter.go @@ -121,6 +121,29 @@ func (op *objectStorageAdapter) ListCommonPrefixes(bucket string, delimiter stri return ret, nil } +func (op *objectStorageAdapter) ListObjects(bucket, prefix string) ([]string, error) { + container, err := getContainerReference(op.blobClient, bucket) + if err != nil { + return nil, err + } + + params := storage.ListBlobsParameters{ + Prefix: prefix, + } + + res, err := container.ListBlobs(params) + if err != nil { + return nil, err + } + + ret := make([]string, 0, len(res.Blobs)) + for _, blob := range res.Blobs { + ret = append(ret, blob.Name) + } + + return ret, nil +} + func (op *objectStorageAdapter) DeleteObject(bucket string, key string) error { container, err := getContainerReference(op.blobClient, bucket) if err != nil { diff --git a/pkg/cloudprovider/gcp/object_storage_adapter.go b/pkg/cloudprovider/gcp/object_storage_adapter.go index 9542180b4..85ec13978 100644 --- a/pkg/cloudprovider/gcp/object_storage_adapter.go +++ b/pkg/cloudprovider/gcp/object_storage_adapter.go @@ -92,6 +92,20 @@ func (op *objectStorageAdapter) ListCommonPrefixes(bucket string, delimiter stri return ret, nil } +func (op *objectStorageAdapter) ListObjects(bucket, prefix string) ([]string, error) { + res, err := op.gcs.Objects.List(bucket).Prefix(prefix).Do() + if err != nil { + return nil, err + } + + ret := make([]string, 0, len(res.Items)) + for _, item := range res.Items { + ret = append(ret, item.Name) + } + + return ret, nil +} + func (op *objectStorageAdapter) DeleteObject(bucket string, key string) error { return op.gcs.Objects.Delete(bucket, key).Do() } diff --git a/pkg/cloudprovider/storage_interfaces.go b/pkg/cloudprovider/storage_interfaces.go index 935f7aa13..bc439f37a 100644 --- a/pkg/cloudprovider/storage_interfaces.go +++ b/pkg/cloudprovider/storage_interfaces.go @@ -37,6 +37,9 @@ type ObjectStorageAdapter interface { // hierarchy in object storage). ListCommonPrefixes(bucket string, delimiter string) ([]string, error) + // ListObjects gets a list of all objects in bucket that have the same prefix. + ListObjects(bucket, prefix string) ([]string, error) + // DeleteObject removes object with the specified key from the given // bucket. DeleteObject(bucket string, key string) error diff --git a/pkg/util/test/object_storage_adapter.go b/pkg/util/test/object_storage_adapter.go index 70e1547b5..7d03eda04 100644 --- a/pkg/util/test/object_storage_adapter.go +++ b/pkg/util/test/object_storage_adapter.go @@ -19,12 +19,34 @@ package test import io "io" import mock "github.com/stretchr/testify/mock" +import time "time" // ObjectStorageAdapter is an autogenerated mock type for the ObjectStorageAdapter type type ObjectStorageAdapter struct { mock.Mock } +// CreateSignedURL provides a mock function with given fields: bucket, key, ttl +func (_m *ObjectStorageAdapter) CreateSignedURL(bucket string, key string, ttl time.Duration) (string, error) { + ret := _m.Called(bucket, key, ttl) + + var r0 string + if rf, ok := ret.Get(0).(func(string, string, time.Duration) string); ok { + r0 = rf(bucket, key, ttl) + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func(string, string, time.Duration) error); ok { + r1 = rf(bucket, key, ttl) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // DeleteObject provides a mock function with given fields: bucket, key func (_m *ObjectStorageAdapter) DeleteObject(bucket string, key string) error { ret := _m.Called(bucket, key) @@ -85,6 +107,29 @@ func (_m *ObjectStorageAdapter) ListCommonPrefixes(bucket string, delimiter stri return r0, r1 } +// ListObjects provides a mock function with given fields: bucket, prefix +func (_m *ObjectStorageAdapter) ListObjects(bucket string, prefix string) ([]string, error) { + ret := _m.Called(bucket, prefix) + + var r0 []string + if rf, ok := ret.Get(0).(func(string, string) []string); ok { + r0 = rf(bucket, prefix) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(bucket, prefix) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // PutObject provides a mock function with given fields: bucket, key, body func (_m *ObjectStorageAdapter) PutObject(bucket string, key string, body io.ReadSeeker) error { ret := _m.Called(bucket, key, body)