aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/Azure/azure-storage-go/fileserviceclient.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/Azure/azure-storage-go/fileserviceclient.go')
-rw-r--r--vendor/github.com/Azure/azure-storage-go/fileserviceclient.go375
1 files changed, 375 insertions, 0 deletions
diff --git a/vendor/github.com/Azure/azure-storage-go/fileserviceclient.go b/vendor/github.com/Azure/azure-storage-go/fileserviceclient.go
new file mode 100644
index 000000000..d68bd7f64
--- /dev/null
+++ b/vendor/github.com/Azure/azure-storage-go/fileserviceclient.go
@@ -0,0 +1,375 @@
+package storage
+
+import (
+ "encoding/xml"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+// FileServiceClient contains operations for Microsoft Azure File Service.
+type FileServiceClient struct {
+ client Client
+ auth authentication
+}
+
+// ListSharesParameters defines the set of customizable parameters to make a
+// List Shares call.
+//
+// See https://msdn.microsoft.com/en-us/library/azure/dn167009.aspx
+type ListSharesParameters struct {
+ Prefix string
+ Marker string
+ Include string
+ MaxResults uint
+ Timeout uint
+}
+
+// ShareListResponse contains the response fields from
+// ListShares call.
+//
+// See https://msdn.microsoft.com/en-us/library/azure/dn167009.aspx
+type ShareListResponse struct {
+ XMLName xml.Name `xml:"EnumerationResults"`
+ Xmlns string `xml:"xmlns,attr"`
+ Prefix string `xml:"Prefix"`
+ Marker string `xml:"Marker"`
+ NextMarker string `xml:"NextMarker"`
+ MaxResults int64 `xml:"MaxResults"`
+ Shares []Share `xml:"Shares>Share"`
+}
+
+type compType string
+
+const (
+ compNone compType = ""
+ compList compType = "list"
+ compMetadata compType = "metadata"
+ compProperties compType = "properties"
+ compRangeList compType = "rangelist"
+)
+
+func (ct compType) String() string {
+ return string(ct)
+}
+
+type resourceType string
+
+const (
+ resourceDirectory resourceType = "directory"
+ resourceFile resourceType = ""
+ resourceShare resourceType = "share"
+)
+
+func (rt resourceType) String() string {
+ return string(rt)
+}
+
+func (p ListSharesParameters) getParameters() url.Values {
+ out := url.Values{}
+
+ if p.Prefix != "" {
+ out.Set("prefix", p.Prefix)
+ }
+ if p.Marker != "" {
+ out.Set("marker", p.Marker)
+ }
+ if p.Include != "" {
+ out.Set("include", p.Include)
+ }
+ if p.MaxResults != 0 {
+ out.Set("maxresults", fmt.Sprintf("%v", p.MaxResults))
+ }
+ if p.Timeout != 0 {
+ out.Set("timeout", fmt.Sprintf("%v", p.Timeout))
+ }
+
+ return out
+}
+
+func (p ListDirsAndFilesParameters) getParameters() url.Values {
+ out := url.Values{}
+
+ if p.Marker != "" {
+ out.Set("marker", p.Marker)
+ }
+ if p.MaxResults != 0 {
+ out.Set("maxresults", fmt.Sprintf("%v", p.MaxResults))
+ }
+ if p.Timeout != 0 {
+ out.Set("timeout", fmt.Sprintf("%v", p.Timeout))
+ }
+
+ return out
+}
+
+// returns url.Values for the specified types
+func getURLInitValues(comp compType, res resourceType) url.Values {
+ values := url.Values{}
+ if comp != compNone {
+ values.Set("comp", comp.String())
+ }
+ if res != resourceFile {
+ values.Set("restype", res.String())
+ }
+ return values
+}
+
+// GetShareReference returns a Share object for the specified share name.
+func (f FileServiceClient) GetShareReference(name string) Share {
+ return Share{
+ fsc: &f,
+ Name: name,
+ Properties: ShareProperties{
+ Quota: -1,
+ },
+ }
+}
+
+// ListShares returns the list of shares in a storage account along with
+// pagination token and other response details.
+//
+// See https://msdn.microsoft.com/en-us/library/azure/dd179352.aspx
+func (f FileServiceClient) ListShares(params ListSharesParameters) (*ShareListResponse, error) {
+ q := mergeParams(params.getParameters(), url.Values{"comp": {"list"}})
+
+ var out ShareListResponse
+ resp, err := f.listContent("", q, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.body.Close()
+ err = xmlUnmarshal(resp.body, &out)
+
+ // assign our client to the newly created Share objects
+ for i := range out.Shares {
+ out.Shares[i].fsc = &f
+ }
+ return &out, err
+}
+
+// GetServiceProperties gets the properties of your storage account's file service.
+// File service does not support logging
+// See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-file-service-properties
+func (f *FileServiceClient) GetServiceProperties() (*ServiceProperties, error) {
+ return f.client.getServiceProperties(fileServiceName, f.auth)
+}
+
+// SetServiceProperties sets the properties of your storage account's file service.
+// File service does not support logging
+// See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-file-service-properties
+func (f *FileServiceClient) SetServiceProperties(props ServiceProperties) error {
+ return f.client.setServiceProperties(props, fileServiceName, f.auth)
+}
+
+// retrieves directory or share content
+func (f FileServiceClient) listContent(path string, params url.Values, extraHeaders map[string]string) (*storageResponse, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return nil, err
+ }
+
+ uri := f.client.getEndpoint(fileServiceName, path, params)
+ extraHeaders = f.client.protectUserAgent(extraHeaders)
+ headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
+
+ resp, err := f.client.exec(http.MethodGet, uri, headers, nil, f.auth)
+ if err != nil {
+ return nil, err
+ }
+
+ if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
+ readAndCloseBody(resp.body)
+ return nil, err
+ }
+
+ return resp, nil
+}
+
+// returns true if the specified resource exists
+func (f FileServiceClient) resourceExists(path string, res resourceType) (bool, http.Header, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return false, nil, err
+ }
+
+ uri := f.client.getEndpoint(fileServiceName, path, getURLInitValues(compNone, res))
+ headers := f.client.getStandardHeaders()
+
+ resp, err := f.client.exec(http.MethodHead, uri, headers, nil, f.auth)
+ if resp != nil {
+ defer readAndCloseBody(resp.body)
+ if resp.statusCode == http.StatusOK || resp.statusCode == http.StatusNotFound {
+ return resp.statusCode == http.StatusOK, resp.headers, nil
+ }
+ }
+ return false, nil, err
+}
+
+// creates a resource depending on the specified resource type
+func (f FileServiceClient) createResource(path string, res resourceType, urlParams url.Values, extraHeaders map[string]string, expectedResponseCodes []int) (http.Header, error) {
+ resp, err := f.createResourceNoClose(path, res, urlParams, extraHeaders)
+ if err != nil {
+ return nil, err
+ }
+ defer readAndCloseBody(resp.body)
+ return resp.headers, checkRespCode(resp.statusCode, expectedResponseCodes)
+}
+
+// creates a resource depending on the specified resource type, doesn't close the response body
+func (f FileServiceClient) createResourceNoClose(path string, res resourceType, urlParams url.Values, extraHeaders map[string]string) (*storageResponse, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return nil, err
+ }
+
+ values := getURLInitValues(compNone, res)
+ combinedParams := mergeParams(values, urlParams)
+ uri := f.client.getEndpoint(fileServiceName, path, combinedParams)
+ extraHeaders = f.client.protectUserAgent(extraHeaders)
+ headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
+
+ return f.client.exec(http.MethodPut, uri, headers, nil, f.auth)
+}
+
+// returns HTTP header data for the specified directory or share
+func (f FileServiceClient) getResourceHeaders(path string, comp compType, res resourceType, verb string) (http.Header, error) {
+ resp, err := f.getResourceNoClose(path, comp, res, verb, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer readAndCloseBody(resp.body)
+
+ if err = checkRespCode(resp.statusCode, []int{http.StatusOK}); err != nil {
+ return nil, err
+ }
+
+ return resp.headers, nil
+}
+
+// gets the specified resource, doesn't close the response body
+func (f FileServiceClient) getResourceNoClose(path string, comp compType, res resourceType, verb string, extraHeaders map[string]string) (*storageResponse, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return nil, err
+ }
+
+ params := getURLInitValues(comp, res)
+ uri := f.client.getEndpoint(fileServiceName, path, params)
+ extraHeaders = f.client.protectUserAgent(extraHeaders)
+ headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
+
+ return f.client.exec(verb, uri, headers, nil, f.auth)
+}
+
+// deletes the resource and returns the response
+func (f FileServiceClient) deleteResource(path string, res resourceType) error {
+ resp, err := f.deleteResourceNoClose(path, res)
+ if err != nil {
+ return err
+ }
+ defer readAndCloseBody(resp.body)
+ return checkRespCode(resp.statusCode, []int{http.StatusAccepted})
+}
+
+// deletes the resource and returns the response, doesn't close the response body
+func (f FileServiceClient) deleteResourceNoClose(path string, res resourceType) (*storageResponse, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return nil, err
+ }
+
+ values := getURLInitValues(compNone, res)
+ uri := f.client.getEndpoint(fileServiceName, path, values)
+ return f.client.exec(http.MethodDelete, uri, f.client.getStandardHeaders(), nil, f.auth)
+}
+
+// merges metadata into extraHeaders and returns extraHeaders
+func mergeMDIntoExtraHeaders(metadata, extraHeaders map[string]string) map[string]string {
+ if metadata == nil && extraHeaders == nil {
+ return nil
+ }
+ if extraHeaders == nil {
+ extraHeaders = make(map[string]string)
+ }
+ for k, v := range metadata {
+ extraHeaders[userDefinedMetadataHeaderPrefix+k] = v
+ }
+ return extraHeaders
+}
+
+// merges extraHeaders into headers and returns headers
+func mergeHeaders(headers, extraHeaders map[string]string) map[string]string {
+ for k, v := range extraHeaders {
+ headers[k] = v
+ }
+ return headers
+}
+
+// sets extra header data for the specified resource
+func (f FileServiceClient) setResourceHeaders(path string, comp compType, res resourceType, extraHeaders map[string]string) (http.Header, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return nil, err
+ }
+
+ params := getURLInitValues(comp, res)
+ uri := f.client.getEndpoint(fileServiceName, path, params)
+ extraHeaders = f.client.protectUserAgent(extraHeaders)
+ headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
+
+ resp, err := f.client.exec(http.MethodPut, uri, headers, nil, f.auth)
+ if err != nil {
+ return nil, err
+ }
+ defer readAndCloseBody(resp.body)
+
+ return resp.headers, checkRespCode(resp.statusCode, []int{http.StatusOK})
+}
+
+// gets metadata for the specified resource
+func (f FileServiceClient) getMetadata(path string, res resourceType) (map[string]string, error) {
+ if err := f.checkForStorageEmulator(); err != nil {
+ return nil, err
+ }
+
+ headers, err := f.getResourceHeaders(path, compMetadata, res, http.MethodGet)
+ if err != nil {
+ return nil, err
+ }
+
+ return getMetadataFromHeaders(headers), nil
+}
+
+// returns a map of custom metadata values from the specified HTTP header
+func getMetadataFromHeaders(header http.Header) map[string]string {
+ metadata := make(map[string]string)
+ for k, v := range header {
+ // Can't trust CanonicalHeaderKey() to munge case
+ // reliably. "_" is allowed in identifiers:
+ // https://msdn.microsoft.com/en-us/library/azure/dd179414.aspx
+ // https://msdn.microsoft.com/library/aa664670(VS.71).aspx
+ // http://tools.ietf.org/html/rfc7230#section-3.2
+ // ...but "_" is considered invalid by
+ // CanonicalMIMEHeaderKey in
+ // https://golang.org/src/net/textproto/reader.go?s=14615:14659#L542
+ // so k can be "X-Ms-Meta-Foo" or "x-ms-meta-foo_bar".
+ k = strings.ToLower(k)
+ if len(v) == 0 || !strings.HasPrefix(k, strings.ToLower(userDefinedMetadataHeaderPrefix)) {
+ continue
+ }
+ // metadata["foo"] = content of the last X-Ms-Meta-Foo header
+ k = k[len(userDefinedMetadataHeaderPrefix):]
+ metadata[k] = v[len(v)-1]
+ }
+
+ if len(metadata) == 0 {
+ return nil
+ }
+
+ return metadata
+}
+
+//checkForStorageEmulator determines if the client is setup for use with
+//Azure Storage Emulator, and returns a relevant error
+func (f FileServiceClient) checkForStorageEmulator() error {
+ if f.client.accountName == StorageEmulatorAccountName {
+ return fmt.Errorf("Error: File service is not currently supported by Azure Storage Emulator")
+ }
+ return nil
+}