Skip to content

Commit

Permalink
v11.1.2 (#397)
Browse files Browse the repository at this point in the history
* v11.1.2

* update travis

* fix test
  • Loading branch information
jhendrixMSFT authored Apr 24, 2019
1 parent 4b7f49d commit 1ffcc88
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 39 deletions.
10 changes: 2 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@ sudo: false
language: go

go:
- master
- 1.12.x
- 1.11.x
- 1.10.x
- 1.9.x
- 1.8.x

matrix:
allow_failures:
- go: master

env:
- DEP_VERSION="0.5.0"
- DEP_VERSION="0.5.1"

before_install:
- curl -L -o $GOPATH/bin/dep https://github.com/golang/dep/releases/download/v$DEP_VERSION/dep-linux-amd64 && chmod +x $GOPATH/bin/dep
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# CHANGELOG

## v11.1.2

### Bug Fixes (back-ports)

- If zero bytes are read from a polling response body don't attempt to unmarshal them.
- For an LRO PUT operation the final GET URL was incorrectly set to the Location polling header in some cases.
- In `Future.WaitForCompletionRef()` if the provided context has a deadline don't add the default deadline.

## v11.1.1

### Bug Fixes
Expand Down
4 changes: 2 additions & 2 deletions autorest/adal/persist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ func TestSaveToken(t *testing.T) {
var actualToken Token
var expectedToken Token

json.Unmarshal([]byte(MockTokenJSON), expectedToken)
json.Unmarshal([]byte(MockTokenJSON), &expectedToken)

contents, err := ioutil.ReadFile(f.Name())
if err != nil {
t.Fatal("!!")
}
json.Unmarshal(contents, actualToken)
json.Unmarshal(contents, &actualToken)

if !reflect.DeepEqual(actualToken, expectedToken) {
t.Fatal("azure: token was not serialized correctly")
Expand Down
51 changes: 32 additions & 19 deletions autorest/azure/async.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,13 @@ func (f Future) PollingMethod() PollingMethodType {
}

// Done queries the service to see if the operation has completed.
// Deprecated: Use DoneWithContext()
func (f *Future) Done(sender autorest.Sender) (bool, error) {
return f.DoneWithContext(context.Background(), sender)
}

// DoneWithContext queries the service to see if the operation has completed.
func (f *Future) DoneWithContext(ctx context.Context, sender autorest.Sender) (done bool, err error) {
// support for legacy Future implementation
if f.req != nil {
resp, err := sender.Do(f.req)
Expand All @@ -107,7 +113,7 @@ func (f *Future) Done(sender autorest.Sender) (bool, error) {
if f.pt.hasTerminated() {
return true, f.pt.pollingError()
}
if err := f.pt.pollForStatus(sender); err != nil {
if err := f.pt.pollForStatus(ctx, sender); err != nil {
return false, err
}
if err := f.pt.checkForErrors(); err != nil {
Expand Down Expand Up @@ -164,15 +170,22 @@ func (f Future) WaitForCompletion(ctx context.Context, client autorest.Client) e
// running operation has completed, the provided context is cancelled, or the client's
// polling duration has been exceeded. It will retry failed polling attempts based on
// the retry value defined in the client up to the maximum retry attempts.
func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Client) error {
if d := client.PollingDuration; d != 0 {
// If no deadline is specified in the context then the client.PollingDuration will be
// used to determine if a default deadline should be used.
// If PollingDuration is greater than zero the value will be used as the context's timeout.
// If PollingDuration is zero then no default deadline will be used.
func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Client) (err error) {
cancelCtx := ctx
// if the provided context already has a deadline don't override it
_, hasDeadline := ctx.Deadline()
if d := client.PollingDuration; !hasDeadline && d != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, d)
cancelCtx, cancel = context.WithTimeout(ctx, d)
defer cancel()
}

done, err := f.Done(client)
for attempts := 0; !done; done, err = f.Done(client) {
done, err := f.DoneWithContext(ctx, client)
for attempts := 0; !done; done, err = f.DoneWithContext(ctx, client) {
if attempts >= client.RetryAttempts {
return autorest.NewErrorWithError(err, "Future", "WaitForCompletion", f.pt.latestResponse(), "the number of retries has been exceeded")
}
Expand All @@ -196,12 +209,12 @@ func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Clien
attempts++
}
// wait until the delay elapses or the context is cancelled
delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, ctx.Done())
delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, cancelCtx.Done())
if !delayElapsed {
return autorest.NewErrorWithError(ctx.Err(), "Future", "WaitForCompletion", f.pt.latestResponse(), "context has been cancelled")
return autorest.NewErrorWithError(cancelCtx.Err(), "Future", "WaitForCompletion", f.pt.latestResponse(), "context has been cancelled")
}
}
return err
return
}

// MarshalJSON implements the json.Marshaler interface.
Expand Down Expand Up @@ -286,7 +299,7 @@ type pollingTracker interface {
initializeState() error

// makes an HTTP request to check the status of the LRO
pollForStatus(sender autorest.Sender) error
pollForStatus(ctx context.Context, sender autorest.Sender) error

// updates internal tracker state, call this after each call to pollForStatus
updatePollingState(provStateApl bool) error
Expand Down Expand Up @@ -400,6 +413,10 @@ func (pt *pollingTrackerBase) updateRawBody() error {
if err != nil {
return autorest.NewErrorWithError(err, "pollingTrackerBase", "updateRawBody", nil, "failed to read response body")
}
// observed in 204 responses over HTTP/2.0; the content length is -1 but body is empty
if len(b) == 0 {
return nil
}
// put the body back so it's available to other callers
pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b))
if err = json.Unmarshal(b, &pt.rawBody); err != nil {
Expand All @@ -409,15 +426,13 @@ func (pt *pollingTrackerBase) updateRawBody() error {
return nil
}

func (pt *pollingTrackerBase) pollForStatus(sender autorest.Sender) error {
func (pt *pollingTrackerBase) pollForStatus(ctx context.Context, sender autorest.Sender) error {
req, err := http.NewRequest(http.MethodGet, pt.URI, nil)
if err != nil {
return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed to create HTTP request")
}
// attach the context from the original request if available (it will be absent for deserialized futures)
if pt.resp != nil {
req = req.WithContext(pt.resp.Request.Context())
}

req = req.WithContext(ctx)
pt.resp, err = sender.Do(req)
if err != nil {
return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed to send HTTP request")
Expand Down Expand Up @@ -446,7 +461,7 @@ func (pt *pollingTrackerBase) updateErrorFromResponse() {
re := respErr{}
defer pt.resp.Body.Close()
var b []byte
if b, err = ioutil.ReadAll(pt.resp.Body); err != nil {
if b, err = ioutil.ReadAll(pt.resp.Body); err != nil || len(b) == 0 {
goto Default
}
if err = json.Unmarshal(b, &re); err != nil {
Expand Down Expand Up @@ -664,7 +679,7 @@ func (pt *pollingTrackerPatch) updatePollingMethod() error {
}
}
// for 202 prefer the Azure-AsyncOperation header but fall back to Location if necessary
// note the absense of the "final GET" mechanism for PATCH
// note the absence of the "final GET" mechanism for PATCH
if pt.resp.StatusCode == http.StatusAccepted {
ao, err := getURLFromAsyncOpHeader(pt.resp)
if err != nil {
Expand Down Expand Up @@ -795,8 +810,6 @@ func (pt *pollingTrackerPut) updatePollingMethod() error {
pt.URI = lh
pt.Pm = PollingLocation
}
// when both headers are returned we use the value in the Location header for the final GET
pt.FinalGetURI = lh
}
// make sure a polling URL was found
if pt.URI == "" {
Expand Down
19 changes: 10 additions & 9 deletions autorest/azure/async_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ func TestCreatePutTracker202SuccessLocation(t *testing.T) {
if pt.pollingMethod() != PollingLocation {
t.Fatalf("wrong polling method: %s", pt.pollingMethod())
}
if pt.finalGetURL() != mocks.TestLocationURL {
if pt.finalGetURL() != resp.Request.URL.String() {
t.Fatalf("wrong final GET URL: %s", pt.finalGetURL())
}
}
Expand All @@ -450,7 +450,7 @@ func TestCreatePutTracker202SuccessBoth(t *testing.T) {
if pt.pollingMethod() != PollingAsyncOperation {
t.Fatalf("wrong polling method: %s", pt.pollingMethod())
}
if pt.finalGetURL() != mocks.TestLocationURL {
if pt.finalGetURL() != resp.Request.URL.String() {
t.Fatalf("wrong final GET URL: %s", pt.finalGetURL())
}
}
Expand Down Expand Up @@ -488,7 +488,7 @@ func TestPollPutTrackerSuccessNoHeaders(t *testing.T) {
}
sender := mocks.NewSender()
sender.AppendResponse(newProvisioningStatusResponse("InProgress"))
err = pt.pollForStatus(sender)
err = pt.pollForStatus(context.Background(), sender)
if err != nil {
t.Fatalf("failed to poll for status: %v", err)
}
Expand All @@ -506,7 +506,7 @@ func TestPollPutTrackerFailNoHeadersEmptyBody(t *testing.T) {
}
sender := mocks.NewSender()
sender.AppendResponse(mocks.NewResponseWithBodyAndStatus(&mocks.Body{}, http.StatusOK, "status ok"))
err = pt.pollForStatus(sender)
err = pt.pollForStatus(context.Background(), sender)
if err != nil {
t.Fatalf("failed to poll for status: %v", err)
}
Expand All @@ -526,7 +526,7 @@ func TestAsyncPollingReturnsWrappedError(t *testing.T) {
}
sender := mocks.NewSender()
sender.AppendResponse(newOperationResourceErrorResponse("Failed"))
err = pt.pollForStatus(sender)
err = pt.pollForStatus(context.Background(), sender)
if err == nil {
t.Fatal("unexpected nil polling error")
}
Expand All @@ -551,7 +551,7 @@ func TestLocationPollingReturnsWrappedError(t *testing.T) {
}
sender := mocks.NewSender()
sender.AppendResponse(newProvisioningStatusErrorResponse("Failed"))
err = pt.pollForStatus(sender)
err = pt.pollForStatus(context.Background(), sender)
if err == nil {
t.Fatal("unexpected nil polling error")
}
Expand All @@ -576,7 +576,7 @@ func TestLocationPollingReturnsUnwrappedError(t *testing.T) {
}
sender := mocks.NewSender()
sender.AppendResponse(newProvisioningStatusUnwrappedErrorResponse("Failed"))
err = pt.pollForStatus(sender)
err = pt.pollForStatus(context.Background(), sender)
if err == nil {
t.Fatal("unexpected nil polling error")
}
Expand Down Expand Up @@ -684,6 +684,7 @@ func TestFuture_PollsUntilProvisioningStatusSucceeds(t *testing.T) {
r3 := newOperationResourceResponse(operationSucceeded)

sender := mocks.NewSender()
ctx := context.Background()
sender.AppendAndRepeatResponse(r2, 2)
sender.AppendResponse(r3)

Expand All @@ -692,7 +693,7 @@ func TestFuture_PollsUntilProvisioningStatusSucceeds(t *testing.T) {
t.Fatalf("failed to create future: %v", err)
}

for done, err := future.Done(sender); !done; done, err = future.Done(sender) {
for done, err := future.DoneWithContext(ctx, sender); !done; done, err = future.DoneWithContext(ctx, sender) {
if future.PollingMethod() != PollingAsyncOperation {
t.Fatalf("wrong future polling method: %s", future.PollingMethod())
}
Expand Down Expand Up @@ -955,7 +956,7 @@ func TestFuture_GetResultFromNonAsyncOperation(t *testing.T) {
if pm := future.PollingMethod(); pm != PollingUnknown {
t.Fatalf("wrong polling method: %s", pm)
}
done, err := future.Done(nil)
done, err := future.DoneWithContext(context.Background(), nil)
if err != nil {
t.Fatalf("failed to check status: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
)

// Number contains the semantic version of this SDK.
const Number = "v11.1.1"
const Number = "v11.1.2"

var (
userAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s",
Expand Down

0 comments on commit 1ffcc88

Please sign in to comment.