Update vendored azure-sdk-for-go
Updating to a recent version of Azure Storage SDK to be able to patch some memory leaks through configurable HTTP client changes which were made possible by recent patches to it. Signed-off-by: Ahmet Alp Balkan <ahmetalpbalkan@gmail.com>
This commit is contained in:
parent
62e88f0fe7
commit
2ab25288a2
10 changed files with 1241 additions and 40 deletions
179
vendor/github.com/Azure/azure-sdk-for-go/storage/client.go
generated
vendored
179
vendor/github.com/Azure/azure-sdk-for-go/storage/client.go
generated
vendored
|
@ -4,6 +4,7 @@ package storage
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -28,15 +29,29 @@ const (
|
|||
|
||||
defaultUseHTTPS = true
|
||||
|
||||
// StorageEmulatorAccountName is the fixed storage account used by Azure Storage Emulator
|
||||
StorageEmulatorAccountName = "devstoreaccount1"
|
||||
|
||||
// StorageEmulatorAccountKey is the the fixed storage account used by Azure Storage Emulator
|
||||
StorageEmulatorAccountKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
|
||||
|
||||
blobServiceName = "blob"
|
||||
tableServiceName = "table"
|
||||
queueServiceName = "queue"
|
||||
fileServiceName = "file"
|
||||
|
||||
storageEmulatorBlob = "127.0.0.1:10000"
|
||||
storageEmulatorTable = "127.0.0.1:10002"
|
||||
storageEmulatorQueue = "127.0.0.1:10001"
|
||||
)
|
||||
|
||||
// Client is the object that needs to be constructed to perform
|
||||
// operations on the storage account.
|
||||
type Client struct {
|
||||
// HTTPClient is the http.Client used to initiate API
|
||||
// requests. If it is nil, http.DefaultClient is used.
|
||||
HTTPClient *http.Client
|
||||
|
||||
accountName string
|
||||
accountKey []byte
|
||||
useHTTPS bool
|
||||
|
@ -50,6 +65,11 @@ type storageResponse struct {
|
|||
body io.ReadCloser
|
||||
}
|
||||
|
||||
type odataResponse struct {
|
||||
storageResponse
|
||||
odata odataErrorMessage
|
||||
}
|
||||
|
||||
// AzureStorageServiceError contains fields of the error response from
|
||||
// Azure Storage Service REST API. See https://msdn.microsoft.com/en-us/library/azure/dd179382.aspx
|
||||
// Some fields might be specific to certain calls.
|
||||
|
@ -64,6 +84,20 @@ type AzureStorageServiceError struct {
|
|||
RequestID string
|
||||
}
|
||||
|
||||
type odataErrorMessageMessage struct {
|
||||
Lang string `json:"lang"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type odataErrorMessageInternal struct {
|
||||
Code string `json:"code"`
|
||||
Message odataErrorMessageMessage `json:"message"`
|
||||
}
|
||||
|
||||
type odataErrorMessage struct {
|
||||
Err odataErrorMessageInternal `json:"odata.error"`
|
||||
}
|
||||
|
||||
// UnexpectedStatusCodeError is returned when a storage service responds with neither an error
|
||||
// nor with an HTTP status code indicating success.
|
||||
type UnexpectedStatusCodeError struct {
|
||||
|
@ -90,9 +124,18 @@ func (e UnexpectedStatusCodeError) Got() int {
|
|||
// NewBasicClient constructs a Client with given storage service name and
|
||||
// key.
|
||||
func NewBasicClient(accountName, accountKey string) (Client, error) {
|
||||
if accountName == StorageEmulatorAccountName {
|
||||
return NewEmulatorClient()
|
||||
}
|
||||
return NewClient(accountName, accountKey, DefaultBaseURL, DefaultAPIVersion, defaultUseHTTPS)
|
||||
}
|
||||
|
||||
//NewEmulatorClient contructs a Client intended to only work with Azure
|
||||
//Storage Emulator
|
||||
func NewEmulatorClient() (Client, error) {
|
||||
return NewClient(StorageEmulatorAccountName, StorageEmulatorAccountKey, DefaultBaseURL, DefaultAPIVersion, false)
|
||||
}
|
||||
|
||||
// NewClient constructs a Client. This should be used if the caller wants
|
||||
// to specify whether to use HTTPS, a specific REST API version or a custom
|
||||
// storage endpoint than Azure Public Cloud.
|
||||
|
@ -108,7 +151,7 @@ func NewClient(accountName, accountKey, blobServiceBaseURL, apiVersion string, u
|
|||
|
||||
key, err := base64.StdEncoding.DecodeString(accountKey)
|
||||
if err != nil {
|
||||
return c, err
|
||||
return c, fmt.Errorf("azure: malformed storage account key: %v", err)
|
||||
}
|
||||
|
||||
return Client{
|
||||
|
@ -125,8 +168,19 @@ func (c Client) getBaseURL(service string) string {
|
|||
if c.useHTTPS {
|
||||
scheme = "https"
|
||||
}
|
||||
|
||||
host := fmt.Sprintf("%s.%s.%s", c.accountName, service, c.baseURL)
|
||||
host := ""
|
||||
if c.accountName == StorageEmulatorAccountName {
|
||||
switch service {
|
||||
case blobServiceName:
|
||||
host = storageEmulatorBlob
|
||||
case tableServiceName:
|
||||
host = storageEmulatorTable
|
||||
case queueServiceName:
|
||||
host = storageEmulatorQueue
|
||||
}
|
||||
} else {
|
||||
host = fmt.Sprintf("%s.%s.%s", c.accountName, service, c.baseURL)
|
||||
}
|
||||
|
||||
u := &url.URL{
|
||||
Scheme: scheme,
|
||||
|
@ -141,8 +195,13 @@ func (c Client) getEndpoint(service, path string, params url.Values) string {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
if path == "" {
|
||||
path = "/" // API doesn't accept path segments not starting with '/'
|
||||
// API doesn't accept path segments not starting with '/'
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
path = fmt.Sprintf("/%v", path)
|
||||
}
|
||||
|
||||
if c.accountName == StorageEmulatorAccountName {
|
||||
path = fmt.Sprintf("/%v%v", StorageEmulatorAccountName, path)
|
||||
}
|
||||
|
||||
u.Path = path
|
||||
|
@ -162,6 +221,12 @@ func (c Client) GetQueueService() QueueServiceClient {
|
|||
return QueueServiceClient{c}
|
||||
}
|
||||
|
||||
// GetTableService returns a TableServiceClient which can operate on the table
|
||||
// service of the storage account.
|
||||
func (c Client) GetTableService() TableServiceClient {
|
||||
return TableServiceClient{c}
|
||||
}
|
||||
|
||||
// GetFileService returns a FileServiceClient which can operate on the file
|
||||
// service of the storage account.
|
||||
func (c Client) GetFileService() FileServiceClient {
|
||||
|
@ -170,7 +235,7 @@ func (c Client) GetFileService() FileServiceClient {
|
|||
|
||||
func (c Client) createAuthorizationHeader(canonicalizedString string) string {
|
||||
signature := c.computeHmac256(canonicalizedString)
|
||||
return fmt.Sprintf("%s %s:%s", "SharedKey", c.accountName, signature)
|
||||
return fmt.Sprintf("%s %s:%s", "SharedKey", c.getCanonicalizedAccountName(), signature)
|
||||
}
|
||||
|
||||
func (c Client) getAuthorizationHeader(verb, url string, headers map[string]string) (string, error) {
|
||||
|
@ -190,6 +255,12 @@ func (c Client) getStandardHeaders() map[string]string {
|
|||
}
|
||||
}
|
||||
|
||||
func (c Client) getCanonicalizedAccountName() string {
|
||||
// since we may be trying to access a secondary storage account, we need to
|
||||
// remove the -secondary part of the storage name
|
||||
return strings.TrimSuffix(c.accountName, "-secondary")
|
||||
}
|
||||
|
||||
func (c Client) buildCanonicalizedHeader(headers map[string]string) string {
|
||||
cm := make(map[string]string)
|
||||
|
||||
|
@ -224,6 +295,22 @@ func (c Client) buildCanonicalizedHeader(headers map[string]string) string {
|
|||
return ch
|
||||
}
|
||||
|
||||
func (c Client) buildCanonicalizedResourceTable(uri string) (string, error) {
|
||||
errMsg := "buildCanonicalizedResourceTable error: %s"
|
||||
u, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf(errMsg, err.Error())
|
||||
}
|
||||
|
||||
cr := "/" + c.getCanonicalizedAccountName()
|
||||
|
||||
if len(u.Path) > 0 {
|
||||
cr += u.Path
|
||||
}
|
||||
|
||||
return cr, nil
|
||||
}
|
||||
|
||||
func (c Client) buildCanonicalizedResource(uri string) (string, error) {
|
||||
errMsg := "buildCanonicalizedResource error: %s"
|
||||
u, err := url.Parse(uri)
|
||||
|
@ -231,9 +318,13 @@ func (c Client) buildCanonicalizedResource(uri string) (string, error) {
|
|||
return "", fmt.Errorf(errMsg, err.Error())
|
||||
}
|
||||
|
||||
cr := "/" + c.accountName
|
||||
cr := "/" + c.getCanonicalizedAccountName()
|
||||
|
||||
if len(u.Path) > 0 {
|
||||
cr += u.Path
|
||||
// Any portion of the CanonicalizedResource string that is derived from
|
||||
// the resource's URI should be encoded exactly as it is in the URI.
|
||||
// -- https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx
|
||||
cr += u.EscapedPath()
|
||||
}
|
||||
|
||||
params, err := url.ParseQuery(u.RawQuery)
|
||||
|
@ -262,6 +353,7 @@ func (c Client) buildCanonicalizedResource(uri string) (string, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cr, nil
|
||||
}
|
||||
|
||||
|
@ -295,7 +387,6 @@ func (c Client) exec(verb, url string, headers map[string]string, body io.Reader
|
|||
return nil, err
|
||||
}
|
||||
headers["Authorization"] = authHeader
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -318,7 +409,11 @@ func (c Client) exec(verb, url string, headers map[string]string, body io.Reader
|
|||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
httpClient := http.Client{}
|
||||
|
||||
httpClient := c.HTTPClient
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
}
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -356,6 +451,70 @@ func (c Client) exec(verb, url string, headers map[string]string, body io.Reader
|
|||
body: resp.Body}, nil
|
||||
}
|
||||
|
||||
func (c Client) execInternalJSON(verb, url string, headers map[string]string, body io.Reader) (*odataResponse, error) {
|
||||
req, err := http.NewRequest(verb, url, body)
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
httpClient := c.HTTPClient
|
||||
if httpClient == nil {
|
||||
httpClient = http.DefaultClient
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respToRet := &odataResponse{}
|
||||
respToRet.body = resp.Body
|
||||
respToRet.statusCode = resp.StatusCode
|
||||
respToRet.headers = resp.Header
|
||||
|
||||
statusCode := resp.StatusCode
|
||||
if statusCode >= 400 && statusCode <= 505 {
|
||||
var respBody []byte
|
||||
respBody, err = readResponseBody(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respBody) == 0 {
|
||||
// no error in response body
|
||||
err = fmt.Errorf("storage: service returned without a response body (%d)", resp.StatusCode)
|
||||
return respToRet, err
|
||||
}
|
||||
// try unmarshal as odata.error json
|
||||
err = json.Unmarshal(respBody, &respToRet.odata)
|
||||
return respToRet, err
|
||||
}
|
||||
|
||||
return respToRet, nil
|
||||
}
|
||||
|
||||
func (c Client) createSharedKeyLite(url string, headers map[string]string) (string, error) {
|
||||
can, err := c.buildCanonicalizedResourceTable(url)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
strToSign := headers["x-ms-date"] + "\n" + can
|
||||
|
||||
hmac := c.computeHmac256(strToSign)
|
||||
return fmt.Sprintf("SharedKeyLite %s:%s", c.accountName, hmac), nil
|
||||
}
|
||||
|
||||
func (c Client) execTable(verb, url string, headers map[string]string, body io.Reader) (*odataResponse, error) {
|
||||
var err error
|
||||
headers["Authorization"], err = c.createSharedKeyLite(url, headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.execInternalJSON(verb, url, headers, body)
|
||||
}
|
||||
|
||||
func readResponseBody(resp *http.Response) ([]byte, error) {
|
||||
defer resp.Body.Close()
|
||||
out, err := ioutil.ReadAll(resp.Body)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue