123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- package storage
- // Copyright 2017 Microsoft Corporation
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- import (
- "fmt"
- "net/http"
- "net/url"
- "strconv"
- )
- // Share represents an Azure file share.
- type Share struct {
- fsc *FileServiceClient
- Name string `xml:"Name"`
- Properties ShareProperties `xml:"Properties"`
- Metadata map[string]string
- }
- // ShareProperties contains various properties of a share.
- type ShareProperties struct {
- LastModified string `xml:"Last-Modified"`
- Etag string `xml:"Etag"`
- Quota int `xml:"Quota"`
- }
- // builds the complete path for this share object.
- func (s *Share) buildPath() string {
- return fmt.Sprintf("/%s", s.Name)
- }
- // Create this share under the associated account.
- // If a share with the same name already exists, the operation fails.
- //
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Create-Share
- func (s *Share) Create(options *FileRequestOptions) error {
- extraheaders := map[string]string{}
- if s.Properties.Quota > 0 {
- extraheaders["x-ms-share-quota"] = strconv.Itoa(s.Properties.Quota)
- }
- params := prepareOptions(options)
- headers, err := s.fsc.createResource(s.buildPath(), resourceShare, params, mergeMDIntoExtraHeaders(s.Metadata, extraheaders), []int{http.StatusCreated})
- if err != nil {
- return err
- }
- s.updateEtagAndLastModified(headers)
- return nil
- }
- // CreateIfNotExists creates this share under the associated account if
- // it does not exist. Returns true if the share is newly created or false if
- // the share already exists.
- //
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Create-Share
- func (s *Share) CreateIfNotExists(options *FileRequestOptions) (bool, error) {
- extraheaders := map[string]string{}
- if s.Properties.Quota > 0 {
- extraheaders["x-ms-share-quota"] = strconv.Itoa(s.Properties.Quota)
- }
- params := prepareOptions(options)
- resp, err := s.fsc.createResourceNoClose(s.buildPath(), resourceShare, params, extraheaders)
- if resp != nil {
- defer drainRespBody(resp)
- if resp.StatusCode == http.StatusCreated || resp.StatusCode == http.StatusConflict {
- if resp.StatusCode == http.StatusCreated {
- s.updateEtagAndLastModified(resp.Header)
- return true, nil
- }
- return false, s.FetchAttributes(nil)
- }
- }
- return false, err
- }
- // Delete marks this share for deletion. The share along with any files
- // and directories contained within it are later deleted during garbage
- // collection. If the share does not exist the operation fails
- //
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Delete-Share
- func (s *Share) Delete(options *FileRequestOptions) error {
- return s.fsc.deleteResource(s.buildPath(), resourceShare, options)
- }
- // DeleteIfExists operation marks this share for deletion if it exists.
- //
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Delete-Share
- func (s *Share) DeleteIfExists(options *FileRequestOptions) (bool, error) {
- resp, err := s.fsc.deleteResourceNoClose(s.buildPath(), resourceShare, options)
- if resp != nil {
- defer drainRespBody(resp)
- if resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusNotFound {
- return resp.StatusCode == http.StatusAccepted, nil
- }
- }
- return false, err
- }
- // Exists returns true if this share already exists
- // on the storage account, otherwise returns false.
- func (s *Share) Exists() (bool, error) {
- exists, headers, err := s.fsc.resourceExists(s.buildPath(), resourceShare)
- if exists {
- s.updateEtagAndLastModified(headers)
- s.updateQuota(headers)
- }
- return exists, err
- }
- // FetchAttributes retrieves metadata and properties for this share.
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-share-properties
- func (s *Share) FetchAttributes(options *FileRequestOptions) error {
- params := prepareOptions(options)
- headers, err := s.fsc.getResourceHeaders(s.buildPath(), compNone, resourceShare, params, http.MethodHead)
- if err != nil {
- return err
- }
- s.updateEtagAndLastModified(headers)
- s.updateQuota(headers)
- s.Metadata = getMetadataFromHeaders(headers)
- return nil
- }
- // GetRootDirectoryReference returns a Directory object at the root of this share.
- func (s *Share) GetRootDirectoryReference() *Directory {
- return &Directory{
- fsc: s.fsc,
- share: s,
- }
- }
- // ServiceClient returns the FileServiceClient associated with this share.
- func (s *Share) ServiceClient() *FileServiceClient {
- return s.fsc
- }
- // SetMetadata replaces the metadata for this share.
- //
- // Some keys may be converted to Camel-Case before sending. All keys
- // are returned in lower case by GetShareMetadata. HTTP header names
- // are case-insensitive so case munging should not matter to other
- // applications either.
- //
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-share-metadata
- func (s *Share) SetMetadata(options *FileRequestOptions) error {
- headers, err := s.fsc.setResourceHeaders(s.buildPath(), compMetadata, resourceShare, mergeMDIntoExtraHeaders(s.Metadata, nil), options)
- if err != nil {
- return err
- }
- s.updateEtagAndLastModified(headers)
- return nil
- }
- // SetProperties sets system properties for this share.
- //
- // Some keys may be converted to Camel-Case before sending. All keys
- // are returned in lower case by SetShareProperties. HTTP header names
- // are case-insensitive so case munging should not matter to other
- // applications either.
- //
- // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Set-Share-Properties
- func (s *Share) SetProperties(options *FileRequestOptions) error {
- extraheaders := map[string]string{}
- if s.Properties.Quota > 0 {
- if s.Properties.Quota > 5120 {
- return fmt.Errorf("invalid value %v for quota, valid values are [1, 5120]", s.Properties.Quota)
- }
- extraheaders["x-ms-share-quota"] = strconv.Itoa(s.Properties.Quota)
- }
- headers, err := s.fsc.setResourceHeaders(s.buildPath(), compProperties, resourceShare, extraheaders, options)
- if err != nil {
- return err
- }
- s.updateEtagAndLastModified(headers)
- return nil
- }
- // updates Etag and last modified date
- func (s *Share) updateEtagAndLastModified(headers http.Header) {
- s.Properties.Etag = headers.Get("Etag")
- s.Properties.LastModified = headers.Get("Last-Modified")
- }
- // updates quota value
- func (s *Share) updateQuota(headers http.Header) {
- quota, err := strconv.Atoi(headers.Get("x-ms-share-quota"))
- if err == nil {
- s.Properties.Quota = quota
- }
- }
- // URL gets the canonical URL to this share. This method does not create a publicly accessible
- // URL if the share is private and this method does not check if the share exists.
- func (s *Share) URL() string {
- return s.fsc.client.getEndpoint(fileServiceName, s.buildPath(), url.Values{})
- }
|