...

Source file src/github.com/Azure/azure-sdk-for-go/storage/fileserviceclient.go

Documentation: github.com/Azure/azure-sdk-for-go/storage

     1  package storage
     2  
     3  // Copyright (c) Microsoft Corporation. All rights reserved.
     4  // Licensed under the MIT License. See License.txt in the project root for license information.
     5  
     6  import (
     7  	"encoding/xml"
     8  	"fmt"
     9  	"net/http"
    10  	"net/url"
    11  	"strconv"
    12  )
    13  
    14  // FileServiceClient contains operations for Microsoft Azure File Service.
    15  type FileServiceClient struct {
    16  	client Client
    17  	auth   authentication
    18  }
    19  
    20  // ListSharesParameters defines the set of customizable parameters to make a
    21  // List Shares call.
    22  //
    23  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Shares
    24  type ListSharesParameters struct {
    25  	Prefix     string
    26  	Marker     string
    27  	Include    string
    28  	MaxResults uint
    29  	Timeout    uint
    30  }
    31  
    32  // ShareListResponse contains the response fields from
    33  // ListShares call.
    34  //
    35  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/List-Shares
    36  type ShareListResponse struct {
    37  	XMLName    xml.Name `xml:"EnumerationResults"`
    38  	Xmlns      string   `xml:"xmlns,attr"`
    39  	Prefix     string   `xml:"Prefix"`
    40  	Marker     string   `xml:"Marker"`
    41  	NextMarker string   `xml:"NextMarker"`
    42  	MaxResults int64    `xml:"MaxResults"`
    43  	Shares     []Share  `xml:"Shares>Share"`
    44  }
    45  
    46  type compType string
    47  
    48  const (
    49  	compNone       compType = ""
    50  	compList       compType = "list"
    51  	compMetadata   compType = "metadata"
    52  	compProperties compType = "properties"
    53  	compRangeList  compType = "rangelist"
    54  )
    55  
    56  func (ct compType) String() string {
    57  	return string(ct)
    58  }
    59  
    60  type resourceType string
    61  
    62  const (
    63  	resourceDirectory resourceType = "directory"
    64  	resourceFile      resourceType = ""
    65  	resourceShare     resourceType = "share"
    66  )
    67  
    68  func (rt resourceType) String() string {
    69  	return string(rt)
    70  }
    71  
    72  func (p ListSharesParameters) getParameters() url.Values {
    73  	out := url.Values{}
    74  
    75  	if p.Prefix != "" {
    76  		out.Set("prefix", p.Prefix)
    77  	}
    78  	if p.Marker != "" {
    79  		out.Set("marker", p.Marker)
    80  	}
    81  	if p.Include != "" {
    82  		out.Set("include", p.Include)
    83  	}
    84  	if p.MaxResults != 0 {
    85  		out.Set("maxresults", strconv.FormatUint(uint64(p.MaxResults), 10))
    86  	}
    87  	if p.Timeout != 0 {
    88  		out.Set("timeout", strconv.FormatUint(uint64(p.Timeout), 10))
    89  	}
    90  
    91  	return out
    92  }
    93  
    94  func (p ListDirsAndFilesParameters) getParameters() url.Values {
    95  	out := url.Values{}
    96  
    97  	if p.Prefix != "" {
    98  		out.Set("prefix", p.Prefix)
    99  	}
   100  	if p.Marker != "" {
   101  		out.Set("marker", p.Marker)
   102  	}
   103  	if p.MaxResults != 0 {
   104  		out.Set("maxresults", strconv.FormatUint(uint64(p.MaxResults), 10))
   105  	}
   106  	out = addTimeout(out, p.Timeout)
   107  
   108  	return out
   109  }
   110  
   111  // returns url.Values for the specified types
   112  func getURLInitValues(comp compType, res resourceType) url.Values {
   113  	values := url.Values{}
   114  	if comp != compNone {
   115  		values.Set("comp", comp.String())
   116  	}
   117  	if res != resourceFile {
   118  		values.Set("restype", res.String())
   119  	}
   120  	return values
   121  }
   122  
   123  // GetShareReference returns a Share object for the specified share name.
   124  func (f *FileServiceClient) GetShareReference(name string) *Share {
   125  	return &Share{
   126  		fsc:  f,
   127  		Name: name,
   128  		Properties: ShareProperties{
   129  			Quota: -1,
   130  		},
   131  	}
   132  }
   133  
   134  // ListShares returns the list of shares in a storage account along with
   135  // pagination token and other response details.
   136  //
   137  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/list-shares
   138  func (f FileServiceClient) ListShares(params ListSharesParameters) (*ShareListResponse, error) {
   139  	q := mergeParams(params.getParameters(), url.Values{"comp": {"list"}})
   140  
   141  	var out ShareListResponse
   142  	resp, err := f.listContent("", q, nil)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	defer resp.Body.Close()
   147  	err = xmlUnmarshal(resp.Body, &out)
   148  
   149  	// assign our client to the newly created Share objects
   150  	for i := range out.Shares {
   151  		out.Shares[i].fsc = &f
   152  	}
   153  	return &out, err
   154  }
   155  
   156  // GetServiceProperties gets the properties of your storage account's file service.
   157  // File service does not support logging
   158  // See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-file-service-properties
   159  func (f *FileServiceClient) GetServiceProperties() (*ServiceProperties, error) {
   160  	return f.client.getServiceProperties(fileServiceName, f.auth)
   161  }
   162  
   163  // SetServiceProperties sets the properties of your storage account's file service.
   164  // File service does not support logging
   165  // See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-file-service-properties
   166  func (f *FileServiceClient) SetServiceProperties(props ServiceProperties) error {
   167  	return f.client.setServiceProperties(props, fileServiceName, f.auth)
   168  }
   169  
   170  // retrieves directory or share content
   171  func (f FileServiceClient) listContent(path string, params url.Values, extraHeaders map[string]string) (*http.Response, error) {
   172  	if err := f.checkForStorageEmulator(); err != nil {
   173  		return nil, err
   174  	}
   175  
   176  	uri := f.client.getEndpoint(fileServiceName, path, params)
   177  	extraHeaders = f.client.protectUserAgent(extraHeaders)
   178  	headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
   179  
   180  	resp, err := f.client.exec(http.MethodGet, uri, headers, nil, f.auth)
   181  	if err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
   186  		drainRespBody(resp)
   187  		return nil, err
   188  	}
   189  
   190  	return resp, nil
   191  }
   192  
   193  // returns true if the specified resource exists
   194  func (f FileServiceClient) resourceExists(path string, res resourceType) (bool, http.Header, error) {
   195  	if err := f.checkForStorageEmulator(); err != nil {
   196  		return false, nil, err
   197  	}
   198  
   199  	uri := f.client.getEndpoint(fileServiceName, path, getURLInitValues(compNone, res))
   200  	headers := f.client.getStandardHeaders()
   201  
   202  	resp, err := f.client.exec(http.MethodHead, uri, headers, nil, f.auth)
   203  	if resp != nil {
   204  		defer drainRespBody(resp)
   205  		if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNotFound {
   206  			return resp.StatusCode == http.StatusOK, resp.Header, nil
   207  		}
   208  	}
   209  	return false, nil, err
   210  }
   211  
   212  // creates a resource depending on the specified resource type
   213  func (f FileServiceClient) createResource(path string, res resourceType, urlParams url.Values, extraHeaders map[string]string, expectedResponseCodes []int) (http.Header, error) {
   214  	resp, err := f.createResourceNoClose(path, res, urlParams, extraHeaders)
   215  	if err != nil {
   216  		return nil, err
   217  	}
   218  	defer drainRespBody(resp)
   219  	return resp.Header, checkRespCode(resp, expectedResponseCodes)
   220  }
   221  
   222  // creates a resource depending on the specified resource type, doesn't close the response body
   223  func (f FileServiceClient) createResourceNoClose(path string, res resourceType, urlParams url.Values, extraHeaders map[string]string) (*http.Response, error) {
   224  	if err := f.checkForStorageEmulator(); err != nil {
   225  		return nil, err
   226  	}
   227  
   228  	values := getURLInitValues(compNone, res)
   229  	combinedParams := mergeParams(values, urlParams)
   230  	uri := f.client.getEndpoint(fileServiceName, path, combinedParams)
   231  	extraHeaders = f.client.protectUserAgent(extraHeaders)
   232  	headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
   233  
   234  	return f.client.exec(http.MethodPut, uri, headers, nil, f.auth)
   235  }
   236  
   237  // returns HTTP header data for the specified directory or share
   238  func (f FileServiceClient) getResourceHeaders(path string, comp compType, res resourceType, params url.Values, verb string) (http.Header, error) {
   239  	resp, err := f.getResourceNoClose(path, comp, res, params, verb, nil)
   240  	if err != nil {
   241  		return nil, err
   242  	}
   243  	defer drainRespBody(resp)
   244  
   245  	if err = checkRespCode(resp, []int{http.StatusOK}); err != nil {
   246  		return nil, err
   247  	}
   248  
   249  	return resp.Header, nil
   250  }
   251  
   252  // gets the specified resource, doesn't close the response body
   253  func (f FileServiceClient) getResourceNoClose(path string, comp compType, res resourceType, params url.Values, verb string, extraHeaders map[string]string) (*http.Response, error) {
   254  	if err := f.checkForStorageEmulator(); err != nil {
   255  		return nil, err
   256  	}
   257  
   258  	params = mergeParams(params, getURLInitValues(comp, res))
   259  	uri := f.client.getEndpoint(fileServiceName, path, params)
   260  	headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
   261  
   262  	return f.client.exec(verb, uri, headers, nil, f.auth)
   263  }
   264  
   265  // deletes the resource and returns the response
   266  func (f FileServiceClient) deleteResource(path string, res resourceType, options *FileRequestOptions) error {
   267  	resp, err := f.deleteResourceNoClose(path, res, options)
   268  	if err != nil {
   269  		return err
   270  	}
   271  	defer drainRespBody(resp)
   272  	return checkRespCode(resp, []int{http.StatusAccepted})
   273  }
   274  
   275  // deletes the resource and returns the response, doesn't close the response body
   276  func (f FileServiceClient) deleteResourceNoClose(path string, res resourceType, options *FileRequestOptions) (*http.Response, error) {
   277  	if err := f.checkForStorageEmulator(); err != nil {
   278  		return nil, err
   279  	}
   280  
   281  	values := mergeParams(getURLInitValues(compNone, res), prepareOptions(options))
   282  	uri := f.client.getEndpoint(fileServiceName, path, values)
   283  	return f.client.exec(http.MethodDelete, uri, f.client.getStandardHeaders(), nil, f.auth)
   284  }
   285  
   286  // merges metadata into extraHeaders and returns extraHeaders
   287  func mergeMDIntoExtraHeaders(metadata, extraHeaders map[string]string) map[string]string {
   288  	if metadata == nil && extraHeaders == nil {
   289  		return nil
   290  	}
   291  	if extraHeaders == nil {
   292  		extraHeaders = make(map[string]string)
   293  	}
   294  	for k, v := range metadata {
   295  		extraHeaders[userDefinedMetadataHeaderPrefix+k] = v
   296  	}
   297  	return extraHeaders
   298  }
   299  
   300  // sets extra header data for the specified resource
   301  func (f FileServiceClient) setResourceHeaders(path string, comp compType, res resourceType, extraHeaders map[string]string, options *FileRequestOptions) (http.Header, error) {
   302  	if err := f.checkForStorageEmulator(); err != nil {
   303  		return nil, err
   304  	}
   305  
   306  	params := mergeParams(getURLInitValues(comp, res), prepareOptions(options))
   307  	uri := f.client.getEndpoint(fileServiceName, path, params)
   308  	extraHeaders = f.client.protectUserAgent(extraHeaders)
   309  	headers := mergeHeaders(f.client.getStandardHeaders(), extraHeaders)
   310  
   311  	resp, err := f.client.exec(http.MethodPut, uri, headers, nil, f.auth)
   312  	if err != nil {
   313  		return nil, err
   314  	}
   315  	defer drainRespBody(resp)
   316  
   317  	return resp.Header, checkRespCode(resp, []int{http.StatusOK})
   318  }
   319  
   320  //checkForStorageEmulator determines if the client is setup for use with
   321  //Azure Storage Emulator, and returns a relevant error
   322  func (f FileServiceClient) checkForStorageEmulator() error {
   323  	if f.client.accountName == StorageEmulatorAccountName {
   324  		return fmt.Errorf("Error: File service is not currently supported by Azure Storage Emulator")
   325  	}
   326  	return nil
   327  }
   328  

View as plain text