@@ -55,17 +55,19 @@ func (a *AzureReader) Close() error { return nil }
5555var _ Client = (* AzureClient )(nil )
5656
5757func newAzureClient (cfg Config ) (* AzureClient , error ) {
58+ // backwards compatible, don't know why we kept the "blob" in the code instead of letting it be input externally.
59+ ep := fmt .Sprintf ("https://%s.blob.%s" , cfg .Credential .AzureAccountName , cfg .Endpoint )
5860 switch cfg .Credential .Type {
5961 case IAM :
6062 cred , err := azidentity .NewDefaultAzureCredential (nil )
6163 if err != nil {
6264 return nil , fmt .Errorf ("storage: new azure default azure credential %w" , err )
6365 }
64- cli , err := azblob .NewClient (cfg . Endpoint , cred , nil )
66+ cli , err := azblob .NewClient (ep , cred , nil )
6567 if err != nil {
6668 return nil , fmt .Errorf ("storage: new azure client %w" , err )
6769 }
68- sasCli , err := service .NewClient (cfg . Endpoint , cred , nil )
70+ sasCli , err := service .NewClient (ep , cred , nil )
6971 if err != nil {
7072 return nil , fmt .Errorf ("storage: new azure service client %w" , err )
7173 }
@@ -76,11 +78,11 @@ func newAzureClient(cfg Config) (*AzureClient, error) {
7678 if err != nil {
7779 return nil , fmt .Errorf ("storage: new azure shared key credential %w" , err )
7880 }
79- cli , err := azblob .NewClientWithSharedKeyCredential (cfg . Endpoint , cred , nil )
81+ cli , err := azblob .NewClientWithSharedKeyCredential (ep , cred , nil )
8082 if err != nil {
8183 return nil , fmt .Errorf ("storage: new azure client %w" , err )
8284 }
83- sasCli , err := service .NewClientWithSharedKeyCredential (cfg . Endpoint , cred , nil )
85+ sasCli , err := service .NewClientWithSharedKeyCredential (ep , cred , nil )
8486 return & AzureClient {cfg : cfg , cli : cli , sasCli : sasCli }, nil
8587 default :
8688 return nil , fmt .Errorf ("storage: azure unsupported credential type: %s" , cfg .Credential .Type .String ())
@@ -219,46 +221,139 @@ func (a *AzureClient) UploadObject(ctx context.Context, i UploadObjectInput) err
219221 return nil
220222}
221223
222- type AzureObjectIterator struct {
224+ type AzureObjectFlatIterator struct {
223225 cli * AzureClient
224226
225- pager * runtime.Pager [azblob.ListBlobsFlatResponse ]
226- currPage azblob.ListBlobsFlatResponse
227- currIndex int
227+ pager * runtime.Pager [azblob.ListBlobsFlatResponse ]
228+
229+ currPage []ObjectAttr
230+ nextIdx int
231+ }
232+
233+ func (flatIter * AzureObjectFlatIterator ) HasNext () bool {
234+ // current page has more entries
235+ if flatIter .nextIdx < len (flatIter .currPage ) {
236+ return true
237+ }
238+
239+ // current page is the last page
240+ if ! flatIter .pager .More () {
241+ return false
242+ }
243+
244+ // try to get next page
245+ page , err := flatIter .pager .NextPage (context .Background ())
246+ if err != nil {
247+ log .Warn ("failed to get next page" , zap .Error (err ))
248+ return false
249+ }
250+ flatIter .currPage = flatIter .currPage [:0 ]
251+ for _ , blob := range page .Segment .BlobItems {
252+ attr := ObjectAttr {Key : * blob .Name , Length : * blob .Properties .ContentLength }
253+ flatIter .currPage = append (flatIter .currPage , attr )
254+ }
255+ flatIter .nextIdx = 0
256+ return true
257+ }
258+
259+ func (flatIter * AzureObjectFlatIterator ) Next () (ObjectAttr , error ) {
260+ attr := flatIter .currPage [flatIter .nextIdx ]
261+ flatIter .nextIdx += 1
262+
263+ return attr , nil
264+ }
265+
266+ type AzureObjectHierarchyIterator struct {
267+ cli * AzureClient
268+
269+ pager * runtime.Pager [container.ListBlobsHierarchyResponse ]
270+
271+ currPage []ObjectAttr
272+ nextIdx int
228273}
229274
230- func (a * AzureObjectIterator ) HasNext () bool {
275+ func (hierIter * AzureObjectHierarchyIterator ) HasNext () bool {
231276 // current page has more entries
232- if a . currIndex < len (a .currPage . Segment . BlobItems ) {
277+ if hierIter . nextIdx < len (hierIter .currPage ) {
233278 return true
234279 }
235280
236- // current page is the last page, try to get next page
237- if ! a .pager .More () {
281+ // no more page
282+ if ! hierIter .pager .More () {
238283 return false
239284 }
240285
241- page , err := a .pager .NextPage (context .Background ())
286+ // try to get next page
287+ page , err := hierIter .pager .NextPage (context .Background ())
242288 if err != nil {
243289 log .Warn ("failed to get next page" , zap .Error (err ))
244290 return false
245291 }
246- a .currPage = page
247- a .currIndex = 0
292+ hierIter .currPage = hierIter .currPage [:0 ]
293+ for _ , blob := range page .Segment .BlobItems {
294+ attr := ObjectAttr {Key : * blob .Name , Length : * blob .Properties .ContentLength }
295+ hierIter .currPage = append (hierIter .currPage , attr )
296+ }
297+ for _ , prefix := range page .Segment .BlobPrefixes {
298+ hierIter .currPage = append (hierIter .currPage , ObjectAttr {Key : * prefix .Name })
299+ }
300+ hierIter .nextIdx = 0
248301 return true
249302}
250303
251- func (a * AzureObjectIterator ) Next () (ObjectAttr , error ) {
252- blob := a .currPage . Segment . BlobItems [ a . currIndex ]
253- a . currIndex ++
304+ func (hierIter * AzureObjectHierarchyIterator ) Next () (ObjectAttr , error ) {
305+ attr := hierIter .currPage [ hierIter . nextIdx ]
306+ hierIter . nextIdx += 1
254307
255- return ObjectAttr { Key : * blob . Name , Length : * blob . Properties . ContentLength } , nil
308+ return attr , nil
256309}
257310
258- func (a * AzureClient ) ListPrefix (_ context.Context , prefix string , _ bool ) (ObjectIterator , error ) {
259- // currently only support list prefix recursively
311+ func (a * AzureClient ) ListPrefix (_ context.Context , prefix string , recursive bool ) (ObjectIterator , error ) {
312+ if recursive {
313+ return a .listPrefixRecursive (prefix )
314+ }
315+ return a .listPrefixNonRecursive (prefix )
316+ }
317+
318+ func (a * AzureClient ) listPrefixRecursive (prefix string ) (* AzureObjectFlatIterator , error ) {
260319 pager := a .cli .NewListBlobsFlatPager (a .cfg .Bucket , & azblob.ListBlobsFlatOptions {Prefix : to .Ptr (prefix )})
261- return & AzureObjectIterator {cli : a , pager : pager }, nil
320+ page , err := pager .NextPage (context .Background ())
321+ if err != nil {
322+ return nil , fmt .Errorf ("storage: azure list prefix %w" , err )
323+ }
324+
325+ var currPage []ObjectAttr
326+ if page .Segment != nil {
327+ for _ , blob := range page .Segment .BlobItems {
328+ attr := ObjectAttr {Key : * blob .Name , Length : * blob .Properties .ContentLength }
329+ currPage = append (currPage , attr )
330+ }
331+ }
332+
333+ return & AzureObjectFlatIterator {cli : a , pager : pager , currPage : currPage }, nil
334+ }
335+
336+ func (a * AzureClient ) listPrefixNonRecursive (prefix string ) (* AzureObjectHierarchyIterator , error ) {
337+ pager := a .cli .ServiceClient ().
338+ NewContainerClient (a .cfg .Bucket ).
339+ NewListBlobsHierarchyPager ("/" , & container.ListBlobsHierarchyOptions {Prefix : to .Ptr (prefix )})
340+ page , err := pager .NextPage (context .Background ())
341+ if err != nil {
342+ return nil , fmt .Errorf ("storage: azure list prefix %w" , err )
343+ }
344+
345+ var currPage []ObjectAttr
346+ if page .Segment != nil {
347+ for _ , blob := range page .Segment .BlobItems {
348+ attr := ObjectAttr {Key : * blob .Name , Length : * blob .Properties .ContentLength }
349+ currPage = append (currPage , attr )
350+ }
351+ for _ , pre := range page .Segment .BlobPrefixes {
352+ currPage = append (currPage , ObjectAttr {Key : * pre .Name })
353+ }
354+ }
355+
356+ return & AzureObjectHierarchyIterator {cli : a , pager : pager , currPage : currPage }, nil
262357}
263358
264359func (a * AzureClient ) DeleteObject (ctx context.Context , prefix string ) error {
0 commit comments