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
Azure Blob: Unable to access Metadata when listing blobs #16679
Comments
In case this helps anybody, here's a quick-and-dirty XML parsing workaround that works and allows me to read the one metadata I'm interested in:
|
I just came here to report the same issue. For example ContentMD5 property isn't returned from the List Response. Here is a complete way to reproduce specifically for the ContentMD5 property: package main
import (
"context"
"crypto/md5"
"encoding/base64"
"fmt"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)
func main() {
cred, err := azblob.NewSharedKeyCredential(os.Getenv("AzureBlobStorageAccount"), os.Getenv("AzureBlobStorageAccessKey"))
if err != nil {
fmt.Printf("failed to create credential %v", err)
}
url := fmt.Sprintf("https://%s.blob.core.windows.net/%s", os.Getenv("AzureBlobStorageAccount"), os.Getenv("AzureBlobStorageContainer"))
container, err := azblob.NewContainerClientWithSharedKey(url, cred, nil)
if err != nil {
fmt.Printf("failed to create container client %v", err)
}
blockBlob := container.NewBlockBlobClient("randomfile.txt")
content := []byte("Hello World!")
md5hash := md5.New()
md5hash.Write(content)
b64md5hash := base64.StdEncoding.EncodeToString(md5hash.Sum(nil))
blockBlob.UploadBufferToBlockBlob(context.Background(), content, azblob.HighLevelUploadToBlockBlobOption{
HTTPHeaders: &azblob.BlobHTTPHeaders{
BlobContentMD5: []byte(b64md5hash),
},
})
props, _ := blockBlob.GetProperties(context.Background(), nil)
receivedB64md5hash := base64.StdEncoding.EncodeToString(props.ContentMD5)
if b64md5hash != receivedB64md5hash {
panic("MD5 hash mismatch")
}
fmt.Println("MD5 hash from GetProperties response verified")
pager := container.ListBlobsFlat(nil)
blobs := []*azblob.BlobItemInternal{}
for pager.NextPage(context.Background()) {
response := pager.PageResponse()
blobs = append(blobs, response.ContainerListBlobFlatSegmentResult.Segment.BlobItems...)
}
for _, blob := range blobs {
if *blob.Name == "randomfile.txt" {
receivedListb64md5Hash := base64.StdEncoding.EncodeToString(blob.Properties.ContentMD5)
// blob.Properties.ContentMD5 is nil
// this seems to be an issue marshalling the response from the server, but in the List request only
if b64md5hash != receivedListb64md5Hash {
fmt.Println("MD5 hash from ListBlobsFlat response does not match")
panic("MD5 hash mismatch")
}
break
}
}
} |
@RickWinter @jhendrixMSFT FYI I am currently rewriting the Dapr Blob Storage Output Binding component to use the Track 2 SDK and I encountered this issue in my tests. Until the List response contains all the properties I will not be able to certify this component as Stable as far as Dapr is concerned. |
Thanks for the tip @jkowalski. I am not sure why the original code doesn't Decode the XML correctly, but the following seems to work for me with regards to the ContentMD5 property The following code depends on my code snippet from above. var enumerationResults struct {
Blobs struct {
Blob []struct {
Name string `xml:"Name"`
Properties struct {
ContentMD5 []byte `xml:"Content-MD5"`
}
}
}
}
for pager.NextPage(context.Background()) {
response := pager.PageResponse()
if err := xml.NewDecoder(response.RawResponse.Body).Decode(&enumerationResults); err != nil {
panic(err)
}
for _, blob := range enumerationResults.Blobs.Blob {
if blob.Name == "randomfile.txt" {
receivedListb64md5Hash := blob.Properties.ContentMD5
if b64md5hash != string(receivedListb64md5Hash) {
fmt.Println("MD5 hash from ListBlobsFlat response does not match")
panic("MD5 hash mismatch")
}
fmt.Println("MD5 hash from ListBlobsFlat response verified")
break
}
}
} |
Hello, I have the same issue. Could you please review my fix:
and the blob properties is:
Thank you! |
And of course we can decode
|
I'm encountering this issue as well. Had to apply @deiter's fix to a fork of mine in order to get |
Workaround for Azure#16679
Fixed in |
0.3.0 doesn't seem different in this regard than 0.2.0 to me |
Are you able to reproduce this issue again @evenh ? Here's a test which I added to make sure this issue isn't happening again.
|
I see that I wasn't specific enough about mye use case. We use AzCopy to upload a bunch of files (which puts MD5 in the metadata) and we'd like to access that property via this SDK. My testing suggests that the I couldn't figure out to run the tests locally, so haven't tried them. |
This is a codegen issue, I've opened Azure/autorest.go#774 to track it. For now, @mohsha-msft can you fix this up manually? I don't know how many locations we improperly unmarshal base-64 strings. |
Thanks 👏🏻 |
Thanks Joel. I'll keep track of this. I'll fix it manually for now. Do we have any transform to fix this? |
I don't think it can be fixed via a transform. |
Hey @jkowalski , @berndverst , @evenh , and @deiter, azblob v0.4.0 is now publically available. I have fixed the issue here and here. Please reach out and reopen the issue if it still persists. Thanks a lot for your feedbacks! |
Bug Report
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
require github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.2.0
require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1 // indirect
github.com/stretchr/objx v0.2.0 // indirect
)
output of
go version
go version go1.17.2 darwin/arm64
What happened?
I'm trying to list metadata associated with blobs, but it appears to be incorrectly handled in the SDK code so it always comes back empty.
To reproduce, upload some blobs with custom metadata like so:
Now when listing the blobs there are 2 sub-issues, one blocking the other:
ContainerListBlobFlatSegmentOptions.Include
:My first attempt was to try:
but the server never returns any metadata. I read through the code and I think there's a bug generating the
include
query parameter and server silently ignores invalid value (bug in itself?), and to overcome it I have to add artificial square brackets, which makes it work partially - see below:Metadata
After applying the workaround above, I get the following response from the server (there are 4 files in the bucket that match the prefix) - the response was captured using
io.Copy(os.Stderr, resp.RawResponse.Body)
:I was looking to retrieve metadata named
Kopiamtime
which shows up in the server response, but unfortunately cannot be read in Go code, becauseit.Metadata
is always an empty map:This always prints
map[]
.I'm not an expert in Golang XML handling, but I think this mapping is to blame, probably because of extra nesting:
azure-sdk-for-go/sdk/storage/azblob/zz_generated_models.go
Line 381 in a330cae
Also notice how the server returns
OrMetadata
but the code is mappingObjectReplicationMetadata
which is also incorrect.BTW. Thanks for the library. I'm trying to use it in https://github.com/kopia/kopia - all other things are working fine, except this one issue which is currently blocking.
Is there a workaround that can be applied here? I was thinking of manually parsing the XML for the time being until this issue is resolved.
The text was updated successfully, but these errors were encountered: