diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 7be5c88b843b..4ff4639d5dba 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -26,7 +26,7 @@ jobs:
GOPATH: '$(system.defaultWorkingDirectory)/work'
sdkPath: '$(GOPATH)/src/github.com/$(build.repository.name)'
IGNORE_BREAKING_CHANGES: true
- go.list.filter: '| grep -v vendor'
+ go.list.filter: '| grep -v vendor | grep -v azure-sdk-for-go/sdk'
steps:
- task: GoTool@0
@@ -57,7 +57,7 @@ jobs:
- script: go build -v $(go list ./... $(go.list.filter))
workingDirectory: '$(sdkPath)'
displayName: 'Build'
- - script: go test $(dirname $(find . -path ./vendor -prune -o -path ./sdk -prune -o -name '*_test.go' -print) | sort -u)
+ - script: go test $(dirname $(find . -path ./vendor -prune -o -path ./sdk -prune -o -path ./sdk -prune -o -name '*_test.go' -print) | sort -u)
workingDirectory: '$(sdkPath)'
displayName: 'Run Tests'
- script: go run ./tools/apidiff/main.go packages ./services FETCH_HEAD~1 FETCH_HEAD --copyrepo --breakingchanges || $IGNORE_BREAKING_CHANGES
diff --git a/eng/pipelines/templates/steps/build-test.yml b/eng/pipelines/templates/steps/build-test.yml
index f08eed8d6bf4..536460220177 100644
--- a/eng/pipelines/templates/steps/build-test.yml
+++ b/eng/pipelines/templates/steps/build-test.yml
@@ -12,43 +12,78 @@ steps:
go get github.com/axw/gocov/gocov
go get github.com/AlekSi/gocov-xml
go get github.com/matm/gocov-html
+ go get -u github.com/wadey/gocovmerge
displayName: "Install Coverage and Junit Dependencies"
workingDirectory: '${{parameters.GoWorkspace}}'
- pwsh: |
- go vet $(go list $(SCOPE))
- displayName: 'Vet'
+ $modDirs = (./eng/scripts/get_module_dirs.ps1 -serviceDir $(SCOPE))
+ foreach ($md in $modDirs) {
+ pushd $md
+ Write-Host "##[command]Executing go build -v $md"
+ go build -v
+ }
+ displayName: 'Build'
workingDirectory: '${{parameters.GoWorkspace}}'
+ env:
+ GO111MODULE: 'on'
- pwsh: |
- go build -v $(go list $(SCOPE))
- displayName: 'Build'
+ $modDirs = (./eng/scripts/get_module_dirs.ps1 -serviceDir $(SCOPE))
+ foreach ($md in $modDirs) {
+ pushd $md
+ Write-Host "##[command]Executing go vet $md"
+ go vet
+ }
+ displayName: 'Vet'
workingDirectory: '${{parameters.GoWorkspace}}'
+ env:
+ GO111MODULE: 'on'
- pwsh: |
- go test -run "^Test" -race -v -coverprofile coverage.txt -covermode atomic $(SCOPE) | go-junit-report -set-exit-code > $(Build.SourcesDirectory)/report.xml
+ $testDirs = (./eng/scripts/get_test_dirs.ps1 -serviceDir $(SCOPE))
+ foreach ($td in $testDirs) {
+ pushd $td
+ Write-Host "##[command]Executing go test -run "^Test" -race -v -coverprofile coverage.txt -covermode atomic $td | go-junit-report -set-exit-code > report.xml"
+ go test -run "^Test" -race -v -coverprofile coverage.txt -covermode atomic . | go-junit-report -set-exit-code > report.xml
+ # if no tests were actually run (e.g. examples) delete the coverage file so it's omitted from the coverage report
+ if (Select-String -path ./report.xml -pattern '' -simplematch -quiet) {
+ Write-Host "##[command]Deleting empty coverage file"
+ rm coverage.txt
+ }
+ }
displayName: 'Run Tests'
workingDirectory: '${{parameters.GoWorkspace}}'
+ env:
+ GO111MODULE: 'on'
- pwsh: |
- gocov convert ./coverage.txt > ./coverage.json
-
+ $coverageFiles = [Collections.Generic.List[String]]@()
+ Get-Childitem -recurse -path $(SCOPE) -filter coverage.txt | foreach-object {
+ $covFile = $_.FullName
+ Write-Host "Adding $covFile to the list of code coverage files"
+ $coverageFiles.Add($covFile)
+ }
+ gocovmerge $coverageFiles > mergedCoverage.txt
+ gocov convert ./mergedCoverage.txt > ./coverage.json
# gocov converts rely on standard input
- Get-Content ./coverage.json | gocov-xml > $(Build.SourcesDirectory)/coverage.xml
- Get-Content ./coverage.json | gocov-html > $(Build.SourcesDirectory)/coverage.html
+ Get-Content ./coverage.json | gocov-xml > ./coverage.xml
+ Get-Content ./coverage.json | gocov-html > ./coverage.html
displayName: 'Generate Coverage XML'
- workingDirectory: '${{parameters.GoWorkspace}}'
+ workingDirectory: '${{parameters.GoWorkspace}}sdk'
- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testRunner: JUnit
- testResultsFiles: '$(Build.SourcesDirectory)/report.xml'
+ testResultsFiles: '${{parameters.GoWorkspace}}sdk/**/report.xml'
testRunTitle: 'Go ${{ parameters.GoVersion }} on ${{ parameters.Image }}'
+ failTaskOnFailedTests: true
- task: PublishCodeCoverageResults@1
condition: succeededOrFailed()
inputs:
codeCoverageTool: Cobertura
- summaryFileLocation: '$(Build.SourcesDirectory)/coverage.xml'
- additionalCodeCoverageFiles: '$(Build.SourcesDirectory)/coverage.html'
+ summaryFileLocation: '${{parameters.GoWorkspace}}sdk/coverage.xml'
+ additionalCodeCoverageFiles: '${{parameters.GoWorkspace}}sdk/coverage.html'
+ failIfCoverageEmpty: true
diff --git a/eng/pipelines/templates/steps/set-scope.yml b/eng/pipelines/templates/steps/set-scope.yml
index 09d3c71fc9e9..02d355fa69cd 100644
--- a/eng/pipelines/templates/steps/set-scope.yml
+++ b/eng/pipelines/templates/steps/set-scope.yml
@@ -8,7 +8,7 @@ steps:
$serviceDir = "${{parameters.ServiceDirectory}}"
$scope = (./eng/scripts/scoped_discover.ps1 -serviceDir "$serviceDir")
- Write-Host
+ Write-Host $scope
Write-Host "##vso[task.setvariable variable=SCOPE]$scope"
displayName: 'Set Target Scope'
workingDirectory: "${{ parameters.GoWorkspace }}"
diff --git a/eng/scripts/get_module_dirs.ps1 b/eng/scripts/get_module_dirs.ps1
new file mode 100644
index 000000000000..5404ea45a7a7
--- /dev/null
+++ b/eng/scripts/get_module_dirs.ps1
@@ -0,0 +1,15 @@
+Param(
+ [string] $serviceDir
+)
+
+$modDirs = [Collections.Generic.List[String]]@()
+
+# find each module directory under $serviceDir
+Get-Childitem -recurse -path $serviceDir -filter go.mod | foreach-object {
+ $cdir = $_.Directory
+ Write-Host "Adding $cdir to list of module paths"
+ $modDirs.Add($cdir)
+}
+
+# return the list of module directories
+return $modDirs
diff --git a/eng/scripts/get_test_dirs.ps1 b/eng/scripts/get_test_dirs.ps1
new file mode 100644
index 000000000000..07a46f047c8b
--- /dev/null
+++ b/eng/scripts/get_test_dirs.ps1
@@ -0,0 +1,17 @@
+Param(
+ [string] $serviceDir
+)
+
+$testDirs = [Collections.Generic.List[String]]@()
+
+# find each directory under $serviceDir that contains Go test files
+Get-Childitem -recurse -path $serviceDir -filter *_test.go | foreach-object {
+ $cdir = $_.Directory
+ if (!$testDirs.Contains($cdir)) {
+ Write-Host "Adding $cdir to list of test directories"
+ $testDirs.Add($cdir)
+ }
+}
+
+# return the list of test directories
+return $testDirs
diff --git a/eng/scripts/scoped_discover.ps1 b/eng/scripts/scoped_discover.ps1
index 11bccc1a031f..88168575ae7d 100644
--- a/eng/scripts/scoped_discover.ps1
+++ b/eng/scripts/scoped_discover.ps1
@@ -11,4 +11,4 @@ else {
$path = Resolve-Path -Path $targetDir
-return "$path/..."
+return $path
diff --git a/sdk/azcore/core.go b/sdk/azcore/core.go
deleted file mode 100644
index 364a3bf9f108..000000000000
--- a/sdk/azcore/core.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "io"
- "net/http"
-)
-
-// Policy represents an extensibility point for the Pipeline that can mutate the specified
-// Request and react to the received Response.
-type Policy interface {
- // Do applies the policy to the specified Request. When implementing a Policy, mutate the
- // request before calling req.Do() to move on to the next policy, and respond to the result
- // before returning to the caller.
- Do(ctx context.Context, req *Request) (*Response, error)
-}
-
-// PolicyFunc is a type that implements the Policy interface.
-// Use this type when implementing a stateless policy as a first-class function.
-type PolicyFunc func(context.Context, *Request) (*Response, error)
-
-// Do implements the Policy interface on PolicyFunc.
-func (pf PolicyFunc) Do(ctx context.Context, req *Request) (*Response, error) {
- return pf(ctx, req)
-}
-
-// Transport represents an HTTP pipeline transport used to send HTTP requests and receive responses.
-type Transport interface {
- // Do sends the HTTP request and returns the HTTP response or error.
- Do(ctx context.Context, req *http.Request) (*http.Response, error)
-}
-
-// TransportFunc is a type that implements the Transport interface.
-// Use this type when implementing a stateless transport as a first-class function.
-type TransportFunc func(context.Context, *http.Request) (*http.Response, error)
-
-// Do implements the Transport interface on TransportFunc.
-func (tf TransportFunc) Do(ctx context.Context, req *http.Request) (*http.Response, error) {
- return tf(ctx, req)
-}
-
-// used to adapt a TransportPolicy to a Policy
-type transportPolicy struct {
- trans Transport
-}
-
-func (tp transportPolicy) Do(ctx context.Context, req *Request) (*Response, error) {
- resp, err := tp.trans.Do(ctx, req.Request)
- if err != nil {
- return nil, err
- }
- return &Response{Response: resp}, nil
-}
-
-// Pipeline represents a primitive for sending HTTP requests and receiving responses.
-// Its behavior can be extended by specifying policies during construction.
-type Pipeline struct {
- policies []Policy
-}
-
-// NewPipeline creates a new goroutine-safe Pipeline object from the specified Policies.
-// If no transport is provided then the default HTTP transport will be used.
-func NewPipeline(transport Transport, policies ...Policy) Pipeline {
- if transport == nil {
- transport = DefaultHTTPClientTransport()
- }
- // transport policy must always be the last in the slice
- policies = append(policies, newBodyDownloadPolicy(), transportPolicy{trans: transport})
- return Pipeline{
- policies: policies,
- }
-}
-
-// Do is called for each and every HTTP request. It passes the Context and request through
-// all the Policy objects (which can transform the Request's URL/query parameters/headers)
-// and ultimately sends the transformed HTTP request over the network.
-func (p Pipeline) Do(ctx context.Context, req *Request) (*Response, error) {
- req.policies = p.policies
- return req.Next(ctx)
-}
-
-// ReadSeekCloser is the interface that groups the io.ReadCloser and io.Seeker interfaces.
-type ReadSeekCloser interface {
- io.ReadCloser
- io.Seeker
-}
-
-type nopCloser struct {
- io.ReadSeeker
-}
-
-func (n nopCloser) Close() error {
- return nil
-}
-
-// NopCloser returns a ReadSeekCloser with a no-op close method wrapping the provided io.ReadSeeker.
-func NopCloser(rs io.ReadSeeker) ReadSeekCloser {
- return nopCloser{rs}
-}
-
-// Retrier provides methods describing if an error should be considered as transient.
-type Retrier interface {
- // IsNotRetriable returns true for error types that are not retriable.
- IsNotRetriable() bool
-}
diff --git a/sdk/azcore/credential.go b/sdk/azcore/credential.go
deleted file mode 100644
index 997872203925..000000000000
--- a/sdk/azcore/credential.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "time"
-)
-
-// AuthenticationPolicyOptions contains various options used to create a credential policy.
-type AuthenticationPolicyOptions struct {
- // Options contains the TokenRequestOptions that includes a scopes field which contains
- // the list of OAuth2 authentication scopes used when requesting a token.
- // This field is ignored for other forms of authentication (e.g. shared key).
- Options TokenRequestOptions
-}
-
-// Credential represents any credential type.
-type Credential interface {
- // AuthenticationPolicy returns a policy that requests the credential and applies it to the HTTP request.
- AuthenticationPolicy(options AuthenticationPolicyOptions) Policy
-}
-
-// credentialFunc is a type that implements the Credential interface.
-// Use this type when implementing a stateless credential as a first-class function.
-type credentialFunc func(options AuthenticationPolicyOptions) Policy
-
-// AuthenticationPolicy implements the Credential interface on credentialFunc.
-func (cf credentialFunc) AuthenticationPolicy(options AuthenticationPolicyOptions) Policy {
- return cf(options)
-}
-
-// TokenCredential represents a credential capable of providing an OAuth token.
-type TokenCredential interface {
- Credential
- // GetToken requests an access token for the specified set of scopes.
- GetToken(ctx context.Context, options TokenRequestOptions) (*AccessToken, error)
-}
-
-// AccessToken represents an Azure service bearer access token with expiry information.
-type AccessToken struct {
- Token string
- ExpiresOn time.Time
-}
-
-// TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token
-type TokenRequestOptions struct {
- Scopes []string
-}
diff --git a/sdk/azcore/doc.go b/sdk/azcore/doc.go
deleted file mode 100644
index 6546445bc796..000000000000
--- a/sdk/azcore/doc.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// +build go1.13
-
-// Copyright 2017 Microsoft Corporation. All rights reserved.
-// Use of this source code is governed by an MIT
-// license that can be found in the LICENSE file.
-
-/*
-Package azcore implements an HTTP request/response middleware pipeline whose
-policy objects mutate an HTTP request's URL, query parameters, and/or headers before
-the request is sent over the wire.
-
-Not all policy objects mutate an HTTP request; some policy objects simply impact the
-flow of requests/responses by performing operations such as logging, retry policies,
-timeouts, failure injection, and deserialization of response payloads.
-
-Implementing the Policy Interface
-
-To implement a policy, define a struct that implements the pipeline.Policy interface's Do method. Your Do
-method is called when an HTTP request wants to be sent over the network. Your Do method can perform any
-operation(s) it desires. For example, it can log the outgoing request, mutate the URL, headers, and/or query
-parameters, inject a failure, etc. Your Do method must then forward the HTTP request to next Policy object
-in a linked-list ensuring that the remaining Policy objects perform their work. Ultimately, the last Policy
-object sends the HTTP request over the network (by calling the HTTPSender's Do method).
-
-When an HTTP response comes back, each Policy object in the linked-list gets a chance to process the response
-(in reverse order). The Policy object can log the response, retry the operation if due to a transient failure
-or timeout, deserialize the response body, etc. Ultimately, the last Policy object returns the HTTP response
-to the code that initiated the original HTTP request.
-
-Here is a template for how to define a pipeline.Policy object:
-
- type myPolicy struct {
- node PolicyNode
- // TODO: Add configuration/setting fields here (if desired)...
- }
-
- func (p *myPolicy) Do(ctx context.Context, request pipeline.Request) (pipeline.Response, error) {
- // TODO: Mutate/process the HTTP request here...
- response, err := p.node.Do(ctx, request) // Forward HTTP request to next Policy & get HTTP response
- // TODO: Mutate/process the HTTP response here...
- return response, err // Return response/error to previous Policy
- }
-
-Implementing the Factory Interface
-
-Each Policy struct definition requires a factory struct definition that implements the pipeline.Factory interface's New
-method. The New method is called when application code wants to initiate a new HTTP request. Factory's New method is
-passed a pipeline.PolicyNode object which contains a reference to the owning pipeline.Pipeline object (discussed later) and
-a reference to the next Policy object in the linked list. The New method should create its corresponding Policy object
-passing it the PolicyNode and any other configuration/settings fields appropriate for the specific Policy object.
-
-Here is a template for how to define a pipeline.Policy object:
-
- // NOTE: Once created & initialized, Factory objects should be goroutine-safe (ex: immutable);
- // this allows reuse (efficient use of memory) and makes these objects usable by multiple goroutines concurrently.
- type myPolicyFactory struct {
- // TODO: Add any configuration/setting fields if desired...
- }
-
- func (f *myPolicyFactory) New(node pipeline.PolicyNode) Policy {
- return &myPolicy{node: node} // TODO: Also initialize any configuration/setting fields here (if desired)...
- }
-
-Using your Factory and Policy objects via a Pipeline
-
-To use the Factory and Policy objects, an application constructs a slice of Factory objects and passes
-this slice to the pipeline.NewPipeline function.
-
- func NewPipeline(factories []pipeline.Factory, sender pipeline.HTTPSender) Pipeline
-
-This function also requires an object implementing the HTTPSender interface. For simple scenarios,
-passing nil for HTTPSender causes a standard Go http.Client object to be created and used to actually
-send the HTTP response over the network. For more advanced scenarios, you can pass your own HTTPSender
-object in. This allows sharing of http.Client objects or the use of custom-configured http.Client objects
-or other objects that can simulate the network requests for testing purposes.
-
-Now that you have a pipeline.Pipeline object, you can create a pipeline.Request object (which is a simple
-wrapper around Go's standard http.Request object) and pass it to Pipeline's Do method along with passing a
-context.Context for cancelling the HTTP request (if desired).
-
- type Pipeline interface {
- Do(ctx context.Context, methodFactory pipeline.Factory, request pipeline.Request) (pipeline.Response, error)
- }
-
-Do iterates over the slice of Factory objects and tells each one to create its corresponding
-Policy object. After the linked-list of Policy objects have been created, Do calls the first
-Policy object passing it the Context & HTTP request parameters. These parameters now flow through
-all the Policy objects giving each object a chance to look at and/or mutate the HTTP request.
-The last Policy object sends the message over the network.
-
-When the network operation completes, the HTTP response and error return values pass
-back through the same Policy objects in reverse order. Most Policy objects ignore the
-response/error but some log the result, retry the operation (depending on the exact
-reason the operation failed), or deserialize the response's body. Your own Policy
-objects can do whatever they like when processing outgoing requests or incoming responses.
-
-Note that after an I/O request runs to completion, the Policy objects for that request
-are garbage collected. However, Pipeline object (like Factory objects) are goroutine-safe allowing
-them to be created once and reused over many I/O operations. This allows for efficient use of
-memory and also makes them safely usable by multiple goroutines concurrently.
-
-Inserting a Method-Specific Factory into the Linked-List of Policy Objects
-
-While Pipeline and Factory objects can be reused over many different operations, it is
-common to have special behavior for a specific operation/method. For example, a method
-may need to deserialize the response's body to an instance of a specific data type.
-To accommodate this, the Pipeline's Do method takes an additional method-specific
-Factory object. The Do method tells this Factory to create a Policy object and
-injects this method-specific Policy object into the linked-list of Policy objects.
-
-When creating a Pipeline object, the slice of Factory objects passed must have 1
-(and only 1) entry marking where the method-specific Factory should be injected.
-The Factory marker is obtained by calling the pipeline.MethodFactoryMarker() function:
-
- func MethodFactoryMarker() pipeline.Factory
-
-Creating an HTTP Request Object
-
-The HTTP request object passed to Pipeline's Do method is not Go's http.Request struct.
-Instead, it is a pipeline.Request struct which is a simple wrapper around Go's standard
-http.Request. You create a pipeline.Request object by calling the pipeline.NewRequest function:
-
- func NewRequest(method string, url url.URL, options pipeline.RequestOptions) (request pipeline.Request, err error)
-
-To this function, you must pass a pipeline.RequestOptions that looks like this:
-
- type RequestOptions struct {
- // The readable and seekable stream to be sent to the server as the request's body.
- Body io.ReadSeeker
-
- // The callback method (if not nil) to be invoked to report progress as the stream is uploaded in the HTTP request.
- Progress ProgressReceiver
- }
-
-The method and struct ensure that the request's body stream is a read/seekable stream.
-A seekable stream is required so that upon retry, the final Policy object can seek
-the stream back to the beginning before retrying the network request and re-uploading the
-body. In addition, you can associate a ProgressReceiver callback function which will be
-invoked periodically to report progress while bytes are being read from the body stream
-and sent over the network.
-
-Processing the HTTP Response
-
-When an HTTP response comes in from the network, a reference to Go's http.Response struct is
-embedded in a struct that implements the pipeline.Response interface:
-
- type Response interface {
- Response() *http.Response
- }
-
-This interface is returned through all the Policy objects. Each Policy object can call the Response
-interface's Response method to examine (or mutate) the embedded http.Response object.
-
-A Policy object can internally define another struct (implementing the pipeline.Response interface)
-that embeds an http.Response and adds additional fields and return this structure to other Policy
-objects. This allows a Policy object to deserialize the body to some other struct and return the
-original http.Response and the additional struct back through the Policy chain. Other Policy objects
-can see the Response but cannot see the additional struct with the deserialized body. After all the
-Policy objects have returned, the pipeline.Response interface is returned by Pipeline's Do method.
-The caller of this method can perform a type assertion attempting to get back to the struct type
-really returned by the Policy object. If the type assertion is successful, the caller now has
-access to both the http.Response and the deserialized struct object.
-*/
-package azcore
diff --git a/sdk/azcore/error.go b/sdk/azcore/error.go
deleted file mode 100644
index 93d6957e206f..000000000000
--- a/sdk/azcore/error.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "errors"
- "fmt"
-)
-
-var (
- // ErrNoMorePolicies is returned from Request.Next() if there are no more policies in the pipeline.
- ErrNoMorePolicies = errors.New("no more policies")
-)
-
-// TODO: capture frame info for marshal, unmarshal, and parsing errors
-// built in frame in xerror? %w
-type frameInfo struct {
- file string
- line int
-}
-
-func (f frameInfo) String() string {
- if f.zero() {
- return ""
- }
- return fmt.Sprintf("file: %s, line: %d", f.file, f.line)
-}
-
-func (f frameInfo) zero() bool {
- return f.file == "" && f.line == 0
-}
-
-// RequestError is returned when the service returns an unsuccessful resopnse code (4xx, 5xx).
-type RequestError struct {
- msg string
- resp *Response
-}
-
-func newRequestError(message string, response *Response) error {
- return RequestError{msg: message, resp: response}
-}
-
-func (re RequestError) Error() string {
- return re.msg
-}
-
-// Response returns the underlying response.
-func (re RequestError) Response() *Response {
- return re.resp
-}
diff --git a/sdk/azcore/go.mod b/sdk/azcore/go.mod
deleted file mode 100644
index 637312064cb5..000000000000
--- a/sdk/azcore/go.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-module github.com/Azure/azure-sdk-for-go/sdk/azcore
-
-require github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0
-
-go 1.13
diff --git a/sdk/azcore/go.sum b/sdk/azcore/go.sum
deleted file mode 100644
index 6306f1577dcd..000000000000
--- a/sdk/azcore/go.sum
+++ /dev/null
@@ -1,2 +0,0 @@
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws=
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY=
diff --git a/sdk/azcore/headers.go b/sdk/azcore/headers.go
deleted file mode 100644
index 2b8ea562e2d5..000000000000
--- a/sdk/azcore/headers.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-// Constants ensuring that header names are correctly spelled and consistently cased.
-const (
- HeaderAuthorization = "Authorization"
- HeaderCacheControl = "Cache-Control"
- HeaderContentEncoding = "Content-Encoding"
- HeaderContentDisposition = "Content-Disposition"
- HeaderContentLanguage = "Content-Language"
- HeaderContentLength = "Content-Length"
- HeaderContentMD5 = "Content-MD5"
- HeaderContentType = "Content-Type"
- HeaderDate = "Date"
- HeaderIfMatch = "If-Match"
- HeaderIfModifiedSince = "If-Modified-Since"
- HeaderIfNoneMatch = "If-None-Match"
- HeaderIfUnmodifiedSince = "If-Unmodified-Since"
- HeaderMetadata = "Metadata"
- HeaderRange = "Range"
- HeaderRetryAfter = "Retry-After"
- HeaderURLEncoded = "application/x-www-form-urlencoded"
- HeaderUserAgent = "User-Agent"
- HeaderXmsDate = "x-ms-date"
- HeaderXmsVersion = "x-ms-version"
-)
diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go
deleted file mode 100644
index 1fe1517b4b65..000000000000
--- a/sdk/azcore/log.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-// LogClassification is used to group entries. Each group can be toggled on or off.
-type LogClassification string
-
-const (
- // LogError entries contain detailed error information.
- // This includes the error message and stack trace.
- LogError LogClassification = "Error"
-
- // LogRequest entries contain information about HTTP requests.
- // This includes information like the URL, query parameters, and headers.
- LogRequest LogClassification = "Request"
-
- // LogResponse entries contain information about HTTP responses.
- // This includes information like the HTTP status code, headers, and request URL.
- LogResponse LogClassification = "Response"
-
- // LogRetryPolicy entries contain information specific to the retry policy in use.
- LogRetryPolicy LogClassification = "RetryPolicy"
-
- // LogSlowResponse entries contain information for responses that take longer than the specified threshold.
- LogSlowResponse LogClassification = "SlowResponse"
-)
-
-// Listener is the function signature invoked when writing log entries.
-// A Listener is required to perform its own synchronization if it's
-// expected to be called from multiple Go routines.
-type Listener func(LogClassification, string)
-
-// Logger controls which classifications to log and writing to the underlying log.
-type Logger struct {
- cls []LogClassification
- lst Listener
-}
-
-// SetClassifications is used to control which classifications are written to
-// the log. By default all log classifications are written.
-func (l *Logger) SetClassifications(cls ...LogClassification) {
- l.cls = cls
-}
-
-// SetListener will set the Logger to write to the specified Listener.
-func (l *Logger) SetListener(lst Listener) {
- l.lst = lst
-}
-
-// Should returns true if the specified log classification should be written to the log.
-// By default all log classifications will be logged. Call SetClassification() to limit
-// the log classifications for logging.
-// If no listener has been set this will return false.
-// Calling this method is useful when the message to log is computationally expensive
-// and you want to avoid the overhead if its log classification is not enabled.
-func (l *Logger) Should(cls LogClassification) bool {
- if l.lst == nil {
- return false
- }
- if l.cls == nil || len(l.cls) == 0 {
- return true
- }
- for _, c := range l.cls {
- if c == cls {
- return true
- }
- }
- return false
-}
-
-// Write invokes the underlying Listener with the specified classification and message.
-// If the classification shouldn't be logged or there is no listener then Write does nothing.
-func (l *Logger) Write(cls LogClassification, message string) {
- if l.lst == nil || !l.Should(cls) {
- return
- }
- l.lst(cls, message)
-}
-
-// for testing purposes
-func (l *Logger) resetClassifications() {
- l.cls = nil
-}
-
-var log Logger
-
-// Log returns the process-wide logger.
-func Log() *Logger {
- return &log
-}
diff --git a/sdk/azcore/log_test.go b/sdk/azcore/log_test.go
deleted file mode 100644
index f9eadbe2c5f8..000000000000
--- a/sdk/azcore/log_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import "testing"
-
-func TestLoggingDefault(t *testing.T) {
- // ensure logging with nil listener doesn't fail
- Log().SetListener(nil)
- Log().Write(LogError, "this should work just fine")
-
- log := map[LogClassification]string{}
- Log().SetListener(func(cls LogClassification, msg string) {
- log[cls] = msg
- })
- const req = "this is a request"
- Log().Write(LogRequest, req)
- const resp = "this is a response"
- Log().Write(LogResponse, resp)
- if l := len(log); l != 2 {
- t.Fatalf("unexpected log entry count: %d", l)
- }
- if log[LogRequest] != req {
- t.Fatalf("unexpected log request: %s", log[LogRequest])
- }
- if log[LogResponse] != resp {
- t.Fatalf("unexpected log response: %s", log[LogResponse])
- }
-}
-
-func TestLoggingClassification(t *testing.T) {
- log := map[LogClassification]string{}
- Log().SetListener(func(cls LogClassification, msg string) {
- log[cls] = msg
- })
- Log().SetClassifications(LogError)
- defer Log().resetClassifications()
- Log().Write(LogSlowResponse, "this shouldn't be in the log")
- if s, ok := log[LogSlowResponse]; ok {
- t.Fatalf("unexpected log entry %s", s)
- }
- const err = "this is an error"
- Log().Write(LogError, err)
- if log[LogError] != err {
- t.Fatalf("unexpected log entry: %s", log[LogError])
- }
-}
diff --git a/sdk/azcore/policy_anonymous_credential.go b/sdk/azcore/policy_anonymous_credential.go
deleted file mode 100644
index 6d5977ccd9f6..000000000000
--- a/sdk/azcore/policy_anonymous_credential.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import "context"
-
-// AnonymousCredential is for use with HTTP(S) requests that read public resource
-// or for use with Shared Access Signatures (SAS).
-func AnonymousCredential() Credential {
- return credentialFunc(func(AuthenticationPolicyOptions) Policy {
- return PolicyFunc(func(ctx context.Context, req *Request) (*Response, error) {
- return req.Next(ctx)
- })
- })
-}
diff --git a/sdk/azcore/policy_anonymous_credential_test.go b/sdk/azcore/policy_anonymous_credential_test.go
deleted file mode 100644
index d860a843f704..000000000000
--- a/sdk/azcore/policy_anonymous_credential_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "net/http"
- "reflect"
- "testing"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestAnonymousCredential(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithStatusCode(http.StatusOK))
- pl := NewPipeline(srv, AnonymousCredential().AuthenticationPolicy(AuthenticationPolicyOptions{}))
- req := NewRequest(http.MethodGet, srv.URL())
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !reflect.DeepEqual(req.Header, resp.Request.Header) {
- t.Fatal("unexpected modification to request headers")
- }
-}
diff --git a/sdk/azcore/policy_body_download.go b/sdk/azcore/policy_body_download.go
deleted file mode 100644
index 22f5a1b9b415..000000000000
--- a/sdk/azcore/policy_body_download.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "fmt"
- "io"
- "io/ioutil"
-)
-
-// newBodyDownloadPolicy creates a policy object that downloads the response's body to a []byte.
-func newBodyDownloadPolicy() Policy {
- return PolicyFunc(func(ctx context.Context, req *Request) (*Response, error) {
- resp, err := req.Next(ctx)
- if err != nil {
- return resp, err
- }
- var opValues bodyDownloadPolicyOpValues
- if req.OperationValue(&opValues); !opValues.skip && resp.Body != nil {
- // Either bodyDownloadPolicyOpValues was not specified (so skip is false)
- // or it was specified and skip is false: don't skip downloading the body
- b, err := ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- if err != nil {
- err = fmt.Errorf("body download policy: %w", err)
- }
- resp.Body = &nopClosingBytesReader{s: b}
- }
- return resp, err
- })
-}
-
-// bodyDownloadPolicyOpValues is the struct containing the per-operation values
-type bodyDownloadPolicyOpValues struct {
- skip bool
-}
-
-// nopClosingBytesReader is an io.ReadCloser around a byte slice.
-// It also provides direct access to the byte slice.
-type nopClosingBytesReader struct {
- s []byte
- i int64
-}
-
-// Bytes returns the underlying byte slice.
-func (r *nopClosingBytesReader) Bytes() []byte {
- return r.s
-}
-
-// Close implements the io.Closer interface.
-func (*nopClosingBytesReader) Close() error {
- return nil
-}
-
-// Read implements the io.Reader interface.
-func (r *nopClosingBytesReader) Read(b []byte) (n int, err error) {
- if r.i >= int64(len(r.s)) {
- return 0, io.EOF
- }
- n = copy(b, r.s[r.i:])
- r.i += int64(n)
- return
-}
-
-// Set replaces the existing byte slice with the specified byte slice and resets the reader.
-func (r *nopClosingBytesReader) Set(b []byte) {
- r.s = b
- r.i = 0
-}
diff --git a/sdk/azcore/policy_body_download_test.go b/sdk/azcore/policy_body_download_test.go
deleted file mode 100644
index a46f4dcfd502..000000000000
--- a/sdk/azcore/policy_body_download_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "net/http"
- "testing"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestDownloadBody(t *testing.T) {
- const message = "downloaded"
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte(message)))
- // download policy is automatically added during pipeline construction
- pl := NewPipeline(srv)
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(resp.payload()) == 0 {
- t.Fatal("missing payload")
- }
- if string(resp.payload()) != message {
- t.Fatalf("unexpected response: %s", string(resp.payload()))
- }
-}
-
-func TestSkipBodyDownload(t *testing.T) {
- const message = "not downloaded"
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte(message)))
- // download policy is automatically added during pipeline construction
- pl := NewPipeline(srv)
- req := NewRequest(http.MethodGet, srv.URL())
- req.SkipBodyDownload()
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if len(resp.payload()) > 0 {
- t.Fatalf("unexpected download: %s", string(resp.payload()))
- }
-}
diff --git a/sdk/azcore/policy_logging.go b/sdk/azcore/policy_logging.go
deleted file mode 100644
index 5900e64f9c04..000000000000
--- a/sdk/azcore/policy_logging.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "bytes"
- "context"
- "fmt"
- "net/http"
- "net/url"
- "runtime"
- "strings"
- "time"
-)
-
-// RequestLogOptions configures the retry policy's behavior.
-type RequestLogOptions struct {
- // LogWarningIfTryOverThreshold logs a warning if a tried operation takes longer than the specified
- // duration (-1=no logging; 0=default threshold).
- LogWarningIfTryOverThreshold time.Duration
-}
-
-func (o RequestLogOptions) defaults() RequestLogOptions {
- if o.LogWarningIfTryOverThreshold == 0 {
- // It would be good to relate this to https://azure.microsoft.com/en-us/support/legal/sla/storage/v1_2/
- // But this monitors the time to get the HTTP response; NOT the time to download the response body.
- o.LogWarningIfTryOverThreshold = 3 * time.Second // Default to 3 seconds
- }
- return o
-}
-
-type requestLogPolicy struct {
- options RequestLogOptions
-}
-
-// NewRequestLogPolicy creates a RequestLogPolicy object configured using the specified options.
-func NewRequestLogPolicy(o RequestLogOptions) Policy {
- o = o.defaults() // Force defaults to be calculated
- return &requestLogPolicy{options: o}
-}
-
-// logPolicyOpValues is the struct containing the per-operation values
-type logPolicyOpValues struct {
- try int32
- start time.Time
-}
-
-func (p *requestLogPolicy) Do(ctx context.Context, req *Request) (*Response, error) {
- // Get the per-operation values. These are saved in the Message's map so that they persist across each retry calling into this policy object.
- var opValues logPolicyOpValues
- if req.OperationValue(&opValues); opValues.start.IsZero() {
- opValues.start = time.Now() // If this is the 1st try, record this operation's start time
- }
- opValues.try++ // The first try is #1 (not #0)
- req.SetOperationValue(opValues)
-
- // Log the outgoing request as informational
- if Log().Should(LogRequest) {
- b := &bytes.Buffer{}
- fmt.Fprintf(b, "==> OUTGOING REQUEST (Try=%d)\n", opValues.try)
- WriteRequestWithResponse(b, prepareRequestForLogging(req), nil, nil)
- Log().Write(LogRequest, b.String())
- }
-
- // Set the time for this particular retry operation and then Do the operation.
- tryStart := time.Now()
- response, err := req.Next(ctx) // Make the request
- tryEnd := time.Now()
- tryDuration := tryEnd.Sub(tryStart)
- opDuration := tryEnd.Sub(opValues.start)
-
- logClass := LogResponse // Default logging information
-
- // If the response took too long, we'll upgrade to warning.
- if p.options.LogWarningIfTryOverThreshold > 0 && tryDuration > p.options.LogWarningIfTryOverThreshold {
- // Log a warning if the try duration exceeded the specified threshold
- logClass = LogSlowResponse
- }
-
- if err == nil { // We got a response from the service
- sc := response.StatusCode
- if ((sc >= 400 && sc <= 499) && sc != http.StatusNotFound && sc != http.StatusConflict && sc != http.StatusPreconditionFailed && sc != http.StatusRequestedRangeNotSatisfiable) || (sc >= 500 && sc <= 599) {
- logClass = LogError // Promote to Error any 4xx (except those listed is an error) or any 5xx
- } else {
- // For other status codes, we leave the level as is.
- }
- } else { // This error did not get an HTTP response from the service; upgrade the severity to Error
- logClass = LogError
- }
-
- if Log().Should(logClass) {
- // We're going to log this; build the string to log
- b := &bytes.Buffer{}
- slow := ""
- if p.options.LogWarningIfTryOverThreshold > 0 && tryDuration > p.options.LogWarningIfTryOverThreshold {
- slow = fmt.Sprintf("[SLOW >%v]", p.options.LogWarningIfTryOverThreshold)
- }
- fmt.Fprintf(b, "==> REQUEST/RESPONSE (Try=%d/%v%s, OpTime=%v) -- ", opValues.try, tryDuration, slow, opDuration)
- if err != nil { // This HTTP request did not get a response from the service
- fmt.Fprint(b, "REQUEST ERROR\n")
- } else {
- if logClass == LogError {
- fmt.Fprint(b, "RESPONSE STATUS CODE ERROR\n")
- } else {
- fmt.Fprint(b, "RESPONSE SUCCESSFULLY RECEIVED\n")
- }
- }
-
- WriteRequestWithResponse(b, prepareRequestForLogging(req), response, err)
- if logClass == LogError {
- b.Write(stack()) // For errors (or lower levels), we append the stack trace (an expensive operation)
- }
- Log().Write(logClass, b.String())
- }
- return response, err
-}
-
-// RedactSigQueryParam redacts the 'sig' query parameter in URL's raw query to protect secret.
-func RedactSigQueryParam(rawQuery string) (bool, string) {
- rawQuery = strings.ToLower(rawQuery) // lowercase the string so we can look for ?sig= and &sig=
- sigFound := strings.Contains(rawQuery, "?sig=")
- if !sigFound {
- sigFound = strings.Contains(rawQuery, "&sig=")
- if !sigFound {
- return sigFound, rawQuery // [?|&]sig= not found; return same rawQuery passed in (no memory allocation)
- }
- }
- // [?|&]sig= found, redact its value
- values, _ := url.ParseQuery(rawQuery)
- for name := range values {
- if strings.EqualFold(name, "sig") {
- values[name] = []string{"REDACTED"}
- }
- }
- return sigFound, values.Encode()
-}
-
-func prepareRequestForLogging(req *Request) *Request {
- request := req
- if sigFound, rawQuery := RedactSigQueryParam(request.URL.RawQuery); sigFound {
- // Make copy so we don't destroy the query parameters we actually need to send in the request
- request = req.copy()
- request.URL.RawQuery = rawQuery
- }
- return request
-}
-
-func stack() []byte {
- buf := make([]byte, 1024)
- for {
- n := runtime.Stack(buf, false)
- if n < len(buf) {
- return buf[:n]
- }
- buf = make([]byte, 2*len(buf))
- }
-}
diff --git a/sdk/azcore/policy_logging_test.go b/sdk/azcore/policy_logging_test.go
deleted file mode 100644
index 7afc73d3f59b..000000000000
--- a/sdk/azcore/policy_logging_test.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "errors"
- "net/http"
- "strings"
- "testing"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestPolicyLoggingSuccess(t *testing.T) {
- log := map[LogClassification]string{}
- Log().SetListener(func(cls LogClassification, s string) {
- log[cls] = s
- })
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse()
- pl := NewPipeline(srv, NewRequestLogPolicy(RequestLogOptions{}))
- req := NewRequest(http.MethodGet, srv.URL())
- qp := req.URL.Query()
- qp.Set("one", "fish")
- qp.Set("sig", "redact")
- req.URL.RawQuery = qp.Encode()
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if logReq, ok := log[LogRequest]; ok {
- // Request ==> OUTGOING REQUEST (Try=1)
- // GET http://127.0.0.1:49475?one=fish&sig=REDACTED
- // (no headers)
- if !strings.Contains(logReq, "sig=REDACTED") {
- t.Fatal("missing redacted sig query param")
- }
- if !strings.Contains(logReq, "(no headers)") {
- t.Fatal("missing (no headers)")
- }
- } else {
- t.Fatal("missing LogRequest")
- }
- if logResp, ok := log[LogResponse]; ok {
- // Response ==> REQUEST/RESPONSE (Try=1/1.0034ms, OpTime=1.0034ms) -- RESPONSE SUCCESSFULLY RECEIVED
- // GET http://127.0.0.1:49475?one=fish&sig=REDACTED
- // (no headers)
- // --------------------------------------------------------------------------------
- // RESPONSE Status: 200 OK
- // Content-Length: [0]
- // Date: [Fri, 22 Nov 2019 23:48:02 GMT]
- if !strings.Contains(logResp, "RESPONSE Status: 200 OK") {
- t.Fatal("missing response status")
- }
- } else {
- t.Fatal("missing LogResponse")
- }
-}
-
-func TestPolicyLoggingError(t *testing.T) {
- log := map[LogClassification]string{}
- Log().SetListener(func(cls LogClassification, s string) {
- log[cls] = s
- })
- srv, close := mock.NewServer()
- defer close()
- srv.SetError(errors.New("bogus error"))
- pl := NewPipeline(srv, NewRequestLogPolicy(RequestLogOptions{}))
- req := NewRequest(http.MethodGet, srv.URL())
- req.Header.Add("header", "one")
- req.Header.Add("Authorization", "redact")
- resp, err := pl.Do(context.Background(), req)
- if err == nil {
- t.Fatal("unexpected nil error")
- }
- if resp != nil {
- t.Fatal("unexpected respose")
- }
- if logReq, ok := log[LogRequest]; ok {
- // Request ==> OUTGOING REQUEST (Try=1)
- // GET http://127.0.0.1:50057
- // Authorization: REDACTED
- // Header: [one]
- if !strings.Contains(logReq, "Authorization: REDACTED") {
- t.Fatal("missing redacted authorization header")
- }
- } else {
- t.Fatal("missing LogRequest")
- }
- if logError, ok := log[LogError]; ok {
- // Error ==> REQUEST/RESPONSE (Try=1/0s, OpTime=0s) -- REQUEST ERROR
- // GET http://127.0.0.1:50057
- // Authorization: REDACTED
- // Header: [one]
- // --------------------------------------------------------------------------------
- // ERROR:
- // bogus error
- // ...stack track...
- if !strings.Contains(logError, "Authorization: REDACTED") {
- t.Fatal("missing redacted authorization header")
- }
- if !strings.Contains(logError, "bogus error") {
- t.Fatal("missing error message")
- }
- } else {
- t.Fatal("missing LogError")
- }
-}
-
-// TODO: add test for slow response
diff --git a/sdk/azcore/policy_retry.go b/sdk/azcore/policy_retry.go
deleted file mode 100644
index d632b8191ffa..000000000000
--- a/sdk/azcore/policy_retry.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "fmt"
- "io"
- "math/rand"
- "net/http"
- "time"
-)
-
-const (
- defaultMaxRetries = 3
-)
-
-// RetryOptions configures the retry policy's behavior.
-type RetryOptions struct {
- // MaxRetries specifies the maximum number of attempts a failed operation will be retried
- // before producing an error. A value of zero means one try and no retries.
- MaxRetries int32
-
- // TryTimeout indicates the maximum time allowed for any single try of an HTTP request.
- TryTimeout time.Duration
-
- // RetryDelay specifies the amount of delay to use before retrying an operation.
- // The delay increases exponentially with each retry up to a maximum specified by MaxRetryDelay.
- // If you specify 0, then you must also specify 0 for MaxRetryDelay.
- // If you specify RetryDelay, then you must also specify MaxRetryDelay, and MaxRetryDelay should be
- // equal to or greater than RetryDelay.
- RetryDelay time.Duration
-
- // MaxRetryDelay specifies the maximum delay allowed before retrying an operation.
- // If you specify 0, then you must also specify 0 for RetryDelay.
- MaxRetryDelay time.Duration
-
- // StatusCodes specifies the HTTP status codes that indicate the operation should be retried.
- // If unspecified it will default to the status codes in StatusCodesForRetry.
- StatusCodes []int
-}
-
-var (
- // StatusCodesForRetry is the default set of HTTP status code for which the policy will retry.
- // Changing its value will affect future created clients that use the default values.
- StatusCodesForRetry = []int{
- http.StatusRequestTimeout, // 408
- http.StatusInternalServerError, // 500
- http.StatusBadGateway, // 502
- http.StatusServiceUnavailable, // 503
- http.StatusGatewayTimeout, // 504
- }
-)
-
-// DefaultRetryOptions returns an instance of RetryOptions initialized with default values.
-func DefaultRetryOptions() RetryOptions {
- return RetryOptions{
- StatusCodes: StatusCodesForRetry,
- MaxRetries: defaultMaxRetries,
- TryTimeout: 1 * time.Minute,
- RetryDelay: 4 * time.Second,
- MaxRetryDelay: 120 * time.Second,
- }
-}
-
-// used as a context key for adding/retrieving RetryOptions
-type ctxWithRetryOptionsKey struct{}
-
-// WithRetryOptions adds the specified RetryOptions to the parent context.
-// Use this to specify custom RetryOptions at the API-call level.
-func WithRetryOptions(parent context.Context, options RetryOptions) context.Context {
- return context.WithValue(parent, ctxWithRetryOptionsKey{}, options)
-}
-
-func (o RetryOptions) calcDelay(try int32) time.Duration { // try is >=1; never 0
- pow := func(number int64, exponent int32) int64 { // pow is nested helper function
- var result int64 = 1
- for n := int32(0); n < exponent; n++ {
- result *= number
- }
- return result
- }
-
- delay := time.Duration(pow(2, try)-1) * o.RetryDelay
-
- // Introduce some jitter: [0.0, 1.0) / 2 = [0.0, 0.5) + 0.8 = [0.8, 1.3)
- delay = time.Duration(delay.Seconds() * (rand.Float64()/2 + 0.8) * float64(time.Second)) // NOTE: We want math/rand; not crypto/rand
- if delay > o.MaxRetryDelay {
- delay = o.MaxRetryDelay
- }
- return delay
-}
-
-// NewRetryPolicy creates a policy object configured using the specified options.
-// Pass nil to accept the default values; this is the same as passing the result
-// from a call to DefaultRetryOptions().
-func NewRetryPolicy(o *RetryOptions) Policy {
- if o == nil {
- def := DefaultRetryOptions()
- o = &def
- }
- return &retryPolicy{options: *o}
-}
-
-type retryPolicy struct {
- options RetryOptions
-}
-
-func (p *retryPolicy) Do(ctx context.Context, req *Request) (resp *Response, err error) {
- options := p.options
- // check if the retry options have been overridden for this call
- if override := ctx.Value(ctxWithRetryOptionsKey{}); override != nil {
- options = override.(RetryOptions)
- }
- // Exponential retry algorithm: ((2 ^ attempt) - 1) * delay * random(0.8, 1.2)
- // When to retry: connection failure or temporary/timeout.
- if req.Body != nil {
- // wrap the body so we control when it's actually closed
- rwbody := &retryableRequestBody{body: req.Body.(ReadSeekCloser)}
- req.Body = rwbody
- req.Request.GetBody = func() (io.ReadCloser, error) {
- _, err := rwbody.Seek(0, io.SeekStart) // Seek back to the beginning of the stream
- return rwbody, err
- }
- defer rwbody.realClose()
- }
- try := int32(1)
- shouldLog := Log().Should(LogRetryPolicy)
- for {
- resp = nil // reset
- if shouldLog {
- Log().Write(LogRetryPolicy, fmt.Sprintf("\n=====> Try=%d\n", try))
- }
-
- // For each try, seek to the beginning of the Body stream. We do this even for the 1st try because
- // the stream may not be at offset 0 when we first get it and we want the same behavior for the
- // 1st try as for additional tries.
- err = req.RewindBody()
- if err != nil {
- return
- }
-
- // Set the per-try time for this particular retry operation and then Do the operation.
- tryCtx, tryCancel := context.WithTimeout(ctx, options.TryTimeout)
- resp, err = req.Next(tryCtx) // Make the request
- if req.bodyDownloadEnabled() || err != nil || resp.Body == nil {
- // immediately cancel the per-try timeout if any of the following are true
- // 1. auto-download of the response body is enabled
- // 2. an error was returned
- // 3. there is no response body
- // note that we have to check 2 before 3 as if 2 is true then we can't touch resp
- tryCancel()
- } else {
- // wrap the response body in a responseBodyReader.
- // closing the responseBodyReader will cancel the timeout.
- resp.Body = &responseBodyReader{rb: resp.Body, cancelFunc: tryCancel}
- }
- if shouldLog {
- Log().Write(LogRetryPolicy, fmt.Sprintf("Err=%v, response=%v\n", err, resp))
- }
-
- if err == nil && !resp.HasStatusCode(options.StatusCodes...) {
- // if there is no error and the response code isn't in the list of retry codes then we're done.
- return
- } else if ctx.Err() != nil {
- // don't retry if the parent context has been cancelled or its deadline exceeded
- return
- } else if retrier, ok := err.(Retrier); ok && retrier.IsNotRetriable() {
- // the error says it's not retriable so don't retry
- return
- }
-
- // drain before retrying so nothing is leaked
- resp.Drain()
-
- if try == options.MaxRetries+1 {
- // max number of tries has been reached, don't sleep again
- return
- }
-
- // use the delay from retry-after if available
- delay := resp.retryAfter()
- if delay <= 0 {
- delay = options.calcDelay(try)
- }
- if shouldLog {
- Log().Write(LogRetryPolicy, fmt.Sprintf("Try=%d, Delay=%v\n", try, delay))
- }
- select {
- case <-time.After(delay):
- try++
- case <-ctx.Done():
- err = ctx.Err()
- return
- }
- }
-}
-
-// ********** The following type/methods implement the retryableRequestBody (a ReadSeekCloser)
-
-// This struct is used when sending a body to the network
-type retryableRequestBody struct {
- body io.ReadSeeker // Seeking is required to support retries
-}
-
-// Read reads a block of data from an inner stream and reports progress
-func (b *retryableRequestBody) Read(p []byte) (n int, err error) {
- return b.body.Read(p)
-}
-
-func (b *retryableRequestBody) Seek(offset int64, whence int) (offsetFromStart int64, err error) {
- return b.body.Seek(offset, whence)
-}
-
-func (b *retryableRequestBody) Close() error {
- // We don't want the underlying transport to close the request body on transient failures so this is a nop.
- // The retry policy closes the request body upon success.
- return nil
-}
-
-func (b *retryableRequestBody) realClose() error {
- if c, ok := b.body.(io.Closer); ok {
- return c.Close()
- }
- return nil
-}
-
-// used when returning the response body to the caller for reading/closing
-type responseBodyReader struct {
- rb io.ReadCloser
- cancelFunc context.CancelFunc
-}
-
-func (r *responseBodyReader) Read(p []byte) (int, error) {
- return r.rb.Read(p)
-}
-
-func (r *responseBodyReader) Close() error {
- r.cancelFunc()
- return r.rb.Close()
-}
diff --git a/sdk/azcore/policy_retry_test.go b/sdk/azcore/policy_retry_test.go
deleted file mode 100644
index 139dfe4598b3..000000000000
--- a/sdk/azcore/policy_retry_test.go
+++ /dev/null
@@ -1,334 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "errors"
- "io"
- "net/http"
- "strings"
- "testing"
- "time"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func testRetryOptions() *RetryOptions {
- def := DefaultRetryOptions()
- def.RetryDelay = 20 * time.Millisecond
- return &def
-}
-
-func TestRetryPolicySuccess(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithStatusCode(http.StatusOK))
- pl := NewPipeline(srv, NewRetryPolicy(nil))
- req := NewRequest(http.MethodGet, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if body.rcount > 0 {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-func TestRetryPolicyFailOnStatusCode(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithStatusCode(http.StatusInternalServerError))
- pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions()))
- req := NewRequest(http.MethodGet, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusInternalServerError {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if r := srv.Requests(); r != defaultMaxRetries+1 {
- t.Fatalf("wrong request count, got %d expected %d", r, defaultMaxRetries+1)
- }
- if body.rcount != defaultMaxRetries {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-func TestRetryPolicySuccessWithRetry(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.AppendResponse(mock.WithStatusCode(http.StatusRequestTimeout))
- srv.AppendResponse(mock.WithStatusCode(http.StatusInternalServerError))
- srv.AppendResponse()
- pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions()))
- req := NewRequest(http.MethodGet, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if r := srv.Requests(); r != 3 {
- t.Fatalf("wrong retry count, got %d expected %d", r, 3)
- }
- if body.rcount != 2 {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-func TestRetryPolicyFailOnError(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- fakeErr := errors.New("bogus error")
- srv.SetError(fakeErr)
- pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions()))
- req := NewRequest(http.MethodPost, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- resp, err := pl.Do(context.Background(), req)
- if !errors.Is(err, fakeErr) {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp != nil {
- t.Fatal("unexpected response")
- }
- if r := srv.Requests(); r != defaultMaxRetries+1 {
- t.Fatalf("wrong request count, got %d expected %d", r, defaultMaxRetries+1)
- }
- if body.rcount != defaultMaxRetries {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-func TestRetryPolicySuccessWithRetryComplex(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.AppendResponse(mock.WithStatusCode(http.StatusRequestTimeout))
- srv.AppendError(errors.New("bogus error"))
- srv.AppendResponse(mock.WithStatusCode(http.StatusInternalServerError))
- srv.AppendResponse(mock.WithStatusCode(http.StatusAccepted))
- pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions()))
- req := NewRequest(http.MethodGet, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusAccepted {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if r := srv.Requests(); r != defaultMaxRetries+1 {
- t.Fatalf("wrong request count, got %d expected %d", r, defaultMaxRetries+1)
- }
- if body.rcount != defaultMaxRetries {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-func TestRetryPolicyRequestTimedOut(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetError(errors.New("bogus error"))
- pl := NewPipeline(srv, NewRetryPolicy(nil))
- req := NewRequest(http.MethodPost, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
- defer cancel()
- resp, err := pl.Do(ctx, req)
- if !errors.Is(err, context.DeadlineExceeded) {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp != nil {
- t.Fatal("unexpected response")
- }
- if body.rcount > 0 {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-type fatalError struct {
- s string
-}
-
-func (f fatalError) Error() string {
- return f.s
-}
-
-func (f fatalError) IsNotRetriable() bool {
- return true
-}
-
-func TestRetryPolicyIsNotRetriable(t *testing.T) {
- theErr := fatalError{s: "it's dead Jim"}
- srv, close := mock.NewServer()
- defer close()
- srv.AppendResponse(mock.WithStatusCode(http.StatusRequestTimeout))
- srv.AppendError(theErr)
- pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions()))
- _, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err == nil {
- t.Fatal("unexpected nil error")
- }
- if !errors.Is(err, theErr) {
- t.Fatalf("unexpected error type: got %v wanted %v", err, theErr)
- }
- if r := srv.Requests(); r != 2 {
- t.Fatalf("wrong retry count, got %d expected %d", r, 3)
- }
-}
-
-func TestWithRetryOptions(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.RepeatResponse(9, mock.WithStatusCode(http.StatusRequestTimeout))
- srv.AppendResponse(mock.WithStatusCode(http.StatusOK))
- defaultOptions := testRetryOptions()
- pl := NewPipeline(srv, NewRetryPolicy(defaultOptions))
- customOptions := *defaultOptions
- customOptions.MaxRetries = 10
- customOptions.MaxRetryDelay = 200 * time.Millisecond
- retryCtx := WithRetryOptions(context.Background(), customOptions)
- req := NewRequest(http.MethodGet, srv.URL())
- body := newRewindTrackingBody("stuff")
- req.SetBody(body)
- resp, err := pl.Do(retryCtx, req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if body.rcount != int(customOptions.MaxRetries-1) {
- t.Fatalf("unexpected rewind count: %d", body.rcount)
- }
- if !body.closed {
- t.Fatal("request body wasn't closed")
- }
-}
-
-func TestRetryPolicyFailOnErrorNoDownload(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- fakeErr := errors.New("bogus error")
- srv.SetError(fakeErr)
- pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions()))
- req := NewRequest(http.MethodPost, srv.URL())
- req.SkipBodyDownload()
- resp, err := pl.Do(context.Background(), req)
- if !errors.Is(err, fakeErr) {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp != nil {
- t.Fatal("unexpected response")
- }
- if r := srv.Requests(); r != defaultMaxRetries+1 {
- t.Fatalf("wrong request count, got %d expected %d", r, defaultMaxRetries+1)
- }
-}
-
-func TestRetryPolicySuccessNoDownload(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithStatusCode(http.StatusOK), mock.WithBody([]byte("response body")))
- pl := NewPipeline(srv, NewRetryPolicy(nil))
- req := NewRequest(http.MethodGet, srv.URL())
- req.SkipBodyDownload()
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- resp.Body.Close()
-}
-
-func TestRetryPolicySuccessNoDownloadNoBody(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithStatusCode(http.StatusOK))
- pl := NewPipeline(srv, NewRetryPolicy(nil))
- req := NewRequest(http.MethodGet, srv.URL())
- req.SkipBodyDownload()
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.StatusCode != http.StatusOK {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- resp.Body.Close()
-}
-
-// TODO: add test for retry failing to read response body
-
-// TODO: add test for per-retry timeout failed but e2e succeeded
-
-func newRewindTrackingBody(s string) *rewindTrackingBody {
- // there are two rewinds that happen before rewinding for a retry
- // 1. to get the body's size in SetBody()
- // 2. the first call to Do() in the retry policy
- // to offset this we init rcount with -2 so rcount is only > 0 on a rewind due to a retry
- return &rewindTrackingBody{
- body: strings.NewReader(s),
- rcount: -2,
- }
-}
-
-// used to track the number of times a request body has been rewound
-type rewindTrackingBody struct {
- body *strings.Reader
- closed bool // indicates if the body was closed
- rcount int // number of times a rewind happened
-}
-
-func (r *rewindTrackingBody) Close() error {
- r.closed = true
- return nil
-}
-
-func (r *rewindTrackingBody) Read(b []byte) (int, error) {
- return r.body.Read(b)
-}
-
-func (r *rewindTrackingBody) Seek(offset int64, whence int) (int64, error) {
- if offset == 0 && whence == io.SeekStart {
- r.rcount++
- }
- return r.body.Seek(offset, whence)
-}
diff --git a/sdk/azcore/policy_telemetry.go b/sdk/azcore/policy_telemetry.go
deleted file mode 100644
index 10c83fb82f2f..000000000000
--- a/sdk/azcore/policy_telemetry.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "bytes"
- "context"
- "fmt"
- "os"
- "runtime"
-)
-
-// TelemetryOptions configures the telemetry policy's behavior.
-type TelemetryOptions struct {
- // Value is a string prepended to each request's User-Agent and sent to the service.
- // The service records the user-agent in logs for diagnostics and tracking of client requests.
- Value string
-}
-
-type telemetryPolicy struct {
- telemetryValue string
-}
-
-// NewTelemetryPolicy creates a telemetry policy object that adds telemetry information to outgoing HTTP requests.
-func NewTelemetryPolicy(o TelemetryOptions) Policy {
- b := &bytes.Buffer{}
- b.WriteString(o.Value)
- if b.Len() > 0 {
- b.WriteRune(' ')
- }
- b.WriteString(platformInfo)
- return &telemetryPolicy{telemetryValue: b.String()}
-}
-
-func (p telemetryPolicy) Do(ctx context.Context, req *Request) (*Response, error) {
- req.Request.Header.Set(HeaderUserAgent, p.telemetryValue)
- return req.Next(ctx)
-}
-
-// NOTE: the ONLY function that should write to this variable is this func
-var platformInfo = func() string {
- operatingSystem := runtime.GOOS // Default OS string
- switch operatingSystem {
- case "windows":
- operatingSystem = os.Getenv("OS") // Get more specific OS information
- case "linux": // accept default OS info
- case "freebsd": // accept default OS info
- }
- return fmt.Sprintf("(%s; %s)", runtime.Version(), operatingSystem)
-}()
diff --git a/sdk/azcore/policy_telemetry_test.go b/sdk/azcore/policy_telemetry_test.go
deleted file mode 100644
index 2c5dfe3a7f71..000000000000
--- a/sdk/azcore/policy_telemetry_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "fmt"
- "net/http"
- "testing"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestPolicyTelemetryDefault(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse()
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if v := resp.Request.Header.Get(HeaderUserAgent); v != platformInfo {
- t.Fatalf("unexpected user agent value: %s", v)
- }
-}
-
-func TestPolicyTelemetryWithCustomInfo(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse()
- const testValue = "azcore_test"
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{Value: testValue}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if v := resp.Request.Header.Get(HeaderUserAgent); v != fmt.Sprintf("%s %s", testValue, platformInfo) {
- t.Fatalf("unexpected user agent value: %s", v)
- }
-}
diff --git a/sdk/azcore/policy_unique_request_id.go b/sdk/azcore/policy_unique_request_id.go
deleted file mode 100644
index c5f9a84f2867..000000000000
--- a/sdk/azcore/policy_unique_request_id.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
-)
-
-const xMsClientRequestID = "x-ms-client-request-id"
-
-// NewUniqueRequestIDPolicy creates a policy object that sets the request's x-ms-client-request-id header if it doesn't already exist.
-func NewUniqueRequestIDPolicy() Policy {
- return PolicyFunc(func(ctx context.Context, req *Request) (*Response, error) {
- id := req.Request.Header.Get(xMsClientRequestID)
- if id == "" {
- // Add a unique request ID if the caller didn't specify one already
- req.Request.Header.Set(xMsClientRequestID, uuid.New().String())
- }
- return req.Next(ctx)
- })
-}
diff --git a/sdk/azcore/policy_unique_request_id_test.go b/sdk/azcore/policy_unique_request_id_test.go
deleted file mode 100644
index 66c2141063c1..000000000000
--- a/sdk/azcore/policy_unique_request_id_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "net/http"
- "testing"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestUniqueRequestIDPolicy(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse()
- pl := NewPipeline(srv, NewUniqueRequestIDPolicy())
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.Request.Header.Get(xMsClientRequestID) == "" {
- t.Fatal("missing request ID header")
- }
-}
-
-func TestUniqueRequestIDPolicyUserDefined(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse()
- pl := NewPipeline(srv, NewUniqueRequestIDPolicy())
- req := NewRequest(http.MethodGet, srv.URL())
- const customID = "my-custom-id"
- req.Header.Set(xMsClientRequestID, customID)
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if v := resp.Request.Header.Get(xMsClientRequestID); v != customID {
- t.Fatalf("unexpected request ID value: %s", v)
- }
-}
diff --git a/sdk/azcore/progress.go b/sdk/azcore/progress.go
deleted file mode 100644
index 8364581b657e..000000000000
--- a/sdk/azcore/progress.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import "io"
-
-// ********** The following is common between the request body AND the response body.
-
-// ProgressReceiver defines the signature of a callback function invoked as progress is reported.
-type ProgressReceiver func(bytesTransferred int64)
-
-// ********** The following are specific to the request body (a ReadSeekCloser)
-
-// This struct is used when sending a body to the network
-type requestBodyProgress struct {
- requestBody ReadSeekCloser // Seeking is required to support retries
- pr ProgressReceiver
-}
-
-// NewRequestBodyProgress adds progress reporting to an HTTP request's body stream.
-func NewRequestBodyProgress(requestBody ReadSeekCloser, pr ProgressReceiver) ReadSeekCloser {
- return &requestBodyProgress{requestBody: requestBody, pr: pr}
-}
-
-// Read reads a block of data from an inner stream and reports progress
-func (rbp *requestBodyProgress) Read(p []byte) (n int, err error) {
- n, err = rbp.requestBody.Read(p)
- if err != nil {
- return
- }
- // Invokes the user's callback method to report progress
- position, err := rbp.requestBody.Seek(0, io.SeekCurrent)
- if err != nil {
- return
- }
- rbp.pr(position)
- return
-}
-
-func (rbp *requestBodyProgress) Seek(offset int64, whence int) (offsetFromStart int64, err error) {
- return rbp.requestBody.Seek(offset, whence)
-}
-
-// requestBodyProgress supports Close but the underlying stream may not; if it does, Close will close it.
-func (rbp *requestBodyProgress) Close() error {
- return rbp.requestBody.Close()
-}
-
-// ********** The following are specific to the response body (a ReadCloser)
-
-// This struct is used when sending a body to the network
-type responseBodyProgress struct {
- responseBody io.ReadCloser
- pr ProgressReceiver
- offset int64
-}
-
-// NewResponseBodyProgress adds progress reporting to an HTTP response's body stream.
-func NewResponseBodyProgress(responseBody io.ReadCloser, pr ProgressReceiver) io.ReadCloser {
- return &responseBodyProgress{responseBody: responseBody, pr: pr, offset: 0}
-}
-
-// Read reads a block of data from an inner stream and reports progress
-func (rbp *responseBodyProgress) Read(p []byte) (n int, err error) {
- n, err = rbp.responseBody.Read(p)
- rbp.offset += int64(n)
-
- // Invokes the user's callback method to report progress
- rbp.pr(rbp.offset)
- return
-}
-
-func (rbp *responseBodyProgress) Close() error {
- return rbp.responseBody.Close()
-}
diff --git a/sdk/azcore/progress_test.go b/sdk/azcore/progress_test.go
deleted file mode 100644
index 61c3830175f0..000000000000
--- a/sdk/azcore/progress_test.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "bytes"
- "context"
- "io/ioutil"
- "net/http"
- "reflect"
- "testing"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestProgressReporting(t *testing.T) {
- const contentSize = 4096
- content := make([]byte, contentSize)
- for i := 0; i < contentSize; i++ {
- content[i] = byte(i % 255)
- }
- body := bytes.NewReader(content)
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody(content))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- req := NewRequest(http.MethodGet, srv.URL())
- req.SkipBodyDownload()
- var bytesSent int64
- reqRpt := NewRequestBodyProgress(NopCloser(body), func(bytesTransferred int64) {
- bytesSent = bytesTransferred
- })
- req.SetBody(reqRpt)
- resp, err := pl.Do(context.Background(), req)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- var bytesReceived int64
- respRpt := NewResponseBodyProgress(resp.Body, func(bytesTransferred int64) {
- bytesReceived = bytesTransferred
- })
- defer respRpt.Close()
- b, err := ioutil.ReadAll(respRpt)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if bytesSent != contentSize {
- t.Fatalf("wrong bytes sent: %d", bytesSent)
- }
- if bytesReceived != contentSize {
- t.Fatalf("wrong bytes received: %d", bytesReceived)
- }
- if !reflect.DeepEqual(content, b) {
- t.Fatal("request and response bodies don't match")
- }
-}
diff --git a/sdk/azcore/request.go b/sdk/azcore/request.go
deleted file mode 100644
index 55f2e1e90874..000000000000
--- a/sdk/azcore/request.go
+++ /dev/null
@@ -1,218 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "bytes"
- "context"
- "encoding/base64"
- "encoding/json"
- "encoding/xml"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "reflect"
- "strings"
-)
-
-const (
- contentTypeAppJSON = "application/json"
- contentTypeAppXML = "application/xml"
-)
-
-// Base64Encoding is usesd to specify which base-64 encoder/decoder to use when
-// encoding/decoding a slice of bytes to/from a string.
-type Base64Encoding int
-
-const (
- Base64StdFormat Base64Encoding = 0
- Base64URLFormat Base64Encoding = 1
-)
-
-// Request is an abstraction over the creation of an HTTP request as it passes through the pipeline.
-type Request struct {
- *http.Request
- policies []Policy
- values opValues
-}
-
-type opValues map[reflect.Type]interface{}
-
-// Set adds/changes a value
-func (ov opValues) set(value interface{}) {
- ov[reflect.TypeOf(value)] = value
-}
-
-// Get looks for a value set by SetValue first
-func (ov opValues) get(value interface{}) bool {
- v, ok := ov[reflect.ValueOf(value).Elem().Type()]
- if ok {
- reflect.ValueOf(value).Elem().Set(reflect.ValueOf(v))
- }
- return ok
-}
-
-// NewRequest creates a new Request with the specified input.
-func NewRequest(httpMethod string, endpoint url.URL) *Request {
- // removeEmptyPort strips the empty port in ":port" to ""
- // as mandated by RFC 3986 Section 6.2.3.
- // adapted from removeEmptyPort() in net/http.go
- if strings.LastIndex(endpoint.Host, ":") > strings.LastIndex(endpoint.Host, "]") {
- endpoint.Host = strings.TrimSuffix(endpoint.Host, ":")
- }
- return &Request{
- Request: &http.Request{
- Method: httpMethod,
- URL: &endpoint,
- Proto: "HTTP/1.1",
- ProtoMajor: 1,
- ProtoMinor: 1,
- Header: http.Header{},
- Host: endpoint.Host,
- },
- }
-}
-
-// Next calls the next policy in the pipeline.
-// If there are no more policies, nil and ErrNoMorePolicies are returned.
-// This method is intended to be called from pipeline policies.
-// To send a request through a pipeline call Pipeline.Do().
-func (req *Request) Next(ctx context.Context) (*Response, error) {
- if len(req.policies) == 0 {
- return nil, ErrNoMorePolicies
- }
- nextPolicy := req.policies[0]
- nextReq := *req
- nextReq.policies = nextReq.policies[1:]
- return nextPolicy.Do(ctx, &nextReq)
-}
-
-// MarshalAsByteArray will base-64 encode the byte slice v, then calls SetBody.
-// The encoded value is treated as a JSON string.
-func (req *Request) MarshalAsByteArray(v []byte, format Base64Encoding) error {
- var encode string
- switch format {
- case Base64StdFormat:
- encode = base64.StdEncoding.EncodeToString(v)
- case Base64URLFormat:
- // use raw encoding so that '=' characters are omitted as they have special meaning in URLs
- encode = base64.RawURLEncoding.EncodeToString(v)
- default:
- return fmt.Errorf("unrecognized byte array format: %d", format)
- }
- // send as a JSON string
- encode = fmt.Sprintf("\"%s\"", encode)
- req.Header.Set(HeaderContentType, contentTypeAppJSON)
- return req.SetBody(NopCloser(strings.NewReader(encode)))
-}
-
-// MarshalAsJSON calls json.Marshal() to get the JSON encoding of v then calls SetBody.
-// If json.Marshal fails a MarshalError is returned. Any error from SetBody is returned.
-func (req *Request) MarshalAsJSON(v interface{}) error {
- b, err := json.Marshal(v)
- if err != nil {
- return fmt.Errorf("error marshalling type %s: %w", reflect.TypeOf(v).Name(), err)
- }
- req.Header.Set(HeaderContentType, contentTypeAppJSON)
- return req.SetBody(NopCloser(bytes.NewReader(b)))
-}
-
-// MarshalAsXML calls xml.Marshal() to get the XML encoding of v then calls SetBody.
-// If xml.Marshal fails a MarshalError is returned. Any error from SetBody is returned.
-func (req *Request) MarshalAsXML(v interface{}) error {
- b, err := xml.Marshal(v)
- if err != nil {
- return fmt.Errorf("error marshalling type %s: %w", reflect.TypeOf(v).Name(), err)
- }
- req.Header.Set(HeaderContentType, contentTypeAppXML)
- return req.SetBody(NopCloser(bytes.NewReader(b)))
-}
-
-// SetOperationValue adds/changes a mutable key/value associated with a single operation.
-func (req *Request) SetOperationValue(value interface{}) {
- if req.values == nil {
- req.values = opValues{}
- }
- req.values.set(value)
-}
-
-// OperationValue looks for a value set by SetOperationValue().
-func (req *Request) OperationValue(value interface{}) bool {
- if req.values == nil {
- return false
- }
- return req.values.get(value)
-}
-
-// SetBody sets the specified ReadSeekCloser as the HTTP request body.
-func (req *Request) SetBody(body ReadSeekCloser) error {
- // Set the body and content length.
- size, err := body.Seek(0, io.SeekEnd) // Seek to the end to get the stream's size
- if err != nil {
- return err
- }
- if size == 0 {
- body.Close()
- return nil
- }
- _, err = body.Seek(0, io.SeekStart)
- if err != nil {
- return err
- }
- req.Request.Body = body
- req.Request.ContentLength = size
- return nil
-}
-
-// SkipBodyDownload will disable automatic downloading of the response body.
-func (req *Request) SkipBodyDownload() {
- req.SetOperationValue(bodyDownloadPolicyOpValues{skip: true})
-}
-
-// returns true if auto-body download policy is enabled
-func (req *Request) bodyDownloadEnabled() bool {
- var opValues bodyDownloadPolicyOpValues
- req.OperationValue(&opValues)
- return !opValues.skip
-}
-
-// RewindBody seeks the request's Body stream back to the beginning so it can be resent when retrying an operation.
-func (req *Request) RewindBody() error {
- if req.Body != nil {
- // Reset the stream back to the beginning
- _, err := req.Body.(io.Seeker).Seek(0, io.SeekStart)
- return err
- }
- return nil
-}
-
-// Close closes the request body.
-func (req *Request) Close() error {
- if req.Body == nil {
- return nil
- }
- return req.Body.Close()
-}
-
-func (req *Request) copy() *Request {
- clonedURL := *req.URL
- // Copy the values and immutable references
- return &Request{
- Request: &http.Request{
- Method: req.Method,
- URL: &clonedURL,
- Proto: req.Proto,
- ProtoMajor: req.ProtoMajor,
- ProtoMinor: req.ProtoMinor,
- Header: req.Header.Clone(),
- Host: req.URL.Host,
- Body: req.Body, // shallow copy
- ContentLength: req.ContentLength,
- GetBody: req.GetBody,
- },
- }
-}
diff --git a/sdk/azcore/request_test.go b/sdk/azcore/request_test.go
deleted file mode 100644
index 3154541c6b1a..000000000000
--- a/sdk/azcore/request_test.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "errors"
- "io/ioutil"
- "net/http"
- "net/url"
- "testing"
-)
-
-type testJSON struct {
- SomeInt int
- SomeString string
-}
-
-type testXML struct {
- SomeInt int
- SomeString string
-}
-
-func TestRequestMarshalXML(t *testing.T) {
- u, err := url.Parse("https://contoso.com")
- if err != nil {
- panic(err)
- }
- req := NewRequest(http.MethodPost, *u)
- err = req.MarshalAsXML(testXML{SomeInt: 1, SomeString: "s"})
- if err != nil {
- t.Fatalf("marshal failure: %v", err)
- }
- if ct := req.Header.Get(HeaderContentType); ct != contentTypeAppXML {
- t.Fatalf("unexpected content type, got %s wanted %s", ct, contentTypeAppXML)
- }
- if req.Body == nil {
- t.Fatal("unexpected nil request body")
- }
- if req.ContentLength == 0 {
- t.Fatal("unexpected zero content length")
- }
-}
-
-func TestRequestEmptyPipeline(t *testing.T) {
- u, err := url.Parse("https://contoso.com")
- if err != nil {
- panic(err)
- }
- req := NewRequest(http.MethodPost, *u)
- resp, err := req.Next(context.Background())
- if resp != nil {
- t.Fatal("expected nil response")
- }
- if !errors.Is(err, ErrNoMorePolicies) {
- t.Fatalf("expected ErrNoMorePolicies, got %v", err)
- }
-}
-
-func TestRequestMarshalJSON(t *testing.T) {
- u, err := url.Parse("https://contoso.com")
- if err != nil {
- panic(err)
- }
- req := NewRequest(http.MethodPost, *u)
- err = req.MarshalAsJSON(testJSON{SomeInt: 1, SomeString: "s"})
- if err != nil {
- t.Fatalf("marshal failure: %v", err)
- }
- if ct := req.Header.Get(HeaderContentType); ct != contentTypeAppJSON {
- t.Fatalf("unexpected content type, got %s wanted %s", ct, contentTypeAppJSON)
- }
- if req.Body == nil {
- t.Fatal("unexpected nil request body")
- }
- if req.ContentLength == 0 {
- t.Fatal("unexpected zero content length")
- }
-}
-
-func TestRequestMarshalAsByteArrayURLFormat(t *testing.T) {
- u, err := url.Parse("https://contoso.com")
- if err != nil {
- panic(err)
- }
- req := NewRequest(http.MethodPost, *u)
- const payload = "a string that gets encoded with base64url"
- err = req.MarshalAsByteArray([]byte(payload), Base64URLFormat)
- if err != nil {
- t.Fatalf("marshal failure: %v", err)
- }
- if ct := req.Header.Get(HeaderContentType); ct != contentTypeAppJSON {
- t.Fatalf("unexpected content type, got %s wanted %s", ct, contentTypeAppJSON)
- }
- if req.Body == nil {
- t.Fatal("unexpected nil request body")
- }
- if req.ContentLength == 0 {
- t.Fatal("unexpected zero content length")
- }
- b, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Fatal(err)
- }
- if string(b) != `"YSBzdHJpbmcgdGhhdCBnZXRzIGVuY29kZWQgd2l0aCBiYXNlNjR1cmw"` {
- t.Fatalf("bad body, got %s", string(b))
- }
-}
-
-func TestRequestMarshalAsByteArrayStdFormat(t *testing.T) {
- u, err := url.Parse("https://contoso.com")
- if err != nil {
- panic(err)
- }
- req := NewRequest(http.MethodPost, *u)
- const payload = "a string that gets encoded with base64url"
- err = req.MarshalAsByteArray([]byte(payload), Base64StdFormat)
- if err != nil {
- t.Fatalf("marshal failure: %v", err)
- }
- if ct := req.Header.Get(HeaderContentType); ct != contentTypeAppJSON {
- t.Fatalf("unexpected content type, got %s wanted %s", ct, contentTypeAppJSON)
- }
- if req.Body == nil {
- t.Fatal("unexpected nil request body")
- }
- if req.ContentLength == 0 {
- t.Fatal("unexpected zero content length")
- }
- b, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Fatal(err)
- }
- if string(b) != `"YSBzdHJpbmcgdGhhdCBnZXRzIGVuY29kZWQgd2l0aCBiYXNlNjR1cmw="` {
- t.Fatalf("bad body, got %s", string(b))
- }
-}
diff --git a/sdk/azcore/response.go b/sdk/azcore/response.go
deleted file mode 100644
index 3f018acd82ce..000000000000
--- a/sdk/azcore/response.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "encoding/xml"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "reflect"
- "sort"
- "strconv"
- "strings"
- "time"
-)
-
-// Response represents the response from an HTTP request.
-type Response struct {
- *http.Response
-}
-
-func (r *Response) payload() []byte {
- if r.Body == nil {
- return nil
- }
- // r.Body won't be a nopClosingBytesReader if downloading was skipped
- if buf, ok := r.Body.(*nopClosingBytesReader); ok {
- return buf.Bytes()
- }
- return nil
-}
-
-// HasStatusCode returns true if the Response's status code is one of the specified values.
-func (r *Response) HasStatusCode(statusCodes ...int) bool {
- if r == nil {
- return false
- }
- for _, sc := range statusCodes {
- if r.StatusCode == sc {
- return true
- }
- }
- return false
-}
-
-// UnmarshalAsByteArray will base-64 decode the received payload and place the result into the value pointed to by v.
-func (r *Response) UnmarshalAsByteArray(v **[]byte, format Base64Encoding) error {
- if len(r.payload()) == 0 {
- return nil
- }
- payload := string(r.payload())
- if payload[0] == '"' {
- // remove surrounding quotes
- payload = payload[1 : len(payload)-1]
- }
- switch format {
- case Base64StdFormat:
- decoded, err := base64.StdEncoding.DecodeString(payload)
- if err == nil {
- *v = &decoded
- return nil
- }
- return err
- case Base64URLFormat:
- // use raw encoding as URL format should not contain any '=' characters
- decoded, err := base64.RawURLEncoding.DecodeString(payload)
- if err == nil {
- *v = &decoded
- return nil
- }
- return err
- default:
- return fmt.Errorf("unrecognized byte array format: %d", format)
- }
-}
-
-// UnmarshalAsJSON calls json.Unmarshal() to unmarshal the received payload into the value pointed to by v.
-// If no payload was received a RequestError is returned. If json.Unmarshal fails a UnmarshalError is returned.
-func (r *Response) UnmarshalAsJSON(v interface{}) error {
- // TODO: verify early exit is correct
- if len(r.payload()) == 0 {
- return nil
- }
- r.removeBOM()
- err := json.Unmarshal(r.payload(), v)
- if err != nil {
- err = fmt.Errorf("unmarshalling type %s: %w", reflect.TypeOf(v).Elem().Name(), err)
- }
- return err
-}
-
-// UnmarshalAsXML calls xml.Unmarshal() to unmarshal the received payload into the value pointed to by v.
-// If no payload was received a RequestError is returned. If xml.Unmarshal fails a UnmarshalError is returned.
-func (r *Response) UnmarshalAsXML(v interface{}) error {
- // TODO: verify early exit is correct
- if len(r.payload()) == 0 {
- return nil
- }
- r.removeBOM()
- err := xml.Unmarshal(r.payload(), v)
- if err != nil {
- err = fmt.Errorf("unmarshalling type %s: %w", reflect.TypeOf(v).Elem().Name(), err)
- }
- return err
-}
-
-// Drain reads the response body to completion then closes it. The bytes read are discarded.
-func (r *Response) Drain() {
- if r != nil && r.Body != nil {
- io.Copy(ioutil.Discard, r.Body)
- r.Body.Close()
- }
-}
-
-// removeBOM removes any byte-order mark prefix from the payload if present.
-func (r *Response) removeBOM() {
- // UTF8
- trimmed := bytes.TrimPrefix(r.payload(), []byte("\xef\xbb\xbf"))
- if len(trimmed) < len(r.payload()) {
- r.Body.(*nopClosingBytesReader).Set(trimmed)
- }
-}
-
-// helper to reduce nil Response checks
-func (r *Response) retryAfter() time.Duration {
- if r == nil {
- return 0
- }
- return RetryAfter(r.Response)
-}
-
-// RetryAfter returns non-zero if the response contains a Retry-After header value.
-func RetryAfter(resp *http.Response) time.Duration {
- if resp == nil {
- return 0
- }
- ra := resp.Header.Get(HeaderRetryAfter)
- if ra == "" {
- return 0
- }
- // retry-after values are expressed in either number of
- // seconds or an HTTP-date indicating when to try again
- if retryAfter, _ := strconv.Atoi(ra); retryAfter > 0 {
- return time.Duration(retryAfter) * time.Second
- } else if t, err := time.Parse(time.RFC1123, ra); err == nil {
- return t.Sub(time.Now())
- }
- return 0
-}
-
-// WriteRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are
-// not nil, then these are also written into the Buffer.
-func WriteRequestWithResponse(b *bytes.Buffer, request *Request, response *Response, err error) {
- // Write the request into the buffer.
- fmt.Fprint(b, " "+request.Method+" "+request.URL.String()+"\n")
- writeHeader(b, request.Header)
- if response != nil {
- fmt.Fprintln(b, " --------------------------------------------------------------------------------")
- fmt.Fprint(b, " RESPONSE Status: "+response.Status+"\n")
- writeHeader(b, response.Header)
- }
- if err != nil {
- fmt.Fprintln(b, " --------------------------------------------------------------------------------")
- fmt.Fprint(b, " ERROR:\n"+err.Error()+"\n")
- }
-}
-
-// formatHeaders appends an HTTP request's or response's header into a Buffer.
-func writeHeader(b *bytes.Buffer, header http.Header) {
- if len(header) == 0 {
- b.WriteString(" (no headers)\n")
- return
- }
- keys := make([]string, 0, len(header))
- // Alphabetize the headers
- for k := range header {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- // Redact the value of any Authorization header to prevent security information from persisting in logs
- value := interface{}("REDACTED")
- if !strings.EqualFold(k, "Authorization") {
- value = header[k]
- }
- fmt.Fprintf(b, " %s: %+v\n", k, value)
- }
-}
diff --git a/sdk/azcore/response_test.go b/sdk/azcore/response_test.go
deleted file mode 100644
index f4b1324dc971..000000000000
--- a/sdk/azcore/response_test.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "net/http"
- "testing"
- "time"
-
- "github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
-)
-
-func TestResponseUnmarshalXML(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- // include UTF8 BOM
- srv.SetResponse(mock.WithBody([]byte("\xef\xbb\xbf1s")))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- var tx testXML
- if err := resp.UnmarshalAsXML(&tx); err != nil {
- t.Fatalf("unexpected error unmarshalling: %v", err)
- }
- if tx.SomeInt != 1 || tx.SomeString != "s" {
- t.Fatal("unexpected value")
- }
-}
-
-func TestResponseFailureStatusCode(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithStatusCode(http.StatusForbidden))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
-}
-
-func TestResponseUnmarshalJSON(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte(`{ "someInt": 1, "someString": "s" }`)))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- var tx testJSON
- if err := resp.UnmarshalAsJSON(&tx); err != nil {
- t.Fatalf("unexpected error unmarshalling: %v", err)
- }
- if tx.SomeInt != 1 || tx.SomeString != "s" {
- t.Fatal("unexpected value")
- }
-}
-
-func TestResponseUnmarshalJSONNoBody(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte{}))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if err := resp.UnmarshalAsJSON(nil); err != nil {
- t.Fatalf("unexpected error unmarshalling: %v", err)
- }
-}
-
-func TestResponseUnmarshalXMLNoBody(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte{}))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- if err := resp.UnmarshalAsXML(nil); err != nil {
- t.Fatalf("unexpected error unmarshalling: %v", err)
- }
-}
-
-func TestRetryAfter(t *testing.T) {
- raw := &http.Response{
- Header: http.Header{},
- }
- resp := Response{raw}
- if d := resp.retryAfter(); d > 0 {
- t.Fatalf("unexpected retry-after value %d", d)
- }
- raw.Header.Set(HeaderRetryAfter, "300")
- d := resp.retryAfter()
- if d <= 0 {
- t.Fatal("expected retry-after value from seconds")
- }
- if d != 300*time.Second {
- t.Fatalf("expected 300 seconds, got %d", d/time.Second)
- }
- atDate := time.Now().Add(600 * time.Second)
- raw.Header.Set(HeaderRetryAfter, atDate.Format(time.RFC1123))
- d = resp.retryAfter()
- if d <= 0 {
- t.Fatal("expected retry-after value from date")
- }
- // d will not be exactly 600 seconds but it will be close
- if d/time.Second != 599 {
- t.Fatalf("expected ~600 seconds, got %d", d/time.Second)
- }
-}
-
-func TestResponseUnmarshalAsByteArrayURLFormat(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte(`"YSBzdHJpbmcgdGhhdCBnZXRzIGVuY29kZWQgd2l0aCBiYXNlNjR1cmw"`)))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- var ba *[]byte
- if err := resp.UnmarshalAsByteArray(&ba, Base64URLFormat); err != nil {
- t.Fatalf("unexpected error unmarshalling: %v", err)
- }
- if string(*ba) != "a string that gets encoded with base64url" {
- t.Fatalf("bad payload, got %s", string(*ba))
- }
-}
-
-func TestResponseUnmarshalAsByteArrayStdFormat(t *testing.T) {
- srv, close := mock.NewServer()
- defer close()
- srv.SetResponse(mock.WithBody([]byte(`"YSBzdHJpbmcgdGhhdCBnZXRzIGVuY29kZWQgd2l0aCBiYXNlNjR1cmw="`)))
- pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{}))
- resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL()))
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !resp.HasStatusCode(http.StatusOK) {
- t.Fatalf("unexpected status code: %d", resp.StatusCode)
- }
- var ba *[]byte
- if err := resp.UnmarshalAsByteArray(&ba, Base64StdFormat); err != nil {
- t.Fatalf("unexpected error unmarshalling: %v", err)
- }
- if string(*ba) != "a string that gets encoded with base64url" {
- t.Fatalf("bad payload, got %s", string(*ba))
- }
-}
diff --git a/sdk/azcore/transport_default_http_client.go b/sdk/azcore/transport_default_http_client.go
deleted file mode 100644
index 4a91d0609cd0..000000000000
--- a/sdk/azcore/transport_default_http_client.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-import (
- "context"
- "crypto/tls"
- "net/http"
-)
-
-var defaultHTTPClient *http.Client
-
-func init() {
- defaultTransport := http.DefaultTransport.(*http.Transport)
- transport := &http.Transport{
- Proxy: defaultTransport.Proxy,
- DialContext: defaultTransport.DialContext,
- MaxIdleConns: defaultTransport.MaxIdleConns,
- IdleConnTimeout: defaultTransport.IdleConnTimeout,
- TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout,
- ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
- TLSClientConfig: &tls.Config{
- MinVersion: tls.VersionTLS12,
- },
- }
- // TODO: in track 1 we created a cookiejar, do we need one here? make it an option? user-specified HTTP client policy?
- defaultHTTPClient = &http.Client{
- Transport: transport,
- }
-}
-
-// DefaultHTTPClientTransport ...
-func DefaultHTTPClientTransport() Transport {
- return TransportFunc(func(ctx context.Context, req *http.Request) (*http.Response, error) {
- return defaultHTTPClient.Do(req.WithContext(ctx))
- })
-}
diff --git a/sdk/azcore/version.go b/sdk/azcore/version.go
deleted file mode 100644
index 8d4493c648c8..000000000000
--- a/sdk/azcore/version.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package azcore
-
-const (
- // UserAgent is the string to be used in the user agent string when making requests.
- UserAgent = "azcore/" + Version
-
- // Version is the semantic version (see http://semver.org) of the pipeline package.
- Version = "0.1.0"
-)
diff --git a/sdk/azidentity/go.mod b/sdk/azidentity/go.mod
index e4f14583feef..ec84ba11f6ce 100644
--- a/sdk/azidentity/go.mod
+++ b/sdk/azidentity/go.mod
@@ -3,6 +3,6 @@ module github.com/Azure/azure-sdk-for-go/sdk/azidentity
go 1.13
require (
- github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0
- github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0
+ github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0
)
diff --git a/sdk/azidentity/go.sum b/sdk/azidentity/go.sum
index 1ae648017870..00dfdfebed95 100644
--- a/sdk/azidentity/go.sum
+++ b/sdk/azidentity/go.sum
@@ -1,4 +1,4 @@
-github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0 h1:ogZVkNX3wS6ekWS3hD9sQCghWIGfw8CQ9JKv0rQQlVw=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v0.8.0/go.mod h1:UKq2za3CMGx75vfPM9tPSuTBNODR4hX1qAeb+GRoDkc=
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws=
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0 h1:VdhfbVpQ3dkhXYOx/Wj1+utikcZkZSZSmpqmXWwaNJY=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.9.0/go.mod h1:hL9TGc07RkJVzDIBxsYXC/r0M+YiRkvl4z1elXCD+8s=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0 h1:cLpVMIkXC/umSP9DMz9I6FttDWJAsmvhpaB6MlkagGY=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.2.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY=
diff --git a/sdk/internal/atomic/atomic.go b/sdk/internal/atomic/atomic.go
deleted file mode 100644
index 781dbeca94af..000000000000
--- a/sdk/internal/atomic/atomic.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package atomic
-
-import (
- "sync/atomic"
- "time"
-)
-
-// Int64 is an atomic wrapper around an int64.
-type Int64 int64
-
-// NewInt64 creates a new Int64.
-func NewInt64(i int64) Int64 {
- return Int64(i)
-}
-
-// CAS is an atomic compare-and-swap.
-func (i *Int64) CAS(old, new int64) bool {
- return atomic.CompareAndSwapInt64((*int64)(i), old, new)
-}
-
-// Load atomically loads the value.
-func (i *Int64) Load() int64 {
- return atomic.LoadInt64((*int64)(i))
-}
-
-// Store atomically stores the value.
-func (i *Int64) Store(v int64) {
- atomic.StoreInt64((*int64)(i), v)
-}
-
-// String is an atomic wrapper around a string.
-type String struct {
- v atomic.Value
-}
-
-// NewString creats a new String.
-func NewString(s string) *String {
- ss := String{}
- ss.v.Store(s)
- return &ss
-}
-
-// Load atomically loads the string.
-func (s *String) Load() string {
- return s.v.Load().(string)
-}
-
-// Store atomically stores the string.
-func (s *String) Store(v string) {
- s.v.Store(v)
-}
-
-// Time is an atomic wrapper around a time.Time.
-type Time struct {
- v atomic.Value
-}
-
-// NewTime creates a new Time.
-func NewTime(t time.Time) *Time {
- tt := Time{}
- tt.v.Store(t)
- return &tt
-}
-
-// Load atomically loads the time.Time.
-func (t *Time) Load() time.Time {
- return t.v.Load().(time.Time)
-}
-
-// Store atomically stores the time.Time.
-func (t *Time) Store(v time.Time) {
- t.v.Store(v)
-}
diff --git a/sdk/internal/go.mod b/sdk/internal/go.mod
deleted file mode 100644
index 1bb024518b8c..000000000000
--- a/sdk/internal/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/Azure/azure-sdk-for-go/sdk/internal
-
-go 1.13
diff --git a/sdk/internal/mock/mock.go b/sdk/internal/mock/mock.go
deleted file mode 100644
index d409860389ca..000000000000
--- a/sdk/internal/mock/mock.go
+++ /dev/null
@@ -1,207 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package mock
-
-import (
- "context"
- "net/http"
- "net/http/httptest"
- "net/url"
-)
-
-// Server is a wrapper around an httptest.Server.
-// The serving of requests is not safe for concurrent use
-// which is ok for right now as each test creates is own
-// server and doesn't create additional go routines.
-type Server struct {
- srv *httptest.Server
-
- // static is the static response, if this is not nil it's always returned.
- static *mockResponse
-
- // resp is the queue of responses. each response is taken from the front.
- resp []mockResponse
-
- // count tracks the number of requests that have been made.
- count int
-}
-
-// NewServer creates a new Server object.
-// The returned close func must be called when the server is no longer needed.
-func NewServer() (*Server, func()) {
- s := Server{}
- s.srv = httptest.NewServer(http.HandlerFunc(s.serveHTTP))
- return &s, func() { s.srv.Close() }
-}
-
-// NewTLSServer creates a new Server object.
-// The returned close func must be called when the server is no longer needed.
-func NewTLSServer() (*Server, func()) {
- s := Server{}
- s.srv = httptest.NewTLSServer(http.HandlerFunc(s.serveHTTP))
- return &s, func() { s.srv.Close() }
-}
-
-// returns true if the next response is an error response
-func (s *Server) isErrorResp() bool {
- if s.static == nil && len(s.resp) == 0 {
- panic("no more responses")
- }
- // always favor static response
- if s.static != nil && s.static.err != nil {
- return true
- }
- if len(s.resp) == 0 {
- return false
- }
- return s.resp[0].err != nil
-}
-
-// returns the static response or the next response in the queue
-func (s *Server) getResponse() mockResponse {
- if s.static == nil && len(s.resp) == 0 {
- panic("no more responses")
- }
- // always favor static response
- if s.static != nil {
- return *s.static
- }
- // pop off first response and return it
- resp := s.resp[0]
- s.resp = s.resp[1:]
- return resp
-}
-
-// URL returns the endpoint of the test server in URL format.
-func (s *Server) URL() url.URL {
- u, err := url.Parse(s.srv.URL)
- if err != nil {
- panic(err)
- }
- return *u
-}
-
-// Do implements the azcore.Transport interface on Server.
-// Calling this when the response queue is empty and no static
-// response has been set will cause a panic.
-func (s *Server) Do(ctx context.Context, req *http.Request) (*http.Response, error) {
- s.count++
- // error responses are returned here
- if s.isErrorResp() {
- resp := s.getResponse()
- return nil, resp.err
- }
- return s.srv.Client().Do(req.WithContext(ctx))
-}
-
-func (s *Server) serveHTTP(w http.ResponseWriter, req *http.Request) {
- s.getResponse().write(w)
-}
-
-// Requests returns the number of times an HTTP request was made.
-func (s *Server) Requests() int {
- return s.count
-}
-
-// AppendError appends the error to the end of the response queue.
-func (s *Server) AppendError(err error) {
- s.resp = append(s.resp, mockResponse{err: err})
-}
-
-// RepeatError appends the error n number of times to the end of the response queue.
-func (s *Server) RepeatError(n int, err error) {
- for i := 0; i < n; i++ {
- s.AppendError(err)
- }
-}
-
-// SetError indicates the same error should always be returned.
-// Any responses set via other methods will be ignored.
-func (s *Server) SetError(err error) {
- s.static = &mockResponse{err: err}
-}
-
-// AppendResponse appends the response to the end of the response queue.
-// If no options are provided the default response is an http.StatusOK.
-func (s *Server) AppendResponse(opts ...ResponseOption) {
- mr := mockResponse{code: http.StatusOK}
- for _, o := range opts {
- o.apply(&mr)
- }
- s.resp = append(s.resp, mr)
-}
-
-// RepeatResponse appends the response n number of times to the end of the response queue.
-// If no options are provided the default response is an http.StatusOK.
-func (s *Server) RepeatResponse(n int, opts ...ResponseOption) {
- for i := 0; i < n; i++ {
- s.AppendResponse(opts...)
- }
-}
-
-// SetResponse indicates the same response should always be returned.
-// Any responses set via other methods will be ignored.
-// If no options are provided the default response is an http.StatusOK.
-func (s *Server) SetResponse(opts ...ResponseOption) {
- mr := mockResponse{code: http.StatusOK}
- for _, o := range opts {
- o.apply(&mr)
- }
- s.static = &mr
-}
-
-// ResponseOption is an abstraction for configuring a mock HTTP response.
-type ResponseOption interface {
- apply(mr *mockResponse)
-}
-
-type fnRespOpt func(*mockResponse)
-
-func (fn fnRespOpt) apply(mr *mockResponse) {
- fn(mr)
-}
-
-type mockResponse struct {
- code int
- body []byte
- headers http.Header
- err error
-}
-
-func (mr mockResponse) write(w http.ResponseWriter) {
- w.WriteHeader(mr.code)
- if mr.body != nil {
- w.Write(mr.body)
- }
- if len(mr.headers) > 0 {
- for k, v := range mr.headers {
- for _, vv := range v {
- w.Header().Add(k, vv)
- }
- }
- }
-}
-
-// WithStatusCode sets the HTTP response's status code to the specified value.
-func WithStatusCode(c int) ResponseOption {
- return fnRespOpt(func(mr *mockResponse) {
- mr.code = c
- })
-}
-
-// WithBody sets the HTTP response's body to the specified value.
-func WithBody(b []byte) ResponseOption {
- return fnRespOpt(func(mr *mockResponse) {
- mr.body = b
- })
-}
-
-// WithHeader adds the specified header and value to the HTTP response.
-func WithHeader(k, v string) ResponseOption {
- return fnRespOpt(func(mr *mockResponse) {
- mr.headers.Add(k, v)
- })
-}
diff --git a/sdk/internal/uuid/uuid.go b/sdk/internal/uuid/uuid.go
deleted file mode 100644
index 4b288d81fecd..000000000000
--- a/sdk/internal/uuid/uuid.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package uuid
-
-import (
- "fmt"
- "math/rand"
- "strconv"
- "time"
-)
-
-// The UUID reserved variants.
-const (
- reservedNCS byte = 0x80
- reservedRFC4122 byte = 0x40
- reservedMicrosoft byte = 0x20
- reservedFuture byte = 0x00
-)
-
-func init() {
- rand.Seed(time.Now().Unix())
-}
-
-// A UUID representation compliant with specification in RFC 4122 document.
-type UUID [16]byte
-
-// New returns a new uuid using RFC 4122 algorithm.
-func New() UUID {
- u := UUID{}
- // Set all bits to randomly (or pseudo-randomly) chosen values.
- // math/rand.Read() is no-fail so we omit any error checking.
- // NOTE: this takes a process-wide lock
- rand.Read(u[:])
- u[8] = (u[8] | reservedRFC4122) & 0x7F // u.setVariant(ReservedRFC4122)
-
- var version byte = 4
- u[6] = (u[6] & 0xF) | (version << 4) // u.setVersion(4)
- return u
-}
-
-// String returns an unparsed version of the generated UUID sequence.
-func (u UUID) String() string {
- return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
-}
-
-// Parse parses a string formatted as "003020100-0504-0706-0809-0a0b0c0d0e0f"
-// or "{03020100-0504-0706-0809-0a0b0c0d0e0f}" into a UUID.
-func Parse(uuidStr string) UUID {
- char := func(hexString string) byte {
- i, _ := strconv.ParseUint(hexString, 16, 8)
- return byte(i)
- }
- if uuidStr[0] == '{' {
- uuidStr = uuidStr[1:] // Skip over the '{'
- }
- // 03020100 - 05 04 - 07 06 - 08 09 - 0a 0b 0c 0d 0e 0f
- // 1 11 1 11 11 1 12 22 2 22 22 22 33 33 33
- // 01234567 8 90 12 3 45 67 8 90 12 3 45 67 89 01 23 45
- uuidVal := UUID{
- char(uuidStr[0:2]),
- char(uuidStr[2:4]),
- char(uuidStr[4:6]),
- char(uuidStr[6:8]),
-
- char(uuidStr[9:11]),
- char(uuidStr[11:13]),
-
- char(uuidStr[14:16]),
- char(uuidStr[16:18]),
-
- char(uuidStr[19:21]),
- char(uuidStr[21:23]),
-
- char(uuidStr[24:26]),
- char(uuidStr[26:28]),
- char(uuidStr[28:30]),
- char(uuidStr[30:32]),
- char(uuidStr[32:34]),
- char(uuidStr[34:36]),
- }
- return uuidVal
-}
-
-func (u UUID) bytes() []byte {
- return u[:]
-}
diff --git a/sdk/to/go.mod b/sdk/to/go.mod
deleted file mode 100644
index 1e4a74c22d67..000000000000
--- a/sdk/to/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/Azure/azure-sdk-for-go/sdk/to
-
-go 1.13
diff --git a/sdk/to/to.go b/sdk/to/to.go
deleted file mode 100644
index 2ebb4b23c202..000000000000
--- a/sdk/to/to.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// +build go1.13
-
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package to
-
-// BoolPtr returns a pointer to the provided bool.
-func BoolPtr(b bool) *bool {
- return &b
-}
-
-// Float32Ptr returns a pointer to the provided float32.
-func Float32Ptr(i float32) *float32 {
- return &i
-}
-
-// Float64Ptr returns a pointer to the provided float64.
-func Float64Ptr(i float64) *float64 {
- return &i
-}
-
-// Int32Ptr returns a pointer to the provided int32.
-func Int32Ptr(i int32) *int32 {
- return &i
-}
-
-// Int64Ptr returns a pointer to the provided int64.
-func Int64Ptr(i int64) *int64 {
- return &i
-}
-
-// StringPtr returns a pointer to the provided string.
-func StringPtr(s string) *string {
- return &s
-}