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

Prepare for release of azblob #16827

Merged
merged 40 commits into from
Jan 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
48c8483
Make azblob.BlobClient.downloadBlobToWriterAt public (#15899)
BenoitPerrot Oct 23, 2021
f7aa441
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-go into…
mohsha-msft Dec 3, 2021
b76e8f6
Replace the advancer (#16354)
adreed-msft Dec 3, 2021
0fc2155
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-go into…
mohsha-msft Dec 16, 2021
a0c5c62
Handle error response XML with whitespace (#16639)
johnstairs Dec 16, 2021
0a92a8d
[chunkwriting] Return original buffer to the pool (#16067)
serprex Dec 16, 2021
ece5efb
UploadStreamToBlockBlob: only require body be io.Reader (#15958)
serprex Dec 16, 2021
94e82fb
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-go into…
mohsha-msft Jan 3, 2022
f94e183
uncomment o.Progress(progress) in getDownloadBlobOptions() (#16727)
discentem Jan 3, 2022
15ba6af
Updated azblob README sample code (#16721)
kimprice Jan 3, 2022
ba0a22f
[KeyVault] updating examples to use ClientSecretCredential, fix parsi…
seankane-msft Jan 3, 2022
d25e96a
Add spell check warnings (#16656)
danieljurek Jan 3, 2022
c513fbb
Adding Smoketests to nightly runs (#16226)
seankane-msft Jan 3, 2022
575e9be
Sync eng/common directory with azure-sdk-tools for PR 2464 (#16730)
azure-sdk Jan 4, 2022
a375c84
Make EndpointToScope resilient to subdomains (#16737)
chlowell Jan 4, 2022
4c52aaf
Add user assigned managed identity example to docs (#16738)
chlowell Jan 4, 2022
ac33105
[KeyVault] fixing broken live test (#16752)
seankane-msft Jan 5, 2022
9bfda37
Sync eng/common directory with azure-sdk-tools for PR 2484 (#16753)
azure-sdk Jan 5, 2022
0b36b2e
Release v61.1.0 1641448664 (#16762)
Alancere Jan 6, 2022
d1141da
Handle skipping docker build when PushImages is set and there is no d…
azure-sdk Jan 6, 2022
6ddd572
add new config (#16774)
ArcturusZhang Jan 7, 2022
2aba54c
Add offline test for Azure Arc managed identity (#16771)
chlowell Jan 7, 2022
9944fdb
Rename armmanagedapplications ci.yml files to avoid pipeline name def…
benbp Jan 7, 2022
c285915
Refactor IMDS discovery to remove probing, stop caching failures (#16…
chlowell Jan 8, 2022
12851e6
Sync eng/common directory with azure-sdk-tools for PR 2500 (#16779)
azure-sdk Jan 8, 2022
b2d33bd
feat: add generator cmd to generate or update readme.go.md file for t…
tadelesh Jan 10, 2022
fb83622
[azservicebus] Updating to handle breaking changes in azcore (#16776)
richardpark-msft Jan 11, 2022
7be27cd
[Core] Bump version of internal (#16793)
seankane-msft Jan 11, 2022
58f04dc
[Core] Update Changelog.md (#16794)
seankane-msft Jan 11, 2022
46dd243
Update CHANGELOG.md (#16795)
seankane-msft Jan 11, 2022
6094839
Increment version for azcore releases (#16798)
azure-sdk Jan 11, 2022
def0609
[azidentity] Making ChainedTokenCredential re-use the first successfu…
sadasant Jan 11, 2022
584a7b0
Align authentication errors with azcore.ResponseError (#16777)
chlowell Jan 11, 2022
ec9c032
Increment version for azidentity releases (#16799)
azure-sdk Jan 11, 2022
8f0d095
[KeyVault] release ready for keyvault keys (#16731)
seankane-msft Jan 11, 2022
3ff5eaf
[Tables] preparing tables for release (#16733)
seankane-msft Jan 11, 2022
992b1b3
[KeyVault] prepare secrets for release (#16732)
seankane-msft Jan 11, 2022
591427e
chore: pump codegen version in scripts (#16802)
tadelesh Jan 12, 2022
5e3a9b8
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-go into…
mohsha-msft Jan 12, 2022
473c542
Update azblob with the latest azcore (#16784)
jhendrixMSFT Jan 12, 2022
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
3 changes: 2 additions & 1 deletion sdk/storage/azblob/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Release History

## 0.2.1 (Unreleased)
## 0.3.0 (Unreleased)

### Features Added

### Breaking Changes
* Updated to latest `azcore`. Public surface area is unchanged.

### Bugs Fixed

Expand Down
4 changes: 2 additions & 2 deletions sdk/storage/azblob/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ serviceClient, err := azblob.NewServiceClientWithSharedKey(fmt.Sprintf("https://
handle(err)
// Provide the convenience function with relevant info (services, resource types, permissions, and duration)
// The SAS token will be valid from this moment onwards.
accountSAS, err := serviceClient.GetAccountSASToken(AccountSASResourceTypes{Object: true, Service: true, Container: true},
accountSAS, err := serviceClient.GetSASToken(AccountSASResourceTypes{Object: true, Service: true, Container: true},
AccountSASPermissions{Read: true, List: true}, AccountSASServices{Blob: true}, time.Now(), time.Now().Add(48*time.Hour))
handle(err)
urlToSend := fmt.Sprintf("https://%s.blob.core.windows.net/?%s", accountName, accountSAS)
Expand Down Expand Up @@ -164,7 +164,7 @@ Three different clients are provided to interact with the various components of
// ===== 1. Creating a container =====

// First, branch off of the service client and create a container client.
container := service.NewContainerClient("myContainer")
container := service.NewContainerClient("mycontainer")
// Then, fire off a create operation on the container client.
// Note that, all service-side requests have an options bag attached, allowing you to specify things like metadata, public access types, etc.
// Specifying nil omits all options.
Expand Down
37 changes: 16 additions & 21 deletions sdk/storage/azblob/chunkwriting.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type blockWriter interface {
// well, 4 MiB or 8 MiB, and auto-scale to as many goroutines within the memory limit. This gives a single dial to tweak and we can
// choose a max value for the memory setting based on internal transfers within Azure (which will give us the maximum throughput model).
// We can even provide a utility to dial this number in for customer networks to optimize their copies.
func copyFromReader(ctx context.Context, from io.ReadSeekCloser, to blockWriter, o UploadStreamToBlockBlobOptions) (BlockBlobCommitBlockListResponse, error) {
func copyFromReader(ctx context.Context, from io.Reader, to blockWriter, o UploadStreamToBlockBlobOptions) (BlockBlobCommitBlockListResponse, error) {
if err := o.defaults(); err != nil {
return BlockBlobCommitBlockListResponse{}, err
}
Expand Down Expand Up @@ -112,6 +112,7 @@ type copier struct {
type copierChunk struct {
buffer []byte
id string
length int
}

// getErr returns an error by priority. First, if a function set an error, it returns that error. Next, if the Context has an error
Expand All @@ -138,37 +139,31 @@ func (c *copier) sendChunk() error {
}

n, err := io.ReadFull(c.reader, buffer)
switch {
case err == nil && n == 0:
return nil
case err == nil:
if n > 0 {
// Some data was read, schedule the write.
id := c.id.next()
c.wg.Add(1)
c.o.TransferManager.Run(
func() {
defer c.wg.Done()
c.write(copierChunk{buffer: buffer[0:n], id: id})
c.write(copierChunk{buffer: buffer, id: id, length: n})
},
)
return nil
case err != nil && (err == io.EOF || err == io.ErrUnexpectedEOF) && n == 0:
return io.EOF
} else {
// Return the unused buffer to the manager.
c.o.TransferManager.Put(buffer)
}

if err == io.EOF || err == io.ErrUnexpectedEOF {
id := c.id.next()
c.wg.Add(1)
c.o.TransferManager.Run(
func() {
defer c.wg.Done()
c.write(copierChunk{buffer: buffer[0:n], id: id})
},
)
if err == nil {
return nil
} else if err == io.EOF || err == io.ErrUnexpectedEOF {
return io.EOF
}
if err := c.getErr(); err != nil {
return err

if cerr := c.getErr(); cerr != nil {
return cerr
}

return err
}

Expand All @@ -180,7 +175,7 @@ func (c *copier) write(chunk copierChunk) {
return
}
stageBlockOptions := c.o.getStageBlockOptions()
_, err := c.to.StageBlock(c.ctx, chunk.id, internal.NopCloser(bytes.NewReader(chunk.buffer)), stageBlockOptions)
_, err := c.to.StageBlock(c.ctx, chunk.id, internal.NopCloser(bytes.NewReader(chunk.buffer[:chunk.length])), stageBlockOptions)
if err != nil {
c.errCh <- fmt.Errorf("write error: %w", err)
return
Expand Down
4 changes: 2 additions & 2 deletions sdk/storage/azblob/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
go 1.16

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.0
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dnaeon/go-vcr v1.2.0 // indirect
github.com/stretchr/testify v1.7.0
Expand Down
8 changes: 4 additions & 4 deletions sdk/storage/azblob/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0 h1:KQgdWmEOmaJKxaUUZwHAYh12t+b+ZJf8q3friycK1kA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.20.0/go.mod h1:ZPW/Z0kLCTdDZaDbYTetxc9Cxl/2lNqxYHYNOF2bti0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1 h1:BUYIbDf/mMZ8945v3QkG3OuqGVyS4Iek0AOLwdRAYoc=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.1/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.0 h1:8wVJL0HUP5yDFXvotdewORTw7Yu88JbreWN/mobSvsQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.0/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 h1:E+m3SkZCN0Bf5q7YdTs5lSm2CYY3CK4spn5OmUIiQtk=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
36 changes: 17 additions & 19 deletions sdk/storage/azblob/highlevel.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (
"context"
"encoding/base64"
"fmt"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal"
"io"
"net/http"
"sync"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal"

"bytes"
"errors"
"os"
Expand Down Expand Up @@ -230,24 +231,21 @@ func (o *HighLevelDownloadFromBlobOptions) getDownloadBlobOptions(offSet, count
}
}

// downloadBlobToWriterAt downloads an Azure blob to a buffer with parallel.
func (b BlobClient) downloadBlobToWriterAt(ctx context.Context, offset int64, count int64, writer io.WriterAt, o HighLevelDownloadFromBlobOptions, initialDownloadResponse *DownloadResponse) error {
// DownloadBlobToWriterAt downloads an Azure blob to a WriterAt with parallel.
// Offset and count are optional, pass 0 for both to download the entire blob.
func (b BlobClient) DownloadBlobToWriterAt(ctx context.Context, offset int64, count int64, writer io.WriterAt, o HighLevelDownloadFromBlobOptions) error {
if o.BlockSize == 0 {
o.BlockSize = BlobDefaultDownloadBlockSize
}

if count == CountToEnd { // If size not specified, calculate it
if initialDownloadResponse != nil {
count = *initialDownloadResponse.ContentLength - offset // if we have the length, use it
} else {
// If we don't have the length at all, get it
downloadBlobOptions := o.getDownloadBlobOptions(0, CountToEnd, nil)
dr, err := b.Download(ctx, downloadBlobOptions)
if err != nil {
return err
}
count = *dr.ContentLength - offset
// If we don't have the length at all, get it
downloadBlobOptions := o.getDownloadBlobOptions(0, CountToEnd, nil)
dr, err := b.Download(ctx, downloadBlobOptions)
if err != nil {
return err
}
count = *dr.ContentLength - offset
}

if count <= 0 {
Expand Down Expand Up @@ -281,7 +279,7 @@ func (b BlobClient) downloadBlobToWriterAt(ctx context.Context, offset int64, co
rangeProgress = bytesTransferred
progressLock.Lock()
progress += diff
//o.Progress(progress)
o.Progress(progress)
progressLock.Unlock()
})
}
Expand All @@ -302,7 +300,7 @@ func (b BlobClient) downloadBlobToWriterAt(ctx context.Context, offset int64, co
// DownloadBlobToBuffer downloads an Azure blob to a buffer with parallel.
// Offset and count are optional, pass 0 for both to download the entire blob.
func (b BlobClient) DownloadBlobToBuffer(ctx context.Context, offset int64, count int64, _bytes []byte, o HighLevelDownloadFromBlobOptions) error {
return b.downloadBlobToWriterAt(ctx, offset, count, newBytesWriter(_bytes), o, nil)
return b.DownloadBlobToWriterAt(ctx, offset, count, newBytesWriter(_bytes), o)
}

// DownloadBlobToFile downloads an Azure blob to a local file.
Expand Down Expand Up @@ -336,7 +334,7 @@ func (b BlobClient) DownloadBlobToFile(ctx context.Context, offset int64, count
}

if size > 0 {
return b.downloadBlobToWriterAt(ctx, offset, size, file, o, nil)
return b.DownloadBlobToWriterAt(ctx, offset, size, file, o)
} else { // if the blob's size is 0, there is no need in downloading it
return nil
}
Expand Down Expand Up @@ -598,7 +596,7 @@ func (u *UploadStreamToBlockBlobOptions) getCommitBlockListOptions() *CommitBloc

// UploadStreamToBlockBlob copies the file held in io.Reader to the Blob at blockBlobClient.
// A Context deadline or cancellation will cause this to error.
func (bb BlockBlobClient) UploadStreamToBlockBlob(ctx context.Context, body io.ReadSeekCloser, o UploadStreamToBlockBlobOptions) (BlockBlobCommitBlockListResponse, error) {
func (bb BlockBlobClient) UploadStreamToBlockBlob(ctx context.Context, body io.Reader, o UploadStreamToBlockBlobOptions) (BlockBlobCommitBlockListResponse, error) {
if err := o.defaults(); err != nil {
return BlockBlobCommitBlockListResponse{}, err
}
Expand Down
1 change: 1 addition & 0 deletions sdk/storage/azblob/zc_blob_lease_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package azblob
import (
"context"
"errors"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
)
Expand Down
3 changes: 2 additions & 1 deletion sdk/storage/azblob/zc_block_blob_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ package azblob

import (
"context"
"io"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"io"
)

const (
Expand Down
19 changes: 17 additions & 2 deletions sdk/storage/azblob/zc_container_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"context"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)
Expand Down Expand Up @@ -183,6 +185,13 @@ func (c ContainerClient) ListBlobsFlat(listOptions *ContainerListBlobFlatSegment
return pager
}

// override the advancer
pager.advancer = func(ctx context.Context, response ContainerListBlobFlatSegmentResponse) (*policy.Request, error) {
return c.client.listBlobFlatSegmentCreateRequest(ctx, &ContainerListBlobFlatSegmentOptions{
Marker: response.NextMarker,
})
}

// TODO: Come Here
//pager.err = func(response *azcore.Response) error {
// return handleError(c.client.listBlobFlatSegmentHandleError(response))
Expand All @@ -206,8 +215,14 @@ func (c ContainerClient) ListBlobsHierarchy(delimiter string, listOptions *Conta
return pager
}

// TODO: Come here
//p := pager.(*listBlobsHierarchySegmentResponsePager)
// override the advancer
pager.advancer = func(ctx context.Context, response ContainerListBlobHierarchySegmentResponse) (*policy.Request, error) {
return c.client.listBlobHierarchySegmentCreateRequest(ctx, delimiter, &ContainerListBlobHierarchySegmentOptions{
Marker: response.NextMarker,
})
}

// todo: come here
//p.errorer = func(response *azcore.Response) error {
// return handleError(c.client.listBlobHierarchySegmentHandleError(response))
//}
Expand Down
1 change: 1 addition & 0 deletions sdk/storage/azblob/zc_container_lease_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package azblob
import (
"context"
"errors"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
)
Expand Down
5 changes: 3 additions & 2 deletions sdk/storage/azblob/zc_page_blob_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ package azblob

import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
"io"
"net/url"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)

const (
Expand Down
47 changes: 31 additions & 16 deletions sdk/storage/azblob/zc_storage_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import (
"encoding/xml"
"errors"
"fmt"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"net/http"
"sort"
"strings"

"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)

// InternalError is an internal error type that all errors get wrapped in.
Expand Down Expand Up @@ -49,7 +52,6 @@ func (e *InternalError) As(target interface{}) bool {
// TL;DR: This implements xml.Unmarshaler, and when the original StorageError is substituted, this unmarshaler kicks in.
// This handles the description and details. defunkifyStorageError handles the response, cause, and service code.
type StorageError struct {
raw string
response *http.Response
description string

Expand All @@ -58,8 +60,9 @@ type StorageError struct {
}

func handleError(err error) error {
if err, ok := err.(ResponseError); ok {
return &InternalError{defunkifyStorageError(err)}
var respErr *azcore.ResponseError
if errors.As(err, &respErr) {
return &InternalError{responseErrorToStorageError(respErr)}
}

if err != nil {
Expand All @@ -69,23 +72,31 @@ func handleError(err error) error {
return nil
}

// defunkifyStorageError is a function that takes the "funky" ResponseError and reduces it to a storageError.
func defunkifyStorageError(responseError ResponseError) error {
if err, ok := responseError.Unwrap().(*StorageError); ok {
// errors.Unwrap(responseError.Unwrap())

err.response = responseError.RawResponse()
// converts an *azcore.ResponseError to a *StorageError, or if that fails, a *InternalError
func responseErrorToStorageError(responseError *azcore.ResponseError) error {
var storageError StorageError
body, err := runtime.Payload(responseError.RawResponse)
if err != nil {
goto Default
}
if len(body) > 0 {
if err := xml.Unmarshal(body, &storageError); err != nil {
goto Default
}
}

err.ErrorCode = StorageErrorCode(responseError.RawResponse().Header.Get("x-ms-error-code"))
storageError.response = responseError.RawResponse

if code, ok := err.details["Code"]; ok {
err.ErrorCode = StorageErrorCode(code)
delete(err.details, "Code")
}
storageError.ErrorCode = StorageErrorCode(responseError.RawResponse.Header.Get("x-ms-error-code"))

return err
if code, ok := storageError.details["Code"]; ok {
storageError.ErrorCode = StorageErrorCode(code)
delete(storageError.details, "Code")
}

return &storageError

Default:
return &InternalError{
cause: responseError,
}
Expand Down Expand Up @@ -193,8 +204,12 @@ func (e *StorageError) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err
switch tt := t.(type) {
case xml.StartElement:
tokName = tt.Name.Local
case xml.EndElement:
tokName = ""
case xml.CharData:
switch tokName {
case "":
continue
case "Message":
e.description = string(tt)
default:
Expand Down
Loading