...

Source file src/github.com/Azure/azure-sdk-for-go/storage/leaseblob.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  	"errors"
     8  	"net/http"
     9  	"net/url"
    10  	"strconv"
    11  	"time"
    12  )
    13  
    14  // lease constants.
    15  const (
    16  	leaseHeaderPrefix = "x-ms-lease-"
    17  	headerLeaseID     = "x-ms-lease-id"
    18  	leaseAction       = "x-ms-lease-action"
    19  	leaseBreakPeriod  = "x-ms-lease-break-period"
    20  	leaseDuration     = "x-ms-lease-duration"
    21  	leaseProposedID   = "x-ms-proposed-lease-id"
    22  	leaseTime         = "x-ms-lease-time"
    23  
    24  	acquireLease = "acquire"
    25  	renewLease   = "renew"
    26  	changeLease  = "change"
    27  	releaseLease = "release"
    28  	breakLease   = "break"
    29  )
    30  
    31  // leasePut is common PUT code for the various acquire/release/break etc functions.
    32  func (b *Blob) leaseCommonPut(headers map[string]string, expectedStatus int, options *LeaseOptions) (http.Header, error) {
    33  	params := url.Values{"comp": {"lease"}}
    34  
    35  	if options != nil {
    36  		params = addTimeout(params, options.Timeout)
    37  		headers = mergeHeaders(headers, headersFromStruct(*options))
    38  	}
    39  	uri := b.Container.bsc.client.getEndpoint(blobServiceName, b.buildPath(), params)
    40  
    41  	resp, err := b.Container.bsc.client.exec(http.MethodPut, uri, headers, nil, b.Container.bsc.auth)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	defer drainRespBody(resp)
    46  
    47  	if err := checkRespCode(resp, []int{expectedStatus}); err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	return resp.Header, nil
    52  }
    53  
    54  // LeaseOptions includes options for all operations regarding leasing blobs
    55  type LeaseOptions struct {
    56  	Timeout           uint
    57  	Origin            string     `header:"Origin"`
    58  	IfMatch           string     `header:"If-Match"`
    59  	IfNoneMatch       string     `header:"If-None-Match"`
    60  	IfModifiedSince   *time.Time `header:"If-Modified-Since"`
    61  	IfUnmodifiedSince *time.Time `header:"If-Unmodified-Since"`
    62  	RequestID         string     `header:"x-ms-client-request-id"`
    63  }
    64  
    65  // AcquireLease creates a lease for a blob
    66  // returns leaseID acquired
    67  // In API Versions starting on 2012-02-12, the minimum leaseTimeInSeconds is 15, the maximum
    68  // non-infinite leaseTimeInSeconds is 60. To specify an infinite lease, provide the value -1.
    69  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Lease-Blob
    70  func (b *Blob) AcquireLease(leaseTimeInSeconds int, proposedLeaseID string, options *LeaseOptions) (returnedLeaseID string, err error) {
    71  	headers := b.Container.bsc.client.getStandardHeaders()
    72  	headers[leaseAction] = acquireLease
    73  
    74  	if leaseTimeInSeconds == -1 {
    75  		// Do nothing, but don't trigger the following clauses.
    76  	} else if leaseTimeInSeconds > 60 || b.Container.bsc.client.apiVersion < "2012-02-12" {
    77  		leaseTimeInSeconds = 60
    78  	} else if leaseTimeInSeconds < 15 {
    79  		leaseTimeInSeconds = 15
    80  	}
    81  
    82  	headers[leaseDuration] = strconv.Itoa(leaseTimeInSeconds)
    83  
    84  	if proposedLeaseID != "" {
    85  		headers[leaseProposedID] = proposedLeaseID
    86  	}
    87  
    88  	respHeaders, err := b.leaseCommonPut(headers, http.StatusCreated, options)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  
    93  	returnedLeaseID = respHeaders.Get(http.CanonicalHeaderKey(headerLeaseID))
    94  
    95  	if returnedLeaseID != "" {
    96  		return returnedLeaseID, nil
    97  	}
    98  
    99  	return "", errors.New("LeaseID not returned")
   100  }
   101  
   102  // BreakLease breaks the lease for a blob
   103  // Returns the timeout remaining in the lease in seconds
   104  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Lease-Blob
   105  func (b *Blob) BreakLease(options *LeaseOptions) (breakTimeout int, err error) {
   106  	headers := b.Container.bsc.client.getStandardHeaders()
   107  	headers[leaseAction] = breakLease
   108  	return b.breakLeaseCommon(headers, options)
   109  }
   110  
   111  // BreakLeaseWithBreakPeriod breaks the lease for a blob
   112  // breakPeriodInSeconds is used to determine how long until new lease can be created.
   113  // Returns the timeout remaining in the lease in seconds
   114  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Lease-Blob
   115  func (b *Blob) BreakLeaseWithBreakPeriod(breakPeriodInSeconds int, options *LeaseOptions) (breakTimeout int, err error) {
   116  	headers := b.Container.bsc.client.getStandardHeaders()
   117  	headers[leaseAction] = breakLease
   118  	headers[leaseBreakPeriod] = strconv.Itoa(breakPeriodInSeconds)
   119  	return b.breakLeaseCommon(headers, options)
   120  }
   121  
   122  // breakLeaseCommon is common code for both version of BreakLease (with and without break period)
   123  func (b *Blob) breakLeaseCommon(headers map[string]string, options *LeaseOptions) (breakTimeout int, err error) {
   124  
   125  	respHeaders, err := b.leaseCommonPut(headers, http.StatusAccepted, options)
   126  	if err != nil {
   127  		return 0, err
   128  	}
   129  
   130  	breakTimeoutStr := respHeaders.Get(http.CanonicalHeaderKey(leaseTime))
   131  	if breakTimeoutStr != "" {
   132  		breakTimeout, err = strconv.Atoi(breakTimeoutStr)
   133  		if err != nil {
   134  			return 0, err
   135  		}
   136  	}
   137  
   138  	return breakTimeout, nil
   139  }
   140  
   141  // ChangeLease changes a lease ID for a blob
   142  // Returns the new LeaseID acquired
   143  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Lease-Blob
   144  func (b *Blob) ChangeLease(currentLeaseID string, proposedLeaseID string, options *LeaseOptions) (newLeaseID string, err error) {
   145  	headers := b.Container.bsc.client.getStandardHeaders()
   146  	headers[leaseAction] = changeLease
   147  	headers[headerLeaseID] = currentLeaseID
   148  	headers[leaseProposedID] = proposedLeaseID
   149  
   150  	respHeaders, err := b.leaseCommonPut(headers, http.StatusOK, options)
   151  	if err != nil {
   152  		return "", err
   153  	}
   154  
   155  	newLeaseID = respHeaders.Get(http.CanonicalHeaderKey(headerLeaseID))
   156  	if newLeaseID != "" {
   157  		return newLeaseID, nil
   158  	}
   159  
   160  	return "", errors.New("LeaseID not returned")
   161  }
   162  
   163  // ReleaseLease releases the lease for a blob
   164  // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/Lease-Blob
   165  func (b *Blob) ReleaseLease(currentLeaseID string, options *LeaseOptions) error {
   166  	headers := b.Container.bsc.client.getStandardHeaders()
   167  	headers[leaseAction] = releaseLease
   168  	headers[headerLeaseID] = currentLeaseID
   169  
   170  	_, err := b.leaseCommonPut(headers, http.StatusOK, options)
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	return nil
   176  }
   177  
   178  // RenewLease renews the lease for a blob as per https://msdn.microsoft.com/en-us/library/azure/ee691972.aspx
   179  func (b *Blob) RenewLease(currentLeaseID string, options *LeaseOptions) error {
   180  	headers := b.Container.bsc.client.getStandardHeaders()
   181  	headers[leaseAction] = renewLease
   182  	headers[headerLeaseID] = currentLeaseID
   183  
   184  	_, err := b.leaseCommonPut(headers, http.StatusOK, options)
   185  	if err != nil {
   186  		return err
   187  	}
   188  
   189  	return nil
   190  }
   191  

View as plain text