aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Azure/go-autorest
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/Azure/go-autorest')
-rw-r--r--vendor/github.com/Azure/go-autorest/LICENSE191
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/autorest.go115
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/async.go308
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/azure.go180
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/config.go13
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/devicetoken.go193
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/environments.go167
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/persist.go59
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/azure/token.go363
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/client.go235
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/date/date.go82
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/date/time.go89
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go86
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/date/utility.go11
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/error.go80
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/preparer.go443
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/responder.go236
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/sender.go270
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/utility.go178
-rw-r--r--vendor/github.com/Azure/go-autorest/autorest/version.go23
20 files changed, 3322 insertions, 0 deletions
diff --git a/vendor/github.com/Azure/go-autorest/LICENSE b/vendor/github.com/Azure/go-autorest/LICENSE
new file mode 100644
index 000000000..b9d6a27ea
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/LICENSE
@@ -0,0 +1,191 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright 2015 Microsoft Corporation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/Azure/go-autorest/autorest/autorest.go b/vendor/github.com/Azure/go-autorest/autorest/autorest.go
new file mode 100644
index 000000000..51f1c4bbc
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/autorest.go
@@ -0,0 +1,115 @@
+/*
+Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines
+and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/)
+generated Go code.
+
+The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending,
+and Responding. A typical pattern is:
+
+ req, err := Prepare(&http.Request{},
+ token.WithAuthorization())
+
+ resp, err := Send(req,
+ WithLogging(logger),
+ DoErrorIfStatusCode(http.StatusInternalServerError),
+ DoCloseIfError(),
+ DoRetryForAttempts(5, time.Second))
+
+ err = Respond(resp,
+ ByDiscardingBody(),
+ ByClosing())
+
+Each phase relies on decorators to modify and / or manage processing. Decorators may first modify
+and then pass the data along, pass the data first and then modify the result, or wrap themselves
+around passing the data (such as a logger might do). Decorators run in the order provided. For
+example, the following:
+
+ req, err := Prepare(&http.Request{},
+ WithBaseURL("https://microsoft.com/"),
+ WithPath("a"),
+ WithPath("b"),
+ WithPath("c"))
+
+will set the URL to:
+
+ https://microsoft.com/a/b/c
+
+Preparers and Responders may be shared and re-used (assuming the underlying decorators support
+sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders
+shared among multiple go-routines, and a single Sender shared among multiple sending go-routines,
+all bound together by means of input / output channels.
+
+Decorators hold their passed state within a closure (such as the path components in the example
+above). Be careful to share Preparers and Responders only in a context where such held state
+applies. For example, it may not make sense to share a Preparer that applies a query string from a
+fixed set of values. Similarly, sharing a Responder that reads the response body into a passed
+struct (e.g., ByUnmarshallingJson) is likely incorrect.
+
+Lastly, the Swagger specification (https://swagger.io) that drives AutoRest
+(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The
+github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure
+correct parsing and formatting.
+
+Errors raised by autorest objects and methods will conform to the autorest.Error interface.
+
+See the included examples for more detail. For details on the suggested use of this package by
+generated clients, see the Client described below.
+*/
+package autorest
+
+import (
+ "net/http"
+ "time"
+)
+
+const (
+ // HeaderLocation specifies the HTTP Location header.
+ HeaderLocation = "Location"
+
+ // HeaderRetryAfter specifies the HTTP Retry-After header.
+ HeaderRetryAfter = "Retry-After"
+)
+
+// ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set
+// and false otherwise.
+func ResponseHasStatusCode(resp *http.Response, codes ...int) bool {
+ return containsInt(codes, resp.StatusCode)
+}
+
+// GetLocation retrieves the URL from the Location header of the passed response.
+func GetLocation(resp *http.Response) string {
+ return resp.Header.Get(HeaderLocation)
+}
+
+// GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If
+// the header is absent or is malformed, it will return the supplied default delay time.Duration.
+func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration {
+ retry := resp.Header.Get(HeaderRetryAfter)
+ if retry == "" {
+ return defaultDelay
+ }
+
+ d, err := time.ParseDuration(retry + "s")
+ if err != nil {
+ return defaultDelay
+ }
+
+ return d
+}
+
+// NewPollingRequest allocates and returns a new http.Request to poll for the passed response.
+func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error) {
+ location := GetLocation(resp)
+ if location == "" {
+ return nil, NewErrorWithResponse("autorest", "NewPollingRequest", resp, "Location header missing from response that requires polling")
+ }
+
+ req, err := Prepare(&http.Request{Cancel: cancel},
+ AsGet(),
+ WithBaseURL(location))
+ if err != nil {
+ return nil, NewErrorWithError(err, "autorest", "NewPollingRequest", nil, "Failure creating poll request to %s", location)
+ }
+
+ return req, nil
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go
new file mode 100644
index 000000000..6e076981f
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go
@@ -0,0 +1,308 @@
+package azure
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/Azure/go-autorest/autorest"
+ "github.com/Azure/go-autorest/autorest/date"
+)
+
+const (
+ headerAsyncOperation = "Azure-AsyncOperation"
+)
+
+const (
+ methodDelete = "DELETE"
+ methodPatch = "PATCH"
+ methodPost = "POST"
+ methodPut = "PUT"
+ methodGet = "GET"
+
+ operationInProgress string = "InProgress"
+ operationCanceled string = "Canceled"
+ operationFailed string = "Failed"
+ operationSucceeded string = "Succeeded"
+)
+
+// DoPollForAsynchronous returns a SendDecorator that polls if the http.Response is for an Azure
+// long-running operation. It will delay between requests for the duration specified in the
+// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
+// closing the optional channel on the http.Request.
+func DoPollForAsynchronous(delay time.Duration) autorest.SendDecorator {
+ return func(s autorest.Sender) autorest.Sender {
+ return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
+ resp, err = s.Do(r)
+ if err != nil {
+ return resp, err
+ }
+ pollingCodes := []int{http.StatusAccepted, http.StatusCreated, http.StatusOK}
+ if !autorest.ResponseHasStatusCode(resp, pollingCodes...) {
+ return resp, nil
+ }
+
+ ps := pollingState{}
+ for err == nil {
+ err = updatePollingState(resp, &ps)
+ if err != nil {
+ break
+ }
+ if ps.hasTerminated() {
+ if !ps.hasSucceeded() {
+ err = ps
+ }
+ break
+ }
+
+ r, err = newPollingRequest(resp, ps)
+ if err != nil {
+ return resp, err
+ }
+
+ delay = autorest.GetRetryAfter(resp, delay)
+ resp, err = autorest.SendWithSender(s, r,
+ autorest.AfterDelay(delay))
+ }
+
+ return resp, err
+ })
+ }
+}
+
+func getAsyncOperation(resp *http.Response) string {
+ return resp.Header.Get(http.CanonicalHeaderKey(headerAsyncOperation))
+}
+
+func hasSucceeded(state string) bool {
+ return state == operationSucceeded
+}
+
+func hasTerminated(state string) bool {
+ switch state {
+ case operationCanceled, operationFailed, operationSucceeded:
+ return true
+ default:
+ return false
+ }
+}
+
+func hasFailed(state string) bool {
+ return state == operationFailed
+}
+
+type provisioningTracker interface {
+ state() string
+ hasSucceeded() bool
+ hasTerminated() bool
+}
+
+type operationResource struct {
+ // Note:
+ // The specification states services should return the "id" field. However some return it as
+ // "operationId".
+ ID string `json:"id"`
+ OperationID string `json:"operationId"`
+ Name string `json:"name"`
+ Status string `json:"status"`
+ Properties map[string]interface{} `json:"properties"`
+ OperationError ServiceError `json:"error"`
+ StartTime date.Time `json:"startTime"`
+ EndTime date.Time `json:"endTime"`
+ PercentComplete float64 `json:"percentComplete"`
+}
+
+func (or operationResource) state() string {
+ return or.Status
+}
+
+func (or operationResource) hasSucceeded() bool {
+ return hasSucceeded(or.state())
+}
+
+func (or operationResource) hasTerminated() bool {
+ return hasTerminated(or.state())
+}
+
+type provisioningProperties struct {
+ ProvisioningState string `json:"provisioningState"`
+}
+
+type provisioningStatus struct {
+ Properties provisioningProperties `json:"properties,omitempty"`
+ ProvisioningError ServiceError `json:"error,omitempty"`
+}
+
+func (ps provisioningStatus) state() string {
+ return ps.Properties.ProvisioningState
+}
+
+func (ps provisioningStatus) hasSucceeded() bool {
+ return hasSucceeded(ps.state())
+}
+
+func (ps provisioningStatus) hasTerminated() bool {
+ return hasTerminated(ps.state())
+}
+
+func (ps provisioningStatus) hasProvisioningError() bool {
+ return ps.ProvisioningError != ServiceError{}
+}
+
+type pollingResponseFormat string
+
+const (
+ usesOperationResponse pollingResponseFormat = "OperationResponse"
+ usesProvisioningStatus pollingResponseFormat = "ProvisioningStatus"
+ formatIsUnknown pollingResponseFormat = ""
+)
+
+type pollingState struct {
+ responseFormat pollingResponseFormat
+ uri string
+ state string
+ code string
+ message string
+}
+
+func (ps pollingState) hasSucceeded() bool {
+ return hasSucceeded(ps.state)
+}
+
+func (ps pollingState) hasTerminated() bool {
+ return hasTerminated(ps.state)
+}
+
+func (ps pollingState) hasFailed() bool {
+ return hasFailed(ps.state)
+}
+
+func (ps pollingState) Error() string {
+ return fmt.Sprintf("Long running operation terminated with status '%s': Code=%q Message=%q", ps.state, ps.code, ps.message)
+}
+
+// updatePollingState maps the operation status -- retrieved from either a provisioningState
+// field, the status field of an OperationResource, or inferred from the HTTP status code --
+// into a well-known states. Since the process begins from the initial request, the state
+// always comes from either a the provisioningState returned or is inferred from the HTTP
+// status code. Subsequent requests will read an Azure OperationResource object if the
+// service initially returned the Azure-AsyncOperation header. The responseFormat field notes
+// the expected response format.
+func updatePollingState(resp *http.Response, ps *pollingState) error {
+ // Determine the response shape
+ // -- The first response will always be a provisioningStatus response; only the polling requests,
+ // depending on the header returned, may be something otherwise.
+ var pt provisioningTracker
+ if ps.responseFormat == usesOperationResponse {
+ pt = &operationResource{}
+ } else {
+ pt = &provisioningStatus{}
+ }
+
+ // If this is the first request (that is, the polling response shape is unknown), determine how
+ // to poll and what to expect
+ if ps.responseFormat == formatIsUnknown {
+ req := resp.Request
+ if req == nil {
+ return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Original HTTP request is missing")
+ }
+
+ // Prefer the Azure-AsyncOperation header
+ ps.uri = getAsyncOperation(resp)
+ if ps.uri != "" {
+ ps.responseFormat = usesOperationResponse
+ } else {
+ ps.responseFormat = usesProvisioningStatus
+ }
+
+ // Else, use the Location header
+ if ps.uri == "" {
+ ps.uri = autorest.GetLocation(resp)
+ }
+
+ // Lastly, requests against an existing resource, use the last request URI
+ if ps.uri == "" {
+ m := strings.ToUpper(req.Method)
+ if m == methodPatch || m == methodPut || m == methodGet {
+ ps.uri = req.URL.String()
+ }
+ }
+ }
+
+ // Read and interpret the response (saving the Body in case no polling is necessary)
+ b := &bytes.Buffer{}
+ err := autorest.Respond(resp,
+ autorest.ByCopying(b),
+ autorest.ByUnmarshallingJSON(pt),
+ autorest.ByClosing())
+ resp.Body = ioutil.NopCloser(b)
+ if err != nil {
+ return err
+ }
+
+ // Interpret the results
+ // -- Terminal states apply regardless
+ // -- Unknown states are per-service inprogress states
+ // -- Otherwise, infer state from HTTP status code
+ if pt.hasTerminated() {
+ ps.state = pt.state()
+ } else if pt.state() != "" {
+ ps.state = operationInProgress
+ } else {
+ switch resp.StatusCode {
+ case http.StatusAccepted:
+ ps.state = operationInProgress
+
+ case http.StatusNoContent, http.StatusCreated, http.StatusOK:
+ ps.state = operationSucceeded
+
+ default:
+ ps.state = operationFailed
+ }
+ }
+
+ if ps.state == operationInProgress && ps.uri == "" {
+ return autorest.NewError("azure", "updatePollingState", "Azure Polling Error - Unable to obtain polling URI for %s %s", resp.Request.Method, resp.Request.URL)
+ }
+
+ // For failed operation, check for error code and message in
+ // -- Operation resource
+ // -- Response
+ // -- Otherwise, Unknown
+ if ps.hasFailed() {
+ if ps.responseFormat == usesOperationResponse {
+ or := pt.(*operationResource)
+ ps.code = or.OperationError.Code
+ ps.message = or.OperationError.Message
+ } else {
+ p := pt.(*provisioningStatus)
+ if p.hasProvisioningError() {
+ ps.code = p.ProvisioningError.Code
+ ps.message = p.ProvisioningError.Message
+ } else {
+ ps.code = "Unknown"
+ ps.message = "None"
+ }
+ }
+ }
+ return nil
+}
+
+func newPollingRequest(resp *http.Response, ps pollingState) (*http.Request, error) {
+ req := resp.Request
+ if req == nil {
+ return nil, autorest.NewError("azure", "newPollingRequest", "Azure Polling Error - Original HTTP request is missing")
+ }
+
+ reqPoll, err := autorest.Prepare(&http.Request{Cancel: req.Cancel},
+ autorest.AsGet(),
+ autorest.WithBaseURL(ps.uri))
+ if err != nil {
+ return nil, autorest.NewErrorWithError(err, "azure", "newPollingRequest", nil, "Failure creating poll request to %s", ps.uri)
+ }
+
+ return reqPoll, nil
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go b/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
new file mode 100644
index 000000000..3f4d13421
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
@@ -0,0 +1,180 @@
+/*
+Package azure provides Azure-specific implementations used with AutoRest.
+
+See the included examples for more detail.
+*/
+package azure
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+
+ "github.com/Azure/go-autorest/autorest"
+)
+
+const (
+ // HeaderClientID is the Azure extension header to set a user-specified request ID.
+ HeaderClientID = "x-ms-client-request-id"
+
+ // HeaderReturnClientID is the Azure extension header to set if the user-specified request ID
+ // should be included in the response.
+ HeaderReturnClientID = "x-ms-return-client-request-id"
+
+ // HeaderRequestID is the Azure extension header of the service generated request ID returned
+ // in the response.
+ HeaderRequestID = "x-ms-request-id"
+)
+
+// ServiceError encapsulates the error response from an Azure service.
+type ServiceError struct {
+ Code string `json:"code"`
+ Message string `json:"message"`
+ Details *[]interface{} `json:"details"`
+}
+
+func (se ServiceError) Error() string {
+ if se.Details != nil {
+ d, err := json.Marshal(*(se.Details))
+ if err != nil {
+ return fmt.Sprintf("Code=%q Message=%q Details=%v", se.Code, se.Message, *se.Details)
+ }
+ return fmt.Sprintf("Code=%q Message=%q Details=%v", se.Code, se.Message, string(d))
+ }
+ return fmt.Sprintf("Code=%q Message=%q", se.Code, se.Message)
+}
+
+// RequestError describes an error response returned by Azure service.
+type RequestError struct {
+ autorest.DetailedError
+
+ // The error returned by the Azure service.
+ ServiceError *ServiceError `json:"error"`
+
+ // The request id (from the x-ms-request-id-header) of the request.
+ RequestID string
+}
+
+// Error returns a human-friendly error message from service error.
+func (e RequestError) Error() string {
+ return fmt.Sprintf("autorest/azure: Service returned an error. Status=%v %v",
+ e.StatusCode, e.ServiceError)
+}
+
+// IsAzureError returns true if the passed error is an Azure Service error; false otherwise.
+func IsAzureError(e error) bool {
+ _, ok := e.(*RequestError)
+ return ok
+}
+
+// NewErrorWithError creates a new Error conforming object from the
+// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
+// if resp is nil), message, and original error. message is treated as a format
+// string to which the optional args apply.
+func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) RequestError {
+ if v, ok := original.(*RequestError); ok {
+ return *v
+ }
+
+ statusCode := autorest.UndefinedStatusCode
+ if resp != nil {
+ statusCode = resp.StatusCode
+ }
+ return RequestError{
+ DetailedError: autorest.DetailedError{
+ Original: original,
+ PackageType: packageType,
+ Method: method,
+ StatusCode: statusCode,
+ Message: fmt.Sprintf(message, args...),
+ },
+ }
+}
+
+// WithReturningClientID returns a PrepareDecorator that adds an HTTP extension header of
+// x-ms-client-request-id whose value is the passed, undecorated UUID (e.g.,
+// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). It also sets the x-ms-return-client-request-id
+// header to true such that UUID accompanies the http.Response.
+func WithReturningClientID(uuid string) autorest.PrepareDecorator {
+ preparer := autorest.CreatePreparer(
+ WithClientID(uuid),
+ WithReturnClientID(true))
+
+ return func(p autorest.Preparer) autorest.Preparer {
+ return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err != nil {
+ return r, err
+ }
+ return preparer.Prepare(r)
+ })
+ }
+}
+
+// WithClientID returns a PrepareDecorator that adds an HTTP extension header of
+// x-ms-client-request-id whose value is passed, undecorated UUID (e.g.,
+// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA").
+func WithClientID(uuid string) autorest.PrepareDecorator {
+ return autorest.WithHeader(HeaderClientID, uuid)
+}
+
+// WithReturnClientID returns a PrepareDecorator that adds an HTTP extension header of
+// x-ms-return-client-request-id whose boolean value indicates if the value of the
+// x-ms-client-request-id header should be included in the http.Response.
+func WithReturnClientID(b bool) autorest.PrepareDecorator {
+ return autorest.WithHeader(HeaderReturnClientID, strconv.FormatBool(b))
+}
+
+// ExtractClientID extracts the client identifier from the x-ms-client-request-id header set on the
+// http.Request sent to the service (and returned in the http.Response)
+func ExtractClientID(resp *http.Response) string {
+ return autorest.ExtractHeaderValue(HeaderClientID, resp)
+}
+
+// ExtractRequestID extracts the Azure server generated request identifier from the
+// x-ms-request-id header.
+func ExtractRequestID(resp *http.Response) string {
+ return autorest.ExtractHeaderValue(HeaderRequestID, resp)
+}
+
+// WithErrorUnlessStatusCode returns a RespondDecorator that emits an
+// azure.RequestError by reading the response body unless the response HTTP status code
+// is among the set passed.
+//
+// If there is a chance service may return responses other than the Azure error
+// format and the response cannot be parsed into an error, a decoding error will
+// be returned containing the response body. In any case, the Responder will
+// return an error if the status code is not satisfied.
+//
+// If this Responder returns an error, the response body will be replaced with
+// an in-memory reader, which needs no further closing.
+func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator {
+ return func(r autorest.Responder) autorest.Responder {
+ return autorest.ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) {
+ var e RequestError
+ defer resp.Body.Close()
+
+ // Copy and replace the Body in case it does not contain an error object.
+ // This will leave the Body available to the caller.
+ b, decodeErr := autorest.CopyAndDecode(autorest.EncodedAsJSON, resp.Body, &e)
+ resp.Body = ioutil.NopCloser(&b)
+ if decodeErr != nil {
+ return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b.String(), decodeErr)
+ } else if e.ServiceError == nil {
+ e.ServiceError = &ServiceError{Code: "Unknown", Message: "Unknown service error"}
+ }
+
+ e.RequestID = ExtractRequestID(resp)
+ if e.StatusCode == nil {
+ e.StatusCode = resp.StatusCode
+ }
+ err = &e
+ }
+ return err
+ })
+ }
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/config.go b/vendor/github.com/Azure/go-autorest/autorest/azure/config.go
new file mode 100644
index 000000000..bea30b0d6
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/config.go
@@ -0,0 +1,13 @@
+package azure
+
+import (
+ "net/url"
+)
+
+// OAuthConfig represents the endpoints needed
+// in OAuth operations
+type OAuthConfig struct {
+ AuthorizeEndpoint url.URL
+ TokenEndpoint url.URL
+ DeviceCodeEndpoint url.URL
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/devicetoken.go b/vendor/github.com/Azure/go-autorest/autorest/azure/devicetoken.go
new file mode 100644
index 000000000..e1d5498a8
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/devicetoken.go
@@ -0,0 +1,193 @@
+package azure
+
+/*
+ This file is largely based on rjw57/oauth2device's code, with the follow differences:
+ * scope -> resource, and only allow a single one
+ * receive "Message" in the DeviceCode struct and show it to users as the prompt
+ * azure-xplat-cli has the following behavior that this emulates:
+ - does not send client_secret during the token exchange
+ - sends resource again in the token exchange request
+*/
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/Azure/go-autorest/autorest"
+)
+
+const (
+ logPrefix = "autorest/azure/devicetoken:"
+)
+
+var (
+ // ErrDeviceGeneric represents an unknown error from the token endpoint when using device flow
+ ErrDeviceGeneric = fmt.Errorf("%s Error while retrieving OAuth token: Unknown Error", logPrefix)
+
+ // ErrDeviceAccessDenied represents an access denied error from the token endpoint when using device flow
+ ErrDeviceAccessDenied = fmt.Errorf("%s Error while retrieving OAuth token: Access Denied", logPrefix)
+
+ // ErrDeviceAuthorizationPending represents the server waiting on the user to complete the device flow
+ ErrDeviceAuthorizationPending = fmt.Errorf("%s Error while retrieving OAuth token: Authorization Pending", logPrefix)
+
+ // ErrDeviceCodeExpired represents the server timing out and expiring the code during device flow
+ ErrDeviceCodeExpired = fmt.Errorf("%s Error while retrieving OAuth token: Code Expired", logPrefix)
+
+ // ErrDeviceSlowDown represents the service telling us we're polling too often during device flow
+ ErrDeviceSlowDown = fmt.Errorf("%s Error while retrieving OAuth token: Slow Down", logPrefix)
+
+ errCodeSendingFails = "Error occurred while sending request for Device Authorization Code"
+ errCodeHandlingFails = "Error occurred while handling response from the Device Endpoint"
+ errTokenSendingFails = "Error occurred while sending request with device code for a token"
+ errTokenHandlingFails = "Error occurred while handling response from the Token Endpoint (during device flow)"
+)
+
+// DeviceCode is the object returned by the device auth endpoint
+// It contains information to instruct the user to complete the auth flow
+type DeviceCode struct {
+ DeviceCode *string `json:"device_code,omitempty"`
+ UserCode *string `json:"user_code,omitempty"`
+ VerificationURL *string `json:"verification_url,omitempty"`
+ ExpiresIn *int64 `json:"expires_in,string,omitempty"`
+ Interval *int64 `json:"interval,string,omitempty"`
+
+ Message *string `json:"message"` // Azure specific
+ Resource string // store the following, stored when initiating, used when exchanging
+ OAuthConfig OAuthConfig
+ ClientID string
+}
+
+// TokenError is the object returned by the token exchange endpoint
+// when something is amiss
+type TokenError struct {
+ Error *string `json:"error,omitempty"`
+ ErrorCodes []int `json:"error_codes,omitempty"`
+ ErrorDescription *string `json:"error_description,omitempty"`
+ Timestamp *string `json:"timestamp,omitempty"`
+ TraceID *string `json:"trace_id,omitempty"`
+}
+
+// DeviceToken is the object return by the token exchange endpoint
+// It can either look like a Token or an ErrorToken, so put both here
+// and check for presence of "Error" to know if we are in error state
+type deviceToken struct {
+ Token
+ TokenError
+}
+
+// InitiateDeviceAuth initiates a device auth flow. It returns a DeviceCode
+// that can be used with CheckForUserCompletion or WaitForUserCompletion.
+func InitiateDeviceAuth(client *autorest.Client, oauthConfig OAuthConfig, clientID, resource string) (*DeviceCode, error) {
+ req, _ := autorest.Prepare(
+ &http.Request{},
+ autorest.AsPost(),
+ autorest.AsFormURLEncoded(),
+ autorest.WithBaseURL(oauthConfig.DeviceCodeEndpoint.String()),
+ autorest.WithFormData(url.Values{
+ "client_id": []string{clientID},
+ "resource": []string{resource},
+ }),
+ )
+
+ resp, err := autorest.SendWithSender(client, req)
+ if err != nil {
+ return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err)
+ }
+
+ var code DeviceCode
+ err = autorest.Respond(
+ resp,
+ autorest.WithErrorUnlessStatusCode(http.StatusOK),
+ autorest.ByUnmarshallingJSON(&code),
+ autorest.ByClosing())
+ if err != nil {
+ return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err)
+ }
+
+ code.ClientID = clientID
+ code.Resource = resource
+ code.OAuthConfig = oauthConfig
+
+ return &code, nil
+}
+
+// CheckForUserCompletion takes a DeviceCode and checks with the Azure AD OAuth endpoint
+// to see if the device flow has: been completed, timed out, or otherwise failed
+func CheckForUserCompletion(client *autorest.Client, code *DeviceCode) (*Token, error) {
+ req, _ := autorest.Prepare(
+ &http.Request{},
+ autorest.AsPost(),
+ autorest.AsFormURLEncoded(),
+ autorest.WithBaseURL(code.OAuthConfig.TokenEndpoint.String()),
+ autorest.WithFormData(url.Values{
+ "client_id": []string{code.ClientID},
+ "code": []string{*code.DeviceCode},
+ "grant_type": []string{OAuthGrantTypeDeviceCode},
+ "resource": []string{code.Resource},
+ }),
+ )
+
+ resp, err := autorest.SendWithSender(client, req)
+ if err != nil {
+ return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err)
+ }
+
+ var token deviceToken
+ err = autorest.Respond(
+ resp,
+ autorest.WithErrorUnlessStatusCode(http.StatusOK, http.StatusBadRequest),
+ autorest.ByUnmarshallingJSON(&token),
+ autorest.ByClosing())
+ if err != nil {
+ return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err)
+ }
+
+ if token.Error == nil {
+ return &token.Token, nil
+ }
+
+ switch *token.Error {
+ case "authorization_pending":
+ return nil, ErrDeviceAuthorizationPending
+ case "slow_down":
+ return nil, ErrDeviceSlowDown
+ case "access_denied":
+ return nil, ErrDeviceAccessDenied
+ case "code_expired":
+ return nil, ErrDeviceCodeExpired
+ default:
+ return nil, ErrDeviceGeneric
+ }
+}
+
+// WaitForUserCompletion calls CheckForUserCompletion repeatedly until a token is granted or an error state occurs.
+// This prevents the user from looping and checking against 'ErrDeviceAuthorizationPending'.
+func WaitForUserCompletion(client *autorest.Client, code *DeviceCode) (*Token, error) {
+ intervalDuration := time.Duration(*code.Interval) * time.Second
+ waitDuration := intervalDuration
+
+ for {
+ token, err := CheckForUserCompletion(client, code)
+
+ if err == nil {
+ return token, nil
+ }
+
+ switch err {
+ case ErrDeviceSlowDown:
+ waitDuration += waitDuration
+ case ErrDeviceAuthorizationPending:
+ // noop
+ default: // everything else is "fatal" to us
+ return nil, err
+ }
+
+ if waitDuration > (intervalDuration * 3) {
+ return nil, fmt.Errorf("%s Error waiting for user to complete device flow. Server told us to slow_down too much", logPrefix)
+ }
+
+ time.Sleep(waitDuration)
+ }
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
new file mode 100644
index 000000000..4701b4376
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go
@@ -0,0 +1,167 @@
+package azure
+
+import (
+ "fmt"
+ "net/url"
+ "strings"
+)
+
+const (
+ activeDirectoryAPIVersion = "1.0"
+)
+
+var environments = map[string]Environment{
+ "AZURECHINACLOUD": ChinaCloud,
+ "AZUREGERMANCLOUD": GermanCloud,
+ "AZUREPUBLICCLOUD": PublicCloud,
+ "AZUREUSGOVERNMENTCLOUD": USGovernmentCloud,
+}
+
+// Environment represents a set of endpoints for each of Azure's Clouds.
+type Environment struct {
+ Name string `json:"name"`
+ ManagementPortalURL string `json:"managementPortalURL"`
+ PublishSettingsURL string `json:"publishSettingsURL"`
+ ServiceManagementEndpoint string `json:"serviceManagementEndpoint"`
+ ResourceManagerEndpoint string `json:"resourceManagerEndpoint"`
+ ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"`
+ GalleryEndpoint string `json:"galleryEndpoint"`
+ KeyVaultEndpoint string `json:"keyVaultEndpoint"`
+ GraphEndpoint string `json:"graphEndpoint"`
+ StorageEndpointSuffix string `json:"storageEndpointSuffix"`
+ SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"`
+ TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"`
+ KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"`
+ ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"`
+ ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"`
+ ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"`
+ ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"`
+}
+
+var (
+ // PublicCloud is the default public Azure cloud environment
+ PublicCloud = Environment{
+ Name: "AzurePublicCloud",
+ ManagementPortalURL: "https://manage.windowsazure.com/",
+ PublishSettingsURL: "https://manage.windowsazure.com/publishsettings/index",
+ ServiceManagementEndpoint: "https://management.core.windows.net/",
+ ResourceManagerEndpoint: "https://management.azure.com/",
+ ActiveDirectoryEndpoint: "https://login.microsoftonline.com/",
+ GalleryEndpoint: "https://gallery.azure.com/",
+ KeyVaultEndpoint: "https://vault.azure.net/",
+ GraphEndpoint: "https://graph.windows.net/",
+ StorageEndpointSuffix: "core.windows.net",
+ SQLDatabaseDNSSuffix: "database.windows.net",
+ TrafficManagerDNSSuffix: "trafficmanager.net",
+ KeyVaultDNSSuffix: "vault.azure.net",
+ ServiceBusEndpointSuffix: "servicebus.azure.com",
+ ServiceManagementVMDNSSuffix: "cloudapp.net",
+ ResourceManagerVMDNSSuffix: "cloudapp.azure.com",
+ ContainerRegistryDNSSuffix: "azurecr.io",
+ }
+
+ // USGovernmentCloud is the cloud environment for the US Government
+ USGovernmentCloud = Environment{
+ Name: "AzureUSGovernmentCloud",
+ ManagementPortalURL: "https://manage.windowsazure.us/",
+ PublishSettingsURL: "https://manage.windowsazure.us/publishsettings/index",
+ ServiceManagementEndpoint: "https://management.core.usgovcloudapi.net/",
+ ResourceManagerEndpoint: "https://management.usgovcloudapi.net/",
+ ActiveDirectoryEndpoint: "https://login.microsoftonline.com/",
+ GalleryEndpoint: "https://gallery.usgovcloudapi.net/",
+ KeyVaultEndpoint: "https://vault.usgovcloudapi.net/",
+ GraphEndpoint: "https://graph.usgovcloudapi.net/",
+ StorageEndpointSuffix: "core.usgovcloudapi.net",
+ SQLDatabaseDNSSuffix: "database.usgovcloudapi.net",
+ TrafficManagerDNSSuffix: "usgovtrafficmanager.net",
+ KeyVaultDNSSuffix: "vault.usgovcloudapi.net",
+ ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net",
+ ServiceManagementVMDNSSuffix: "usgovcloudapp.net",
+ ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us",
+ ContainerRegistryDNSSuffix: "azurecr.io",
+ }
+
+ // ChinaCloud is the cloud environment operated in China
+ ChinaCloud = Environment{
+ Name: "AzureChinaCloud",
+ ManagementPortalURL: "https://manage.chinacloudapi.com/",
+ PublishSettingsURL: "https://manage.chinacloudapi.com/publishsettings/index",
+ ServiceManagementEndpoint: "https://management.core.chinacloudapi.cn/",
+ ResourceManagerEndpoint: "https://management.chinacloudapi.cn/",
+ ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/",
+ GalleryEndpoint: "https://gallery.chinacloudapi.cn/",
+ KeyVaultEndpoint: "https://vault.azure.cn/",
+ GraphEndpoint: "https://graph.chinacloudapi.cn/",
+ StorageEndpointSuffix: "core.chinacloudapi.cn",
+ SQLDatabaseDNSSuffix: "database.chinacloudapi.cn",
+ TrafficManagerDNSSuffix: "trafficmanager.cn",
+ KeyVaultDNSSuffix: "vault.azure.cn",
+ ServiceBusEndpointSuffix: "servicebus.chinacloudapi.net",
+ ServiceManagementVMDNSSuffix: "chinacloudapp.cn",
+ ResourceManagerVMDNSSuffix: "cloudapp.azure.cn",
+ ContainerRegistryDNSSuffix: "azurecr.io",
+ }
+
+ // GermanCloud is the cloud environment operated in Germany
+ GermanCloud = Environment{
+ Name: "AzureGermanCloud",
+ ManagementPortalURL: "http://portal.microsoftazure.de/",
+ PublishSettingsURL: "https://manage.microsoftazure.de/publishsettings/index",
+ ServiceManagementEndpoint: "https://management.core.cloudapi.de/",
+ ResourceManagerEndpoint: "https://management.microsoftazure.de/",
+ ActiveDirectoryEndpoint: "https://login.microsoftonline.de/",
+ GalleryEndpoint: "https://gallery.cloudapi.de/",
+ KeyVaultEndpoint: "https://vault.microsoftazure.de/",
+ GraphEndpoint: "https://graph.cloudapi.de/",
+ StorageEndpointSuffix: "core.cloudapi.de",
+ SQLDatabaseDNSSuffix: "database.cloudapi.de",
+ TrafficManagerDNSSuffix: "azuretrafficmanager.de",
+ KeyVaultDNSSuffix: "vault.microsoftazure.de",
+ ServiceBusEndpointSuffix: "servicebus.cloudapi.de",
+ ServiceManagementVMDNSSuffix: "azurecloudapp.de",
+ ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de",
+ ContainerRegistryDNSSuffix: "azurecr.io",
+ }
+)
+
+// EnvironmentFromName returns an Environment based on the common name specified
+func EnvironmentFromName(name string) (Environment, error) {
+ name = strings.ToUpper(name)
+ env, ok := environments[name]
+ if !ok {
+ return env, fmt.Errorf("autorest/azure: There is no cloud environment matching the name %q", name)
+ }
+ return env, nil
+}
+
+// OAuthConfigForTenant returns an OAuthConfig with tenant specific urls
+func (env Environment) OAuthConfigForTenant(tenantID string) (*OAuthConfig, error) {
+ return OAuthConfigForTenant(env.ActiveDirectoryEndpoint, tenantID)
+}
+
+// OAuthConfigForTenant returns an OAuthConfig with tenant specific urls for target cloud auth endpoint
+func OAuthConfigForTenant(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, error) {
+ template := "%s/oauth2/%s?api-version=%s"
+ u, err := url.Parse(activeDirectoryEndpoint)
+ if err != nil {
+ return nil, err
+ }
+ authorizeURL, err := u.Parse(fmt.Sprintf(template, tenantID, "authorize", activeDirectoryAPIVersion))
+ if err != nil {
+ return nil, err
+ }
+ tokenURL, err := u.Parse(fmt.Sprintf(template, tenantID, "token", activeDirectoryAPIVersion))
+ if err != nil {
+ return nil, err
+ }
+ deviceCodeURL, err := u.Parse(fmt.Sprintf(template, tenantID, "devicecode", activeDirectoryAPIVersion))
+ if err != nil {
+ return nil, err
+ }
+
+ return &OAuthConfig{
+ AuthorizeEndpoint: *authorizeURL,
+ TokenEndpoint: *tokenURL,
+ DeviceCodeEndpoint: *deviceCodeURL,
+ }, nil
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/persist.go b/vendor/github.com/Azure/go-autorest/autorest/azure/persist.go
new file mode 100644
index 000000000..d5cf62ddc
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/persist.go
@@ -0,0 +1,59 @@
+package azure
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+// LoadToken restores a Token object from a file located at 'path'.
+func LoadToken(path string) (*Token, error) {
+ file, err := os.Open(path)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open file (%s) while loading token: %v", path, err)
+ }
+ defer file.Close()
+
+ var token Token
+
+ dec := json.NewDecoder(file)
+ if err = dec.Decode(&token); err != nil {
+ return nil, fmt.Errorf("failed to decode contents of file (%s) into Token representation: %v", path, err)
+ }
+ return &token, nil
+}
+
+// SaveToken persists an oauth token at the given location on disk.
+// It moves the new file into place so it can safely be used to replace an existing file
+// that maybe accessed by multiple processes.
+func SaveToken(path string, mode os.FileMode, token Token) error {
+ dir := filepath.Dir(path)
+ err := os.MkdirAll(dir, os.ModePerm)
+ if err != nil {
+ return fmt.Errorf("failed to create directory (%s) to store token in: %v", dir, err)
+ }
+
+ newFile, err := ioutil.TempFile(dir, "token")
+ if err != nil {
+ return fmt.Errorf("failed to create the temp file to write the token: %v", err)
+ }
+ tempPath := newFile.Name()
+
+ if err := json.NewEncoder(newFile).Encode(token); err != nil {
+ return fmt.Errorf("failed to encode token to file (%s) while saving token: %v", tempPath, err)
+ }
+ if err := newFile.Close(); err != nil {
+ return fmt.Errorf("failed to close temp file %s: %v", tempPath, err)
+ }
+
+ // Atomic replace to avoid multi-writer file corruptions
+ if err := os.Rename(tempPath, path); err != nil {
+ return fmt.Errorf("failed to move temporary token to desired output location. src=%s dst=%s: %v", tempPath, path, err)
+ }
+ if err := os.Chmod(path, mode); err != nil {
+ return fmt.Errorf("failed to chmod the token file %s: %v", path, err)
+ }
+ return nil
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/token.go b/vendor/github.com/Azure/go-autorest/autorest/azure/token.go
new file mode 100644
index 000000000..cfcd03011
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/azure/token.go
@@ -0,0 +1,363 @@
+package azure
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha1"
+ "crypto/x509"
+ "encoding/base64"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+
+ "github.com/Azure/go-autorest/autorest"
+ "github.com/dgrijalva/jwt-go"
+)
+
+const (
+ defaultRefresh = 5 * time.Minute
+ tokenBaseDate = "1970-01-01T00:00:00Z"
+
+ // OAuthGrantTypeDeviceCode is the "grant_type" identifier used in device flow
+ OAuthGrantTypeDeviceCode = "device_code"
+
+ // OAuthGrantTypeClientCredentials is the "grant_type" identifier used in credential flows
+ OAuthGrantTypeClientCredentials = "client_credentials"
+
+ // OAuthGrantTypeRefreshToken is the "grant_type" identifier used in refresh token flows
+ OAuthGrantTypeRefreshToken = "refresh_token"
+)
+
+var expirationBase time.Time
+
+func init() {
+ expirationBase, _ = time.Parse(time.RFC3339, tokenBaseDate)
+}
+
+// TokenRefreshCallback is the type representing callbacks that will be called after
+// a successful token refresh
+type TokenRefreshCallback func(Token) error
+
+// Token encapsulates the access token used to authorize Azure requests.
+type Token struct {
+ AccessToken string `json:"access_token"`
+ RefreshToken string `json:"refresh_token"`
+
+ ExpiresIn string `json:"expires_in"`
+ ExpiresOn string `json:"expires_on"`
+ NotBefore string `json:"not_before"`
+
+ Resource string `json:"resource"`
+ Type string `json:"token_type"`
+}
+
+// Expires returns the time.Time when the Token expires.
+func (t Token) Expires() time.Time {
+ s, err := strconv.Atoi(t.ExpiresOn)
+ if err != nil {
+ s = -3600
+ }
+ return expirationBase.Add(time.Duration(s) * time.Second).UTC()
+}
+
+// IsExpired returns true if the Token is expired, false otherwise.
+func (t Token) IsExpired() bool {
+ return t.WillExpireIn(0)
+}
+
+// WillExpireIn returns true if the Token will expire after the passed time.Duration interval
+// from now, false otherwise.
+func (t Token) WillExpireIn(d time.Duration) bool {
+ return !t.Expires().After(time.Now().Add(d))
+}
+
+// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
+// value is "Bearer " followed by the AccessToken of the Token.
+func (t *Token) WithAuthorization() autorest.PrepareDecorator {
+ return func(p autorest.Preparer) autorest.Preparer {
+ return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ return (autorest.WithBearerAuthorization(t.AccessToken)(p)).Prepare(r)
+ })
+ }
+}
+
+// ServicePrincipalNoSecret represents a secret type that contains no secret
+// meaning it is not valid for fetching a fresh token. This is used by Manual
+type ServicePrincipalNoSecret struct {
+}
+
+// SetAuthenticationValues is a method of the interface ServicePrincipalSecret
+// It only returns an error for the ServicePrincipalNoSecret type
+func (noSecret *ServicePrincipalNoSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
+ return fmt.Errorf("Manually created ServicePrincipalToken does not contain secret material to retrieve a new access token")
+}
+
+// ServicePrincipalSecret is an interface that allows various secret mechanism to fill the form
+// that is submitted when acquiring an oAuth token.
+type ServicePrincipalSecret interface {
+ SetAuthenticationValues(spt *ServicePrincipalToken, values *url.Values) error
+}
+
+// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization.
+type ServicePrincipalTokenSecret struct {
+ ClientSecret string
+}
+
+// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
+// It will populate the form submitted during oAuth Token Acquisition using the client_secret.
+func (tokenSecret *ServicePrincipalTokenSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
+ v.Set("client_secret", tokenSecret.ClientSecret)
+ return nil
+}
+
+// ServicePrincipalCertificateSecret implements ServicePrincipalSecret for generic RSA cert auth with signed JWTs.
+type ServicePrincipalCertificateSecret struct {
+ Certificate *x509.Certificate
+ PrivateKey *rsa.PrivateKey
+}
+
+// SignJwt returns the JWT signed with the certificate's private key.
+func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) {
+ hasher := sha1.New()
+ _, err := hasher.Write(secret.Certificate.Raw)
+ if err != nil {
+ return "", err
+ }
+
+ thumbprint := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
+
+ // The jti (JWT ID) claim provides a unique identifier for the JWT.
+ jti := make([]byte, 20)
+ _, err = rand.Read(jti)
+ if err != nil {
+ return "", err
+ }
+
+ token := jwt.New(jwt.SigningMethodRS256)
+ token.Header["x5t"] = thumbprint
+ token.Claims = jwt.MapClaims{
+ "aud": spt.oauthConfig.TokenEndpoint.String(),
+ "iss": spt.clientID,
+ "sub": spt.clientID,
+ "jti": base64.URLEncoding.EncodeToString(jti),
+ "nbf": time.Now().Unix(),
+ "exp": time.Now().Add(time.Hour * 24).Unix(),
+ }
+
+ signedString, err := token.SignedString(secret.PrivateKey)
+ return signedString, err
+}
+
+// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
+// It will populate the form submitted during oAuth Token Acquisition using a JWT signed with a certificate.
+func (secret *ServicePrincipalCertificateSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
+ jwt, err := secret.SignJwt(spt)
+ if err != nil {
+ return err
+ }
+
+ v.Set("client_assertion", jwt)
+ v.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
+ return nil
+}
+
+// ServicePrincipalToken encapsulates a Token created for a Service Principal.
+type ServicePrincipalToken struct {
+ Token
+
+ secret ServicePrincipalSecret
+ oauthConfig OAuthConfig
+ clientID string
+ resource string
+ autoRefresh bool
+ refreshWithin time.Duration
+ sender autorest.Sender
+
+ refreshCallbacks []TokenRefreshCallback
+}
+
+// NewServicePrincipalTokenWithSecret create a ServicePrincipalToken using the supplied ServicePrincipalSecret implementation.
+func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, resource string, secret ServicePrincipalSecret, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
+ spt := &ServicePrincipalToken{
+ oauthConfig: oauthConfig,
+ secret: secret,
+ clientID: id,
+ resource: resource,
+ autoRefresh: true,
+ refreshWithin: defaultRefresh,
+ sender: &http.Client{},
+ refreshCallbacks: callbacks,
+ }
+ return spt, nil
+}
+
+// NewServicePrincipalTokenFromManualToken creates a ServicePrincipalToken using the supplied token
+func NewServicePrincipalTokenFromManualToken(oauthConfig OAuthConfig, clientID string, resource string, token Token, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
+ spt, err := NewServicePrincipalTokenWithSecret(
+ oauthConfig,
+ clientID,
+ resource,
+ &ServicePrincipalNoSecret{},
+ callbacks...)
+ if err != nil {
+ return nil, err
+ }
+
+ spt.Token = token
+
+ return spt, nil
+}
+
+// NewServicePrincipalToken creates a ServicePrincipalToken from the supplied Service Principal
+// credentials scoped to the named resource.
+func NewServicePrincipalToken(oauthConfig OAuthConfig, clientID string, secret string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
+ return NewServicePrincipalTokenWithSecret(
+ oauthConfig,
+ clientID,
+ resource,
+ &ServicePrincipalTokenSecret{
+ ClientSecret: secret,
+ },
+ callbacks...,
+ )
+}
+
+// NewServicePrincipalTokenFromCertificate create a ServicePrincipalToken from the supplied pkcs12 bytes.
+func NewServicePrincipalTokenFromCertificate(oauthConfig OAuthConfig, clientID string, certificate *x509.Certificate, privateKey *rsa.PrivateKey, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
+ return NewServicePrincipalTokenWithSecret(
+ oauthConfig,
+ clientID,
+ resource,
+ &ServicePrincipalCertificateSecret{
+ PrivateKey: privateKey,
+ Certificate: certificate,
+ },
+ callbacks...,
+ )
+}
+
+// EnsureFresh will refresh the token if it will expire within the refresh window (as set by
+// RefreshWithin).
+func (spt *ServicePrincipalToken) EnsureFresh() error {
+ if spt.WillExpireIn(spt.refreshWithin) {
+ return spt.Refresh()
+ }
+ return nil
+}
+
+// InvokeRefreshCallbacks calls any TokenRefreshCallbacks that were added to the SPT during initialization
+func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error {
+ if spt.refreshCallbacks != nil {
+ for _, callback := range spt.refreshCallbacks {
+ err := callback(spt.Token)
+ if err != nil {
+ return autorest.NewErrorWithError(err,
+ "azure.ServicePrincipalToken", "InvokeRefreshCallbacks", nil, "A TokenRefreshCallback handler returned an error")
+ }
+ }
+ }
+ return nil
+}
+
+// Refresh obtains a fresh token for the Service Principal.
+func (spt *ServicePrincipalToken) Refresh() error {
+ return spt.refreshInternal(spt.resource)
+}
+
+// RefreshExchange refreshes the token, but for a different resource.
+func (spt *ServicePrincipalToken) RefreshExchange(resource string) error {
+ return spt.refreshInternal(resource)
+}
+
+func (spt *ServicePrincipalToken) refreshInternal(resource string) error {
+ v := url.Values{}
+ v.Set("client_id", spt.clientID)
+ v.Set("resource", resource)
+
+ if spt.RefreshToken != "" {
+ v.Set("grant_type", OAuthGrantTypeRefreshToken)
+ v.Set("refresh_token", spt.RefreshToken)
+ } else {
+ v.Set("grant_type", OAuthGrantTypeClientCredentials)
+ err := spt.secret.SetAuthenticationValues(spt, &v)
+ if err != nil {
+ return err
+ }
+ }
+
+ req, _ := autorest.Prepare(&http.Request{},
+ autorest.AsPost(),
+ autorest.AsFormURLEncoded(),
+ autorest.WithBaseURL(spt.oauthConfig.TokenEndpoint.String()),
+ autorest.WithFormData(v))
+
+ resp, err := autorest.SendWithSender(spt.sender, req)
+ if err != nil {
+ return autorest.NewErrorWithError(err,
+ "azure.ServicePrincipalToken", "Refresh", resp, "Failure sending request for Service Principal %s",
+ spt.clientID)
+ }
+
+ var newToken Token
+ err = autorest.Respond(resp,
+ autorest.WithErrorUnlessStatusCode(http.StatusOK),
+ autorest.ByUnmarshallingJSON(&newToken),
+ autorest.ByClosing())
+ if err != nil {
+ return autorest.NewErrorWithError(err,
+ "azure.ServicePrincipalToken", "Refresh", resp, "Failure handling response to Service Principal %s request",
+ spt.clientID)
+ }
+
+ spt.Token = newToken
+
+ err = spt.InvokeRefreshCallbacks(newToken)
+ if err != nil {
+ // its already wrapped inside InvokeRefreshCallbacks
+ return err
+ }
+
+ return nil
+}
+
+// SetAutoRefresh enables or disables automatic refreshing of stale tokens.
+func (spt *ServicePrincipalToken) SetAutoRefresh(autoRefresh bool) {
+ spt.autoRefresh = autoRefresh
+}
+
+// SetRefreshWithin sets the interval within which if the token will expire, EnsureFresh will
+// refresh the token.
+func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) {
+ spt.refreshWithin = d
+ return
+}
+
+// SetSender sets the autorest.Sender used when obtaining the Service Principal token. An
+// undecorated http.Client is used by default.
+func (spt *ServicePrincipalToken) SetSender(s autorest.Sender) {
+ spt.sender = s
+}
+
+// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
+// value is "Bearer " followed by the AccessToken of the ServicePrincipalToken.
+//
+// By default, the token will automatically refresh if nearly expired (as determined by the
+// RefreshWithin interval). Use the AutoRefresh method to enable or disable automatically refreshing
+// tokens.
+func (spt *ServicePrincipalToken) WithAuthorization() autorest.PrepareDecorator {
+ return func(p autorest.Preparer) autorest.Preparer {
+ return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ if spt.autoRefresh {
+ err := spt.EnsureFresh()
+ if err != nil {
+ return r, autorest.NewErrorWithError(err,
+ "azure.ServicePrincipalToken", "WithAuthorization", nil, "Failed to refresh Service Principal Token for request to %s",
+ r.URL)
+ }
+ }
+ return (autorest.WithBearerAuthorization(spt.AccessToken)(p)).Prepare(r)
+ })
+ }
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/client.go b/vendor/github.com/Azure/go-autorest/autorest/client.go
new file mode 100644
index 000000000..b5f94b5c3
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/client.go
@@ -0,0 +1,235 @@
+package autorest
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/http/cookiejar"
+ "runtime"
+ "time"
+)
+
+const (
+ // DefaultPollingDelay is a reasonable delay between polling requests.
+ DefaultPollingDelay = 60 * time.Second
+
+ // DefaultPollingDuration is a reasonable total polling duration.
+ DefaultPollingDuration = 15 * time.Minute
+
+ // DefaultRetryAttempts is number of attempts for retry status codes (5xx).
+ DefaultRetryAttempts = 3
+)
+
+var (
+ // defaultUserAgent builds a string containing the Go version, system archityecture and OS,
+ // and the go-autorest version.
+ defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s",
+ runtime.Version(),
+ runtime.GOARCH,
+ runtime.GOOS,
+ Version(),
+ )
+
+ statusCodesForRetry = []int{
+ http.StatusRequestTimeout, // 408
+ http.StatusInternalServerError, // 500
+ http.StatusBadGateway, // 502
+ http.StatusServiceUnavailable, // 503
+ http.StatusGatewayTimeout, // 504
+ }
+)
+
+const (
+ requestFormat = `HTTP Request Begin ===================================================
+%s
+===================================================== HTTP Request End
+`
+ responseFormat = `HTTP Response Begin ===================================================
+%s
+===================================================== HTTP Response End
+`
+)
+
+// Response serves as the base for all responses from generated clients. It provides access to the
+// last http.Response.
+type Response struct {
+ *http.Response `json:"-"`
+}
+
+// LoggingInspector implements request and response inspectors that log the full request and
+// response to a supplied log.
+type LoggingInspector struct {
+ Logger *log.Logger
+}
+
+// WithInspection returns a PrepareDecorator that emits the http.Request to the supplied logger. The
+// body is restored after being emitted.
+//
+// Note: Since it reads the entire Body, this decorator should not be used where body streaming is
+// important. It is best used to trace JSON or similar body values.
+func (li LoggingInspector) WithInspection() PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ var body, b bytes.Buffer
+
+ defer r.Body.Close()
+
+ r.Body = ioutil.NopCloser(io.TeeReader(r.Body, &body))
+ if err := r.Write(&b); err != nil {
+ return nil, fmt.Errorf("Failed to write response: %v", err)
+ }
+
+ li.Logger.Printf(requestFormat, b.String())
+
+ r.Body = ioutil.NopCloser(&body)
+ return p.Prepare(r)
+ })
+ }
+}
+
+// ByInspecting returns a RespondDecorator that emits the http.Response to the supplied logger. The
+// body is restored after being emitted.
+//
+// Note: Since it reads the entire Body, this decorator should not be used where body streaming is
+// important. It is best used to trace JSON or similar body values.
+func (li LoggingInspector) ByInspecting() RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ var body, b bytes.Buffer
+ defer resp.Body.Close()
+ resp.Body = ioutil.NopCloser(io.TeeReader(resp.Body, &body))
+ if err := resp.Write(&b); err != nil {
+ return fmt.Errorf("Failed to write response: %v", err)
+ }
+
+ li.Logger.Printf(responseFormat, b.String())
+
+ resp.Body = ioutil.NopCloser(&body)
+ return r.Respond(resp)
+ })
+ }
+}
+
+// Client is the base for autorest generated clients. It provides default, "do nothing"
+// implementations of an Authorizer, RequestInspector, and ResponseInspector. It also returns the
+// standard, undecorated http.Client as a default Sender.
+//
+// Generated clients should also use Error (see NewError and NewErrorWithError) for errors and
+// return responses that compose with Response.
+//
+// Most customization of generated clients is best achieved by supplying a custom Authorizer, custom
+// RequestInspector, and / or custom ResponseInspector. Users may log requests, implement circuit
+// breakers (see https://msdn.microsoft.com/en-us/library/dn589784.aspx) or otherwise influence
+// sending the request by providing a decorated Sender.
+type Client struct {
+ Authorizer Authorizer
+ Sender Sender
+ RequestInspector PrepareDecorator
+ ResponseInspector RespondDecorator
+
+ // PollingDelay sets the polling frequency used in absence of a Retry-After HTTP header
+ PollingDelay time.Duration
+
+ // PollingDuration sets the maximum polling time after which an error is returned.
+ PollingDuration time.Duration
+
+ // RetryAttempts sets the default number of retry attempts for client.
+ RetryAttempts int
+
+ // RetryDuration sets the delay duration for retries.
+ RetryDuration time.Duration
+
+ // UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent
+ // through the Do method.
+ UserAgent string
+
+ Jar http.CookieJar
+}
+
+// NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed
+// string.
+func NewClientWithUserAgent(ua string) Client {
+ c := Client{
+ PollingDelay: DefaultPollingDelay,
+ PollingDuration: DefaultPollingDuration,
+ RetryAttempts: DefaultRetryAttempts,
+ RetryDuration: 30 * time.Second,
+ UserAgent: defaultUserAgent,
+ }
+ c.AddToUserAgent(ua)
+ return c
+}
+
+// AddToUserAgent adds an extension to the current user agent
+func (c *Client) AddToUserAgent(extension string) error {
+ if extension != "" {
+ c.UserAgent = fmt.Sprintf("%s %s", c.UserAgent, extension)
+ return nil
+ }
+ return fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent)
+}
+
+// Do implements the Sender interface by invoking the active Sender after applying authorization.
+// If Sender is not set, it uses a new instance of http.Client. In both cases it will, if UserAgent
+// is set, apply set the User-Agent header.
+func (c Client) Do(r *http.Request) (*http.Response, error) {
+ if r.UserAgent() == "" {
+ r, _ = Prepare(r,
+ WithUserAgent(c.UserAgent))
+ }
+ r, err := Prepare(r,
+ c.WithInspection(),
+ c.WithAuthorization())
+ if err != nil {
+ return nil, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed")
+ }
+ resp, err := SendWithSender(c.sender(), r,
+ DoRetryForStatusCodes(c.RetryAttempts, c.RetryDuration, statusCodesForRetry...))
+ Respond(resp,
+ c.ByInspecting())
+ return resp, err
+}
+
+// sender returns the Sender to which to send requests.
+func (c Client) sender() Sender {
+ if c.Sender == nil {
+ j, _ := cookiejar.New(nil)
+ return &http.Client{Jar: j}
+ }
+ return c.Sender
+}
+
+// WithAuthorization is a convenience method that returns the WithAuthorization PrepareDecorator
+// from the current Authorizer. If not Authorizer is set, it uses the NullAuthorizer.
+func (c Client) WithAuthorization() PrepareDecorator {
+ return c.authorizer().WithAuthorization()
+}
+
+// authorizer returns the Authorizer to use.
+func (c Client) authorizer() Authorizer {
+ if c.Authorizer == nil {
+ return NullAuthorizer{}
+ }
+ return c.Authorizer
+}
+
+// WithInspection is a convenience method that passes the request to the supplied RequestInspector,
+// if present, or returns the WithNothing PrepareDecorator otherwise.
+func (c Client) WithInspection() PrepareDecorator {
+ if c.RequestInspector == nil {
+ return WithNothing()
+ }
+ return c.RequestInspector
+}
+
+// ByInspecting is a convenience method that passes the response to the supplied ResponseInspector,
+// if present, or returns the ByIgnoring RespondDecorator otherwise.
+func (c Client) ByInspecting() RespondDecorator {
+ if c.ResponseInspector == nil {
+ return ByIgnoring()
+ }
+ return c.ResponseInspector
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/date.go b/vendor/github.com/Azure/go-autorest/autorest/date/date.go
new file mode 100644
index 000000000..80ca60e9b
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/date/date.go
@@ -0,0 +1,82 @@
+/*
+Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/)
+defined date formats: Date and DateTime. Both types may, in most cases, be used in lieu of
+time.Time types. And both convert to time.Time through a ToTime method.
+*/
+package date
+
+import (
+ "fmt"
+ "time"
+)
+
+const (
+ fullDate = "2006-01-02"
+ fullDateJSON = `"2006-01-02"`
+ dateFormat = "%04d-%02d-%02d"
+ jsonFormat = `"%04d-%02d-%02d"`
+)
+
+// Date defines a type similar to time.Time but assumes a layout of RFC3339 full-date (i.e.,
+// 2006-01-02).
+type Date struct {
+ time.Time
+}
+
+// ParseDate create a new Date from the passed string.
+func ParseDate(date string) (d Date, err error) {
+ return parseDate(date, fullDate)
+}
+
+func parseDate(date string, format string) (Date, error) {
+ d, err := time.Parse(format, date)
+ return Date{Time: d}, err
+}
+
+// MarshalBinary preserves the Date as a byte array conforming to RFC3339 full-date (i.e.,
+// 2006-01-02).
+func (d Date) MarshalBinary() ([]byte, error) {
+ return d.MarshalText()
+}
+
+// UnmarshalBinary reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e.,
+// 2006-01-02).
+func (d *Date) UnmarshalBinary(data []byte) error {
+ return d.UnmarshalText(data)
+}
+
+// MarshalJSON preserves the Date as a JSON string conforming to RFC3339 full-date (i.e.,
+// 2006-01-02).
+func (d Date) MarshalJSON() (json []byte, err error) {
+ return []byte(fmt.Sprintf(jsonFormat, d.Year(), d.Month(), d.Day())), nil
+}
+
+// UnmarshalJSON reconstitutes the Date from a JSON string conforming to RFC3339 full-date (i.e.,
+// 2006-01-02).
+func (d *Date) UnmarshalJSON(data []byte) (err error) {
+ d.Time, err = time.Parse(fullDateJSON, string(data))
+ return err
+}
+
+// MarshalText preserves the Date as a byte array conforming to RFC3339 full-date (i.e.,
+// 2006-01-02).
+func (d Date) MarshalText() (text []byte, err error) {
+ return []byte(fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())), nil
+}
+
+// UnmarshalText reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e.,
+// 2006-01-02).
+func (d *Date) UnmarshalText(data []byte) (err error) {
+ d.Time, err = time.Parse(fullDate, string(data))
+ return err
+}
+
+// String returns the Date formatted as an RFC3339 full-date string (i.e., 2006-01-02).
+func (d Date) String() string {
+ return fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())
+}
+
+// ToTime returns a Date as a time.Time
+func (d Date) ToTime() time.Time {
+ return d.Time
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/time.go b/vendor/github.com/Azure/go-autorest/autorest/date/time.go
new file mode 100644
index 000000000..c1af62963
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/date/time.go
@@ -0,0 +1,89 @@
+package date
+
+import (
+ "regexp"
+ "time"
+)
+
+// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases.
+const (
+ azureUtcFormatJSON = `"2006-01-02T15:04:05.999999999"`
+ azureUtcFormat = "2006-01-02T15:04:05.999999999"
+ rfc3339JSON = `"` + time.RFC3339Nano + `"`
+ rfc3339 = time.RFC3339Nano
+ tzOffsetRegex = `(Z|z|\+|-)(\d+:\d+)*"*$`
+)
+
+// Time defines a type similar to time.Time but assumes a layout of RFC3339 date-time (i.e.,
+// 2006-01-02T15:04:05Z).
+type Time struct {
+ time.Time
+}
+
+// MarshalBinary preserves the Time as a byte array conforming to RFC3339 date-time (i.e.,
+// 2006-01-02T15:04:05Z).
+func (t Time) MarshalBinary() ([]byte, error) {
+ return t.Time.MarshalText()
+}
+
+// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC3339 date-time
+// (i.e., 2006-01-02T15:04:05Z).
+func (t *Time) UnmarshalBinary(data []byte) error {
+ return t.UnmarshalText(data)
+}
+
+// MarshalJSON preserves the Time as a JSON string conforming to RFC3339 date-time (i.e.,
+// 2006-01-02T15:04:05Z).
+func (t Time) MarshalJSON() (json []byte, err error) {
+ return t.Time.MarshalJSON()
+}
+
+// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC3339 date-time
+// (i.e., 2006-01-02T15:04:05Z).
+func (t *Time) UnmarshalJSON(data []byte) (err error) {
+ timeFormat := azureUtcFormatJSON
+ match, err := regexp.Match(tzOffsetRegex, data)
+ if err != nil {
+ return err
+ } else if match {
+ timeFormat = rfc3339JSON
+ }
+ t.Time, err = ParseTime(timeFormat, string(data))
+ return err
+}
+
+// MarshalText preserves the Time as a byte array conforming to RFC3339 date-time (i.e.,
+// 2006-01-02T15:04:05Z).
+func (t Time) MarshalText() (text []byte, err error) {
+ return t.Time.MarshalText()
+}
+
+// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC3339 date-time
+// (i.e., 2006-01-02T15:04:05Z).
+func (t *Time) UnmarshalText(data []byte) (err error) {
+ timeFormat := azureUtcFormat
+ match, err := regexp.Match(tzOffsetRegex, data)
+ if err != nil {
+ return err
+ } else if match {
+ timeFormat = rfc3339
+ }
+ t.Time, err = ParseTime(timeFormat, string(data))
+ return err
+}
+
+// String returns the Time formatted as an RFC3339 date-time string (i.e.,
+// 2006-01-02T15:04:05Z).
+func (t Time) String() string {
+ // Note: time.Time.String does not return an RFC3339 compliant string, time.Time.MarshalText does.
+ b, err := t.MarshalText()
+ if err != nil {
+ return ""
+ }
+ return string(b)
+}
+
+// ToTime returns a Time as a time.Time
+func (t Time) ToTime() time.Time {
+ return t.Time
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go b/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go
new file mode 100644
index 000000000..11995fb9f
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go
@@ -0,0 +1,86 @@
+package date
+
+import (
+ "errors"
+ "time"
+)
+
+const (
+ rfc1123JSON = `"` + time.RFC1123 + `"`
+ rfc1123 = time.RFC1123
+)
+
+// TimeRFC1123 defines a type similar to time.Time but assumes a layout of RFC1123 date-time (i.e.,
+// Mon, 02 Jan 2006 15:04:05 MST).
+type TimeRFC1123 struct {
+ time.Time
+}
+
+// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC1123 date-time
+// (i.e., Mon, 02 Jan 2006 15:04:05 MST).
+func (t *TimeRFC1123) UnmarshalJSON(data []byte) (err error) {
+ t.Time, err = ParseTime(rfc1123JSON, string(data))
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// MarshalJSON preserves the Time as a JSON string conforming to RFC1123 date-time (i.e.,
+// Mon, 02 Jan 2006 15:04:05 MST).
+func (t TimeRFC1123) MarshalJSON() ([]byte, error) {
+ if y := t.Year(); y < 0 || y >= 10000 {
+ return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
+ }
+ b := []byte(t.Format(rfc1123JSON))
+ return b, nil
+}
+
+// MarshalText preserves the Time as a byte array conforming to RFC1123 date-time (i.e.,
+// Mon, 02 Jan 2006 15:04:05 MST).
+func (t TimeRFC1123) MarshalText() ([]byte, error) {
+ if y := t.Year(); y < 0 || y >= 10000 {
+ return nil, errors.New("Time.MarshalText: year outside of range [0,9999]")
+ }
+
+ b := []byte(t.Format(rfc1123))
+ return b, nil
+}
+
+// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC1123 date-time
+// (i.e., Mon, 02 Jan 2006 15:04:05 MST).
+func (t *TimeRFC1123) UnmarshalText(data []byte) (err error) {
+ t.Time, err = ParseTime(rfc1123, string(data))
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// MarshalBinary preserves the Time as a byte array conforming to RFC1123 date-time (i.e.,
+// Mon, 02 Jan 2006 15:04:05 MST).
+func (t TimeRFC1123) MarshalBinary() ([]byte, error) {
+ return t.MarshalText()
+}
+
+// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC1123 date-time
+// (i.e., Mon, 02 Jan 2006 15:04:05 MST).
+func (t *TimeRFC1123) UnmarshalBinary(data []byte) error {
+ return t.UnmarshalText(data)
+}
+
+// ToTime returns a Time as a time.Time
+func (t TimeRFC1123) ToTime() time.Time {
+ return t.Time
+}
+
+// String returns the Time formatted as an RFC1123 date-time string (i.e.,
+// Mon, 02 Jan 2006 15:04:05 MST).
+func (t TimeRFC1123) String() string {
+ // Note: time.Time.String does not return an RFC1123 compliant string, time.Time.MarshalText does.
+ b, err := t.MarshalText()
+ if err != nil {
+ return ""
+ }
+ return string(b)
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/utility.go b/vendor/github.com/Azure/go-autorest/autorest/date/utility.go
new file mode 100644
index 000000000..207b1a240
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/date/utility.go
@@ -0,0 +1,11 @@
+package date
+
+import (
+ "strings"
+ "time"
+)
+
+// ParseTime to parse Time string to specified format.
+func ParseTime(format string, t string) (d time.Time, err error) {
+ return time.Parse(format, strings.ToUpper(t))
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/error.go b/vendor/github.com/Azure/go-autorest/autorest/error.go
new file mode 100644
index 000000000..4bcb8f27b
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/error.go
@@ -0,0 +1,80 @@
+package autorest
+
+import (
+ "fmt"
+ "net/http"
+)
+
+const (
+ // UndefinedStatusCode is used when HTTP status code is not available for an error.
+ UndefinedStatusCode = 0
+)
+
+// DetailedError encloses a error with details of the package, method, and associated HTTP
+// status code (if any).
+type DetailedError struct {
+ Original error
+
+ // PackageType is the package type of the object emitting the error. For types, the value
+ // matches that produced the the '%T' format specifier of the fmt package. For other elements,
+ // such as functions, it is just the package name (e.g., "autorest").
+ PackageType string
+
+ // Method is the name of the method raising the error.
+ Method string
+
+ // StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error.
+ StatusCode interface{}
+
+ // Message is the error message.
+ Message string
+
+ // Service Error is the response body of failed API in bytes
+ ServiceError []byte
+}
+
+// NewError creates a new Error conforming object from the passed packageType, method, and
+// message. message is treated as a format string to which the optional args apply.
+func NewError(packageType string, method string, message string, args ...interface{}) DetailedError {
+ return NewErrorWithError(nil, packageType, method, nil, message, args...)
+}
+
+// NewErrorWithResponse creates a new Error conforming object from the passed
+// packageType, method, statusCode of the given resp (UndefinedStatusCode if
+// resp is nil), and message. message is treated as a format string to which the
+// optional args apply.
+func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError {
+ return NewErrorWithError(nil, packageType, method, resp, message, args...)
+}
+
+// NewErrorWithError creates a new Error conforming object from the
+// passed packageType, method, statusCode of the given resp (UndefinedStatusCode
+// if resp is nil), message, and original error. message is treated as a format
+// string to which the optional args apply.
+func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError {
+ if v, ok := original.(DetailedError); ok {
+ return v
+ }
+
+ statusCode := UndefinedStatusCode
+ if resp != nil {
+ statusCode = resp.StatusCode
+ }
+
+ return DetailedError{
+ Original: original,
+ PackageType: packageType,
+ Method: method,
+ StatusCode: statusCode,
+ Message: fmt.Sprintf(message, args...),
+ }
+}
+
+// Error returns a formatted containing all available details (i.e., PackageType, Method,
+// StatusCode, Message, and original error (if any)).
+func (e DetailedError) Error() string {
+ if e.Original == nil {
+ return fmt.Sprintf("%s#%s: %s: StatusCode=%d", e.PackageType, e.Method, e.Message, e.StatusCode)
+ }
+ return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original)
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer.go b/vendor/github.com/Azure/go-autorest/autorest/preparer.go
new file mode 100644
index 000000000..c9deb261a
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/preparer.go
@@ -0,0 +1,443 @@
+package autorest
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+const (
+ mimeTypeJSON = "application/json"
+ mimeTypeFormPost = "application/x-www-form-urlencoded"
+
+ headerAuthorization = "Authorization"
+ headerContentType = "Content-Type"
+ headerUserAgent = "User-Agent"
+)
+
+// Preparer is the interface that wraps the Prepare method.
+//
+// Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations
+// must ensure to not share or hold per-invocation state since Preparers may be shared and re-used.
+type Preparer interface {
+ Prepare(*http.Request) (*http.Request, error)
+}
+
+// PreparerFunc is a method that implements the Preparer interface.
+type PreparerFunc func(*http.Request) (*http.Request, error)
+
+// Prepare implements the Preparer interface on PreparerFunc.
+func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) {
+ return pf(r)
+}
+
+// PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the
+// http.Request and pass it along or, first, pass the http.Request along then affect the result.
+type PrepareDecorator func(Preparer) Preparer
+
+// CreatePreparer creates, decorates, and returns a Preparer.
+// Without decorators, the returned Preparer returns the passed http.Request unmodified.
+// Preparers are safe to share and re-use.
+func CreatePreparer(decorators ...PrepareDecorator) Preparer {
+ return DecoratePreparer(
+ Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })),
+ decorators...)
+}
+
+// DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it
+// applies to the Preparer. Decorators are applied in the order received, but their affect upon the
+// request depends on whether they are a pre-decorator (change the http.Request and then pass it
+// along) or a post-decorator (pass the http.Request along and alter it on return).
+func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer {
+ for _, decorate := range decorators {
+ p = decorate(p)
+ }
+ return p
+}
+
+// Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators.
+// It creates a Preparer from the decorators which it then applies to the passed http.Request.
+func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) {
+ if r == nil {
+ return nil, NewError("autorest", "Prepare", "Invoked without an http.Request")
+ }
+ return CreatePreparer(decorators...).Prepare(r)
+}
+
+// WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed
+// http.Request.
+func WithNothing() PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ return p.Prepare(r)
+ })
+ }
+}
+
+// WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to
+// the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before
+// adding the header.
+func WithHeader(header string, value string) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ if r.Header == nil {
+ r.Header = make(http.Header)
+ }
+ r.Header.Set(http.CanonicalHeaderKey(header), value)
+ }
+ return r, err
+ })
+ }
+}
+
+// WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
+// value is "Bearer " followed by the supplied token.
+func WithBearerAuthorization(token string) PrepareDecorator {
+ return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token))
+}
+
+// AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value
+// is the passed contentType.
+func AsContentType(contentType string) PrepareDecorator {
+ return WithHeader(headerContentType, contentType)
+}
+
+// WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the
+// passed string.
+func WithUserAgent(ua string) PrepareDecorator {
+ return WithHeader(headerUserAgent, ua)
+}
+
+// AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
+// "application/x-www-form-urlencoded".
+func AsFormURLEncoded() PrepareDecorator {
+ return AsContentType(mimeTypeFormPost)
+}
+
+// AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
+// "application/json".
+func AsJSON() PrepareDecorator {
+ return AsContentType(mimeTypeJSON)
+}
+
+// WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The
+// decorator does not validate that the passed method string is a known HTTP method.
+func WithMethod(method string) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r.Method = method
+ return p.Prepare(r)
+ })
+ }
+}
+
+// AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE.
+func AsDelete() PrepareDecorator { return WithMethod("DELETE") }
+
+// AsGet returns a PrepareDecorator that sets the HTTP method to GET.
+func AsGet() PrepareDecorator { return WithMethod("GET") }
+
+// AsHead returns a PrepareDecorator that sets the HTTP method to HEAD.
+func AsHead() PrepareDecorator { return WithMethod("HEAD") }
+
+// AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS.
+func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") }
+
+// AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH.
+func AsPatch() PrepareDecorator { return WithMethod("PATCH") }
+
+// AsPost returns a PrepareDecorator that sets the HTTP method to POST.
+func AsPost() PrepareDecorator { return WithMethod("POST") }
+
+// AsPut returns a PrepareDecorator that sets the HTTP method to PUT.
+func AsPut() PrepareDecorator { return WithMethod("PUT") }
+
+// WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed
+// from the supplied baseUrl.
+func WithBaseURL(baseURL string) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ var u *url.URL
+ if u, err = url.Parse(baseURL); err != nil {
+ return r, err
+ }
+ if u.Scheme == "" {
+ err = fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
+ }
+ if err == nil {
+ r.URL = u
+ }
+ }
+ return r, err
+ })
+ }
+}
+
+// WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the
+// request base URL (i.e., http.Request.URL) with the corresponding values from the passed map.
+func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator {
+ parameters := ensureValueStrings(urlParameters)
+ for key, value := range parameters {
+ baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1)
+ }
+ return WithBaseURL(baseURL)
+}
+
+// WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the
+// http.Request body.
+func WithFormData(v url.Values) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ s := v.Encode()
+ r.ContentLength = int64(len(s))
+ r.Body = ioutil.NopCloser(strings.NewReader(s))
+ }
+ return r, err
+ })
+ }
+}
+
+// WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters
+// into the http.Request body.
+func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ var body bytes.Buffer
+ writer := multipart.NewWriter(&body)
+ for key, value := range formDataParameters {
+ if rc, ok := value.(io.ReadCloser); ok {
+ var fd io.Writer
+ if fd, err = writer.CreateFormFile(key, key); err != nil {
+ return r, err
+ }
+ if _, err = io.Copy(fd, rc); err != nil {
+ return r, err
+ }
+ } else {
+ if err = writer.WriteField(key, ensureValueString(value)); err != nil {
+ return r, err
+ }
+ }
+ }
+ if err = writer.Close(); err != nil {
+ return r, err
+ }
+ if r.Header == nil {
+ r.Header = make(http.Header)
+ }
+ r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
+ r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
+ r.ContentLength = int64(body.Len())
+ return r, err
+ }
+ return r, err
+ })
+ }
+}
+
+// WithFile returns a PrepareDecorator that sends file in request body.
+func WithFile(f io.ReadCloser) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ b, err := ioutil.ReadAll(f)
+ if err != nil {
+ return r, err
+ }
+ r.Body = ioutil.NopCloser(bytes.NewReader(b))
+ r.ContentLength = int64(len(b))
+ }
+ return r, err
+ })
+ }
+}
+
+// WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request
+// and sets the Content-Length header.
+func WithBool(v bool) PrepareDecorator {
+ return WithString(fmt.Sprintf("%v", v))
+}
+
+// WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the
+// request and sets the Content-Length header.
+func WithFloat32(v float32) PrepareDecorator {
+ return WithString(fmt.Sprintf("%v", v))
+}
+
+// WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the
+// request and sets the Content-Length header.
+func WithFloat64(v float64) PrepareDecorator {
+ return WithString(fmt.Sprintf("%v", v))
+}
+
+// WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request
+// and sets the Content-Length header.
+func WithInt32(v int32) PrepareDecorator {
+ return WithString(fmt.Sprintf("%v", v))
+}
+
+// WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request
+// and sets the Content-Length header.
+func WithInt64(v int64) PrepareDecorator {
+ return WithString(fmt.Sprintf("%v", v))
+}
+
+// WithString returns a PrepareDecorator that encodes the passed string into the body of the request
+// and sets the Content-Length header.
+func WithString(v string) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ r.ContentLength = int64(len(v))
+ r.Body = ioutil.NopCloser(strings.NewReader(v))
+ }
+ return r, err
+ })
+ }
+}
+
+// WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the
+// request and sets the Content-Length header.
+func WithJSON(v interface{}) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ b, err := json.Marshal(v)
+ if err == nil {
+ r.ContentLength = int64(len(b))
+ r.Body = ioutil.NopCloser(bytes.NewReader(b))
+ }
+ }
+ return r, err
+ })
+ }
+}
+
+// WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path
+// is absolute (that is, it begins with a "/"), it replaces the existing path.
+func WithPath(path string) PrepareDecorator {
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ if r.URL == nil {
+ return r, NewError("autorest", "WithPath", "Invoked with a nil URL")
+ }
+ if r.URL, err = parseURL(r.URL, path); err != nil {
+ return r, err
+ }
+ }
+ return r, err
+ })
+ }
+}
+
+// WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
+// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The
+// values will be escaped (aka URL encoded) before insertion into the path.
+func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
+ parameters := escapeValueStrings(ensureValueStrings(pathParameters))
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ if r.URL == nil {
+ return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL")
+ }
+ for key, value := range parameters {
+ path = strings.Replace(path, "{"+key+"}", value, -1)
+ }
+ if r.URL, err = parseURL(r.URL, path); err != nil {
+ return r, err
+ }
+ }
+ return r, err
+ })
+ }
+}
+
+// WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
+// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map.
+func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
+ parameters := ensureValueStrings(pathParameters)
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ if r.URL == nil {
+ return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL")
+ }
+ for key, value := range parameters {
+ path = strings.Replace(path, "{"+key+"}", value, -1)
+ }
+
+ if r.URL, err = parseURL(r.URL, path); err != nil {
+ return r, err
+ }
+ }
+ return r, err
+ })
+ }
+}
+
+func parseURL(u *url.URL, path string) (*url.URL, error) {
+ p := strings.TrimRight(u.String(), "/")
+ if !strings.HasPrefix(path, "/") {
+ path = "/" + path
+ }
+ return url.Parse(p + path)
+}
+
+// WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters
+// given in the supplied map (i.e., key=value).
+func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator {
+ parameters := ensureValueStrings(queryParameters)
+ return func(p Preparer) Preparer {
+ return PreparerFunc(func(r *http.Request) (*http.Request, error) {
+ r, err := p.Prepare(r)
+ if err == nil {
+ if r.URL == nil {
+ return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL")
+ }
+ v := r.URL.Query()
+ for key, value := range parameters {
+ v.Add(key, value)
+ }
+ r.URL.RawQuery = createQuery(v)
+ }
+ return r, err
+ })
+ }
+}
+
+// Authorizer is the interface that provides a PrepareDecorator used to supply request
+// authorization. Most often, the Authorizer decorator runs last so it has access to the full
+// state of the formed HTTP request.
+type Authorizer interface {
+ WithAuthorization() PrepareDecorator
+}
+
+// NullAuthorizer implements a default, "do nothing" Authorizer.
+type NullAuthorizer struct{}
+
+// WithAuthorization returns a PrepareDecorator that does nothing.
+func (na NullAuthorizer) WithAuthorization() PrepareDecorator {
+ return WithNothing()
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/responder.go b/vendor/github.com/Azure/go-autorest/autorest/responder.go
new file mode 100644
index 000000000..87f71e585
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/responder.go
@@ -0,0 +1,236 @@
+package autorest
+
+import (
+ "bytes"
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strings"
+)
+
+// Responder is the interface that wraps the Respond method.
+//
+// Respond accepts and reacts to an http.Response. Implementations must ensure to not share or hold
+// state since Responders may be shared and re-used.
+type Responder interface {
+ Respond(*http.Response) error
+}
+
+// ResponderFunc is a method that implements the Responder interface.
+type ResponderFunc func(*http.Response) error
+
+// Respond implements the Responder interface on ResponderFunc.
+func (rf ResponderFunc) Respond(r *http.Response) error {
+ return rf(r)
+}
+
+// RespondDecorator takes and possibly decorates, by wrapping, a Responder. Decorators may react to
+// the http.Response and pass it along or, first, pass the http.Response along then react.
+type RespondDecorator func(Responder) Responder
+
+// CreateResponder creates, decorates, and returns a Responder. Without decorators, the returned
+// Responder returns the passed http.Response unmodified. Responders may or may not be safe to share
+// and re-used: It depends on the applied decorators. For example, a standard decorator that closes
+// the response body is fine to share whereas a decorator that reads the body into a passed struct
+// is not.
+//
+// To prevent memory leaks, ensure that at least one Responder closes the response body.
+func CreateResponder(decorators ...RespondDecorator) Responder {
+ return DecorateResponder(
+ Responder(ResponderFunc(func(r *http.Response) error { return nil })),
+ decorators...)
+}
+
+// DecorateResponder accepts a Responder and a, possibly empty, set of RespondDecorators, which it
+// applies to the Responder. Decorators are applied in the order received, but their affect upon the
+// request depends on whether they are a pre-decorator (react to the http.Response and then pass it
+// along) or a post-decorator (pass the http.Response along and then react).
+func DecorateResponder(r Responder, decorators ...RespondDecorator) Responder {
+ for _, decorate := range decorators {
+ r = decorate(r)
+ }
+ return r
+}
+
+// Respond accepts an http.Response and a, possibly empty, set of RespondDecorators.
+// It creates a Responder from the decorators it then applies to the passed http.Response.
+func Respond(r *http.Response, decorators ...RespondDecorator) error {
+ if r == nil {
+ return nil
+ }
+ return CreateResponder(decorators...).Respond(r)
+}
+
+// ByIgnoring returns a RespondDecorator that ignores the passed http.Response passing it unexamined
+// to the next RespondDecorator.
+func ByIgnoring() RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ return r.Respond(resp)
+ })
+ }
+}
+
+// ByCopying copies the contents of the http.Response Body into the passed bytes.Buffer as
+// the Body is read.
+func ByCopying(b *bytes.Buffer) RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err == nil && resp != nil && resp.Body != nil {
+ resp.Body = TeeReadCloser(resp.Body, b)
+ }
+ return err
+ })
+ }
+}
+
+// ByDiscardingBody returns a RespondDecorator that first invokes the passed Responder after which
+// it copies the remaining bytes (if any) in the response body to ioutil.Discard. Since the passed
+// Responder is invoked prior to discarding the response body, the decorator may occur anywhere
+// within the set.
+func ByDiscardingBody() RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err == nil && resp != nil && resp.Body != nil {
+ if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
+ return fmt.Errorf("Error discarding the response body: %v", err)
+ }
+ }
+ return err
+ })
+ }
+}
+
+// ByClosing returns a RespondDecorator that first invokes the passed Responder after which it
+// closes the response body. Since the passed Responder is invoked prior to closing the response
+// body, the decorator may occur anywhere within the set.
+func ByClosing() RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if resp != nil && resp.Body != nil {
+ if err := resp.Body.Close(); err != nil {
+ return fmt.Errorf("Error closing the response body: %v", err)
+ }
+ }
+ return err
+ })
+ }
+}
+
+// ByClosingIfError returns a RespondDecorator that first invokes the passed Responder after which
+// it closes the response if the passed Responder returns an error and the response body exists.
+func ByClosingIfError() RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err != nil && resp != nil && resp.Body != nil {
+ if err := resp.Body.Close(); err != nil {
+ return fmt.Errorf("Error closing the response body: %v", err)
+ }
+ }
+ return err
+ })
+ }
+}
+
+// ByUnmarshallingJSON returns a RespondDecorator that decodes a JSON document returned in the
+// response Body into the value pointed to by v.
+func ByUnmarshallingJSON(v interface{}) RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err == nil {
+ b, errInner := ioutil.ReadAll(resp.Body)
+ // Some responses might include a BOM, remove for successful unmarshalling
+ b = bytes.TrimPrefix(b, []byte("\xef\xbb\xbf"))
+ if errInner != nil {
+ err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner)
+ } else if len(strings.Trim(string(b), " ")) > 0 {
+ errInner = json.Unmarshal(b, v)
+ if errInner != nil {
+ err = fmt.Errorf("Error occurred unmarshalling JSON - Error = '%v' JSON = '%s'", errInner, string(b))
+ }
+ }
+ }
+ return err
+ })
+ }
+}
+
+// ByUnmarshallingXML returns a RespondDecorator that decodes a XML document returned in the
+// response Body into the value pointed to by v.
+func ByUnmarshallingXML(v interface{}) RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err == nil {
+ b, errInner := ioutil.ReadAll(resp.Body)
+ if errInner != nil {
+ err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner)
+ } else {
+ errInner = xml.Unmarshal(b, v)
+ if errInner != nil {
+ err = fmt.Errorf("Error occurred unmarshalling Xml - Error = '%v' Xml = '%s'", errInner, string(b))
+ }
+ }
+ }
+ return err
+ })
+ }
+}
+
+// WithErrorUnlessStatusCode returns a RespondDecorator that emits an error unless the response
+// StatusCode is among the set passed. On error, response body is fully read into a buffer and
+// presented in the returned error, as well as in the response body.
+func WithErrorUnlessStatusCode(codes ...int) RespondDecorator {
+ return func(r Responder) Responder {
+ return ResponderFunc(func(resp *http.Response) error {
+ err := r.Respond(resp)
+ if err == nil && !ResponseHasStatusCode(resp, codes...) {
+ derr := NewErrorWithResponse("autorest", "WithErrorUnlessStatusCode", resp, "%v %v failed with %s",
+ resp.Request.Method,
+ resp.Request.URL,
+ resp.Status)
+ if resp.Body != nil {
+ defer resp.Body.Close()
+ b, _ := ioutil.ReadAll(resp.Body)
+ derr.ServiceError = b
+ resp.Body = ioutil.NopCloser(bytes.NewReader(b))
+ }
+ err = derr
+ }
+ return err
+ })
+ }
+}
+
+// WithErrorUnlessOK returns a RespondDecorator that emits an error if the response StatusCode is
+// anything other than HTTP 200.
+func WithErrorUnlessOK() RespondDecorator {
+ return WithErrorUnlessStatusCode(http.StatusOK)
+}
+
+// ExtractHeader extracts all values of the specified header from the http.Response. It returns an
+// empty string slice if the passed http.Response is nil or the header does not exist.
+func ExtractHeader(header string, resp *http.Response) []string {
+ if resp != nil && resp.Header != nil {
+ return resp.Header[http.CanonicalHeaderKey(header)]
+ }
+ return nil
+}
+
+// ExtractHeaderValue extracts the first value of the specified header from the http.Response. It
+// returns an empty string if the passed http.Response is nil or the header does not exist.
+func ExtractHeaderValue(header string, resp *http.Response) string {
+ h := ExtractHeader(header, resp)
+ if len(h) > 0 {
+ return h[0]
+ }
+ return ""
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender.go b/vendor/github.com/Azure/go-autorest/autorest/sender.go
new file mode 100644
index 000000000..9c0697815
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/sender.go
@@ -0,0 +1,270 @@
+package autorest
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "math"
+ "net/http"
+ "time"
+)
+
+// Sender is the interface that wraps the Do method to send HTTP requests.
+//
+// The standard http.Client conforms to this interface.
+type Sender interface {
+ Do(*http.Request) (*http.Response, error)
+}
+
+// SenderFunc is a method that implements the Sender interface.
+type SenderFunc func(*http.Request) (*http.Response, error)
+
+// Do implements the Sender interface on SenderFunc.
+func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
+ return sf(r)
+}
+
+// SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the
+// http.Request and pass it along or, first, pass the http.Request along then react to the
+// http.Response result.
+type SendDecorator func(Sender) Sender
+
+// CreateSender creates, decorates, and returns, as a Sender, the default http.Client.
+func CreateSender(decorators ...SendDecorator) Sender {
+ return DecorateSender(&http.Client{}, decorators...)
+}
+
+// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to
+// the Sender. Decorators are applied in the order received, but their affect upon the request
+// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a
+// post-decorator (pass the http.Request along and react to the results in http.Response).
+func DecorateSender(s Sender, decorators ...SendDecorator) Sender {
+ for _, decorate := range decorators {
+ s = decorate(s)
+ }
+ return s
+}
+
+// Send sends, by means of the default http.Client, the passed http.Request, returning the
+// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which
+// it will apply the http.Client before invoking the Do method.
+//
+// Send is a convenience method and not recommended for production. Advanced users should use
+// SendWithSender, passing and sharing their own Sender (e.g., instance of http.Client).
+//
+// Send will not poll or retry requests.
+func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
+ return SendWithSender(&http.Client{}, r, decorators...)
+}
+
+// SendWithSender sends the passed http.Request, through the provided Sender, returning the
+// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which
+// it will apply the http.Client before invoking the Do method.
+//
+// SendWithSender will not poll or retry requests.
+func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*http.Response, error) {
+ return DecorateSender(s, decorators...).Do(r)
+}
+
+// AfterDelay returns a SendDecorator that delays for the passed time.Duration before
+// invoking the Sender. The delay may be terminated by closing the optional channel on the
+// http.Request. If canceled, no further Senders are invoked.
+func AfterDelay(d time.Duration) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (*http.Response, error) {
+ if !DelayForBackoff(d, 0, r.Cancel) {
+ return nil, fmt.Errorf("autorest: AfterDelay canceled before full delay")
+ }
+ return s.Do(r)
+ })
+ }
+}
+
+// AsIs returns a SendDecorator that invokes the passed Sender without modifying the http.Request.
+func AsIs() SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (*http.Response, error) {
+ return s.Do(r)
+ })
+ }
+}
+
+// DoCloseIfError returns a SendDecorator that first invokes the passed Sender after which
+// it closes the response if the passed Sender returns an error and the response body exists.
+func DoCloseIfError() SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (*http.Response, error) {
+ resp, err := s.Do(r)
+ if err != nil {
+ Respond(resp, ByDiscardingBody(), ByClosing())
+ }
+ return resp, err
+ })
+ }
+}
+
+// DoErrorIfStatusCode returns a SendDecorator that emits an error if the response StatusCode is
+// among the set passed. Since these are artificial errors, the response body may still require
+// closing.
+func DoErrorIfStatusCode(codes ...int) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (*http.Response, error) {
+ resp, err := s.Do(r)
+ if err == nil && ResponseHasStatusCode(resp, codes...) {
+ err = NewErrorWithResponse("autorest", "DoErrorIfStatusCode", resp, "%v %v failed with %s",
+ resp.Request.Method,
+ resp.Request.URL,
+ resp.Status)
+ }
+ return resp, err
+ })
+ }
+}
+
+// DoErrorUnlessStatusCode returns a SendDecorator that emits an error unless the response
+// StatusCode is among the set passed. Since these are artificial errors, the response body
+// may still require closing.
+func DoErrorUnlessStatusCode(codes ...int) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (*http.Response, error) {
+ resp, err := s.Do(r)
+ if err == nil && !ResponseHasStatusCode(resp, codes...) {
+ err = NewErrorWithResponse("autorest", "DoErrorUnlessStatusCode", resp, "%v %v failed with %s",
+ resp.Request.Method,
+ resp.Request.URL,
+ resp.Status)
+ }
+ return resp, err
+ })
+ }
+}
+
+// DoPollForStatusCodes returns a SendDecorator that polls if the http.Response contains one of the
+// passed status codes. It expects the http.Response to contain a Location header providing the
+// URL at which to poll (using GET) and will poll until the time passed is equal to or greater than
+// the supplied duration. It will delay between requests for the duration specified in the
+// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by
+// closing the optional channel on the http.Request.
+func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ...int) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
+ resp, err = s.Do(r)
+
+ if err == nil && ResponseHasStatusCode(resp, codes...) {
+ r, err = NewPollingRequest(resp, r.Cancel)
+
+ for err == nil && ResponseHasStatusCode(resp, codes...) {
+ Respond(resp,
+ ByDiscardingBody(),
+ ByClosing())
+ resp, err = SendWithSender(s, r,
+ AfterDelay(GetRetryAfter(resp, delay)))
+ }
+ }
+
+ return resp, err
+ })
+ }
+}
+
+// DoRetryForAttempts returns a SendDecorator that retries a failed request for up to the specified
+// number of attempts, exponentially backing off between requests using the supplied backoff
+// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on
+// the http.Request.
+func DoRetryForAttempts(attempts int, backoff time.Duration) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
+ for attempt := 0; attempt < attempts; attempt++ {
+ resp, err = s.Do(r)
+ if err == nil {
+ return resp, err
+ }
+ DelayForBackoff(backoff, attempt, r.Cancel)
+ }
+ return resp, err
+ })
+ }
+}
+
+// DoRetryForStatusCodes returns a SendDecorator that retries for specified statusCodes for up to the specified
+// number of attempts, exponentially backing off between requests using the supplied backoff
+// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on
+// the http.Request.
+func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
+ b := []byte{}
+ if r.Body != nil {
+ b, err = ioutil.ReadAll(r.Body)
+ if err != nil {
+ return resp, err
+ }
+ }
+
+ // Increment to add the first call (attempts denotes number of retries)
+ attempts++
+ for attempt := 0; attempt < attempts; attempt++ {
+ r.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+ resp, err = s.Do(r)
+ if err != nil || !ResponseHasStatusCode(resp, codes...) {
+ return resp, err
+ }
+ DelayForBackoff(backoff, attempt, r.Cancel)
+ }
+ return resp, err
+ })
+ }
+}
+
+// DoRetryForDuration returns a SendDecorator that retries the request until the total time is equal
+// to or greater than the specified duration, exponentially backing off between requests using the
+// supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the
+// optional channel on the http.Request.
+func DoRetryForDuration(d time.Duration, backoff time.Duration) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (resp *http.Response, err error) {
+ end := time.Now().Add(d)
+ for attempt := 0; time.Now().Before(end); attempt++ {
+ resp, err = s.Do(r)
+ if err == nil {
+ return resp, err
+ }
+ DelayForBackoff(backoff, attempt, r.Cancel)
+ }
+ return resp, err
+ })
+ }
+}
+
+// WithLogging returns a SendDecorator that implements simple before and after logging of the
+// request.
+func WithLogging(logger *log.Logger) SendDecorator {
+ return func(s Sender) Sender {
+ return SenderFunc(func(r *http.Request) (*http.Response, error) {
+ logger.Printf("Sending %s %s", r.Method, r.URL)
+ resp, err := s.Do(r)
+ if err != nil {
+ logger.Printf("%s %s received error '%v'", r.Method, r.URL, err)
+ } else {
+ logger.Printf("%s %s received %s", r.Method, r.URL, resp.Status)
+ }
+ return resp, err
+ })
+ }
+}
+
+// DelayForBackoff invokes time.After for the supplied backoff duration raised to the power of
+// passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set
+// to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early,
+// returns false.
+// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt
+// count.
+func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool {
+ select {
+ case <-time.After(time.Duration(backoff.Seconds()*math.Pow(2, float64(attempt))) * time.Second):
+ return true
+ case <-cancel:
+ return false
+ }
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility.go b/vendor/github.com/Azure/go-autorest/autorest/utility.go
new file mode 100644
index 000000000..78067148b
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/utility.go
@@ -0,0 +1,178 @@
+package autorest
+
+import (
+ "bytes"
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "net/url"
+ "reflect"
+ "sort"
+ "strings"
+)
+
+// EncodedAs is a series of constants specifying various data encodings
+type EncodedAs string
+
+const (
+ // EncodedAsJSON states that data is encoded as JSON
+ EncodedAsJSON EncodedAs = "JSON"
+
+ // EncodedAsXML states that data is encoded as Xml
+ EncodedAsXML EncodedAs = "XML"
+)
+
+// Decoder defines the decoding method json.Decoder and xml.Decoder share
+type Decoder interface {
+ Decode(v interface{}) error
+}
+
+// NewDecoder creates a new decoder appropriate to the passed encoding.
+// encodedAs specifies the type of encoding and r supplies the io.Reader containing the
+// encoded data.
+func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder {
+ if encodedAs == EncodedAsJSON {
+ return json.NewDecoder(r)
+ } else if encodedAs == EncodedAsXML {
+ return xml.NewDecoder(r)
+ }
+ return nil
+}
+
+// CopyAndDecode decodes the data from the passed io.Reader while making a copy. Having a copy
+// is especially useful if there is a chance the data will fail to decode.
+// encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v
+// is the decoding destination.
+func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error) {
+ b := bytes.Buffer{}
+ return b, NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v)
+}
+
+// TeeReadCloser returns a ReadCloser that writes to w what it reads from rc.
+// It utilizes io.TeeReader to copy the data read and has the same behavior when reading.
+// Further, when it is closed, it ensures that rc is closed as well.
+func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser {
+ return &teeReadCloser{rc, io.TeeReader(rc, w)}
+}
+
+type teeReadCloser struct {
+ rc io.ReadCloser
+ r io.Reader
+}
+
+func (t *teeReadCloser) Read(p []byte) (int, error) {
+ return t.r.Read(p)
+}
+
+func (t *teeReadCloser) Close() error {
+ return t.rc.Close()
+}
+
+func containsInt(ints []int, n int) bool {
+ for _, i := range ints {
+ if i == n {
+ return true
+ }
+ }
+ return false
+}
+
+func escapeValueStrings(m map[string]string) map[string]string {
+ for key, value := range m {
+ m[key] = url.QueryEscape(value)
+ }
+ return m
+}
+
+func ensureValueStrings(mapOfInterface map[string]interface{}) map[string]string {
+ mapOfStrings := make(map[string]string)
+ for key, value := range mapOfInterface {
+ mapOfStrings[key] = ensureValueString(value)
+ }
+ return mapOfStrings
+}
+
+func ensureValueString(value interface{}) string {
+ if value == nil {
+ return ""
+ }
+ switch v := value.(type) {
+ case string:
+ return v
+ case []byte:
+ return string(v)
+ default:
+ return fmt.Sprintf("%v", v)
+ }
+}
+
+// MapToValues method converts map[string]interface{} to url.Values.
+func MapToValues(m map[string]interface{}) url.Values {
+ v := url.Values{}
+ for key, value := range m {
+ x := reflect.ValueOf(value)
+ if x.Kind() == reflect.Array || x.Kind() == reflect.Slice {
+ for i := 0; i < x.Len(); i++ {
+ v.Add(key, ensureValueString(x.Index(i)))
+ }
+ } else {
+ v.Add(key, ensureValueString(value))
+ }
+ }
+ return v
+}
+
+// String method converts interface v to string. If interface is a list, it
+// joins list elements using separator.
+func String(v interface{}, sep ...string) string {
+ if len(sep) > 0 {
+ return ensureValueString(strings.Join(v.([]string), sep[0]))
+ }
+ return ensureValueString(v)
+}
+
+// Encode method encodes url path and query parameters.
+func Encode(location string, v interface{}, sep ...string) string {
+ s := String(v, sep...)
+ switch strings.ToLower(location) {
+ case "path":
+ return pathEscape(s)
+ case "query":
+ return queryEscape(s)
+ default:
+ return s
+ }
+}
+
+func pathEscape(s string) string {
+ return strings.Replace(url.QueryEscape(s), "+", "%20", -1)
+}
+
+func queryEscape(s string) string {
+ return url.QueryEscape(s)
+}
+
+// This method is same as Encode() method of "net/url" go package,
+// except it does not encode the query parameters because they
+// already come encoded. It formats values map in query format (bar=foo&a=b).
+func createQuery(v url.Values) string {
+ var buf bytes.Buffer
+ keys := make([]string, 0, len(v))
+ for k := range v {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ vs := v[k]
+ prefix := url.QueryEscape(k) + "="
+ for _, v := range vs {
+ if buf.Len() > 0 {
+ buf.WriteByte('&')
+ }
+ buf.WriteString(prefix)
+ buf.WriteString(v)
+ }
+ }
+ return buf.String()
+}
diff --git a/vendor/github.com/Azure/go-autorest/autorest/version.go b/vendor/github.com/Azure/go-autorest/autorest/version.go
new file mode 100644
index 000000000..7a0bf9c9f
--- /dev/null
+++ b/vendor/github.com/Azure/go-autorest/autorest/version.go
@@ -0,0 +1,23 @@
+package autorest
+
+import (
+ "fmt"
+)
+
+const (
+ major = "7"
+ minor = "3"
+ patch = "0"
+ tag = ""
+ semVerFormat = "%s.%s.%s%s"
+)
+
+var version string
+
+// Version returns the semantic version (see http://semver.org).
+func Version() string {
+ if version == "" {
+ version = fmt.Sprintf(semVerFormat, major, minor, patch, tag)
+ }
+ return version
+}