aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Azure/go-autorest/autorest
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-04-06 18:53:33 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-04-06 18:53:33 +0800
commitc76ad944920300be58446ddd1a50c8d693957774 (patch)
treeec9aed051e82deb3c479ab1b7ab50aa2c07d9efb /vendor/github.com/Azure/go-autorest/autorest
parent3d8de95f999de6f52f0c1605eb2913278f1d87d2 (diff)
downloadgo-tangerine-c76ad944920300be58446ddd1a50c8d693957774.tar
go-tangerine-c76ad944920300be58446ddd1a50c8d693957774.tar.gz
go-tangerine-c76ad944920300be58446ddd1a50c8d693957774.tar.bz2
go-tangerine-c76ad944920300be58446ddd1a50c8d693957774.tar.lz
go-tangerine-c76ad944920300be58446ddd1a50c8d693957774.tar.xz
go-tangerine-c76ad944920300be58446ddd1a50c8d693957774.tar.zst
go-tangerine-c76ad944920300be58446ddd1a50c8d693957774.zip
.travis, build: autodelete old unstable archives (#13867)
This commit adds a build step to travis to auto-delete unstable archives older than 14 days (our regular release schedule) from Azure via ci.go purge. The commit also pulls in the latest Azure storage code, also switching over from the old import path (github.com/Azure/azure-sdk-for-go) to the new split one (github.com/Azure/azure-storage-go).
Diffstat (limited to 'vendor/github.com/Azure/go-autorest/autorest')
-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
19 files changed, 3131 insertions, 0 deletions
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
+}