Skip to content

Commit

Permalink
Merge pull request #26 from Azure/dev
Browse files Browse the repository at this point in the history
Release 0.6.0 with UploadRangeFromURL
  • Loading branch information
zezha-msft authored Sep 27, 2019
2 parents 7eb2ce7 + 4fe785d commit 825ad79
Show file tree
Hide file tree
Showing 18 changed files with 1,841 additions and 161 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# mac specific
.DS_Store

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
7 changes: 5 additions & 2 deletions azfile/url_directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ func (d DirectoryURL) NewDirectoryURL(directoryName string) DirectoryURL {

// Create creates a new directory within a storage account.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/create-directory.
// Pass default values for SMB properties (ex: "None" for file attributes).
func (d DirectoryURL) Create(ctx context.Context, metadata Metadata) (*DirectoryCreateResponse, error) {
return d.directoryClient.Create(ctx, nil, metadata)
defaultPermissions := "inherit"
return d.directoryClient.Create(ctx, "None", "now", "now", nil, metadata,
&defaultPermissions, nil)
}

// Delete removes the specified empty directory. Note that the directory must be empty before it can be deleted..
Expand Down Expand Up @@ -140,5 +143,5 @@ func (o *ListFilesAndDirectoriesOptions) pointers() (prefix *string, maxResults
// For more information, see https://docs.microsoft.com/en-us/rest/api/storageservices/list-directories-and-files.
func (d DirectoryURL) ListFilesAndDirectoriesSegment(ctx context.Context, marker Marker, o ListFilesAndDirectoriesOptions) (*ListFilesAndDirectoriesSegmentResponse, error) {
prefix, maxResults := o.pointers()
return d.directoryClient.ListFilesAndDirectoriesSegment(ctx, prefix, nil, marker.val, maxResults, nil)
return d.directoryClient.ListFilesAndDirectoriesSegment(ctx, prefix, nil, marker.Val, maxResults, nil)
}
35 changes: 25 additions & 10 deletions azfile/url_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ func (f FileURL) WithSnapshot(shareSnapshot string) FileURL {

// Create creates a new file or replaces a file. Note that this method only initializes the file.
// For more information, see https://docs.microsoft.com/en-us/rest/api/storageservices/create-file.
// Pass default values for SMB properties (ex: "None" for file attributes).
func (f FileURL) Create(ctx context.Context, size int64, h FileHTTPHeaders, metadata Metadata) (*FileCreateResponse, error) {
return f.fileClient.Create(ctx, size, nil,
defaultPermissions := "inherit"
return f.fileClient.Create(ctx, size, "None", "now", "now", nil,
&h.ContentType, &h.ContentEncoding, &h.ContentLanguage, &h.CacheControl,
h.ContentMD5, &h.ContentDisposition, metadata)
h.ContentMD5, &h.ContentDisposition, metadata, &defaultPermissions, nil)
}

// StartCopy copies the data at the source URL to a file.
Expand All @@ -83,7 +85,7 @@ func (f FileURL) AbortCopy(ctx context.Context, copyID string) (*FileAbortCopyRe
// If count is CountToEnd (0), then data is read from specified offset to the end.
// rangeGetContentMD5 only works with partial data downloading.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/get-file.
func (f FileURL) Download(ctx context.Context, offset int64, count int64, rangeGetContentMD5 bool) (*DownloadResponse, error) {
func (f FileURL) Download(ctx context.Context, offset int64, count int64, rangeGetContentMD5 bool) (*RetryableDownloadResponse, error) {
var xRangeGetContentMD5 *bool
if rangeGetContentMD5 {
if offset == 0 && count == CountToEnd {
Expand All @@ -96,7 +98,7 @@ func (f FileURL) Download(ctx context.Context, offset int64, count int64, rangeG
return nil, err
}

return &DownloadResponse{
return &RetryableDownloadResponse{
f: f,
dr: dr,
ctx: ctx,
Expand All @@ -106,7 +108,7 @@ func (f FileURL) Download(ctx context.Context, offset int64, count int64, rangeG

// Body constructs a stream to read data from with a resilient reader option.
// A zero-value option means to get a raw stream.
func (dr *DownloadResponse) Body(o RetryReaderOptions) io.ReadCloser {
func (dr *RetryableDownloadResponse) Body(o RetryReaderOptions) io.ReadCloser {
if o.MaxRetryRequests == 0 {
return dr.Response().Body
}
Expand Down Expand Up @@ -140,8 +142,10 @@ func (f FileURL) GetProperties(ctx context.Context) (*FileGetPropertiesResponse,
// SetHTTPHeaders sets file's system properties.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-file-properties.
func (f FileURL) SetHTTPHeaders(ctx context.Context, h FileHTTPHeaders) (*FileSetHTTPHeadersResponse, error) {
return f.fileClient.SetHTTPHeaders(ctx, nil,
nil, &h.ContentType, &h.ContentEncoding, &h.ContentLanguage, &h.CacheControl, h.ContentMD5, &h.ContentDisposition)
defaultPermissions := "preserve"
return f.fileClient.SetHTTPHeaders(ctx, "preserve", "preserve", "preserve", nil,
nil, &h.ContentType, &h.ContentEncoding, &h.ContentLanguage, &h.CacheControl, h.ContentMD5,
&h.ContentDisposition, &defaultPermissions, nil)
}

// SetMetadata sets a file's metadata.
Expand All @@ -153,12 +157,14 @@ func (f FileURL) SetMetadata(ctx context.Context, metadata Metadata) (*FileSetMe
// Resize resizes the file to the specified size.
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-file-properties.
func (f FileURL) Resize(ctx context.Context, length int64) (*FileSetHTTPHeadersResponse, error) {
return f.fileClient.SetHTTPHeaders(ctx, nil,
&length, nil, nil, nil, nil, nil, nil)
defaultPermissions := "preserve"
return f.fileClient.SetHTTPHeaders(ctx, "preserve", "preserve", "preserve", nil,
&length, nil, nil, nil, nil,
nil, nil, &defaultPermissions, nil)
}

// UploadRange writes bytes to a file.
// offset indiciates the offset at which to begin writing, in bytes.
// offset indicates the offset at which to begin writing, in bytes.
// For more information, see https://docs.microsoft.com/en-us/rest/api/storageservices/put-range.
func (f FileURL) UploadRange(ctx context.Context, offset int64, body io.ReadSeeker, transactionalMD5 []byte) (*FileUploadRangeResponse, error) {
if body == nil {
Expand All @@ -174,6 +180,15 @@ func (f FileURL) UploadRange(ctx context.Context, offset int64, body io.ReadSeek
return f.fileClient.UploadRange(ctx, *toRange(offset, count), FileRangeWriteUpdate, count, body, nil, transactionalMD5)
}

// Update range with bytes from a specific URL.
// offset indicates the offset at which to begin writing, in bytes.
func (f FileURL) UploadRangeFromURL(ctx context.Context, sourceURL url.URL, sourceOffset int64, destOffset int64,
count int64) (*FileUploadRangeFromURLResponse, error) {

return f.fileClient.UploadRangeFromURL(ctx, *toRange(destOffset, count), sourceURL.String(), 0, nil,
toRange(sourceOffset, count), nil, nil, nil)
}

// ClearRange clears the specified range and releases the space used in storage for that range.
// offset means the start offset of the range to clear.
// count means count of bytes to clean, it cannot be CountToEnd (0), and must be explictly specified.
Expand Down
2 changes: 1 addition & 1 deletion azfile/url_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func appendToURLPath(u url.URL, name string) url.URL {
// https://docs.microsoft.com/en-us/rest/api/storageservices/list-shares.
func (s ServiceURL) ListSharesSegment(ctx context.Context, marker Marker, o ListSharesOptions) (*ListSharesResponse, error) {
prefix, include, maxResults := o.pointers()
return s.client.ListSharesSegment(ctx, prefix, marker.val, maxResults, include, nil)
return s.client.ListSharesSegment(ctx, prefix, marker.Val, maxResults, include, nil)
}

// ListSharesOptions defines options available when calling ListSharesSegment.
Expand Down
2 changes: 1 addition & 1 deletion azfile/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package azfile

const serviceLibVersion = "0.5.0"
const serviceLibVersion = "0.6.0"
5 changes: 3 additions & 2 deletions azfile/zt_examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,10 @@ func ExampleShareURL_SetQuota() {
// Check current usage stats for the share.
// Note that the ShareStats object is part of the protocol layer for the File service.
if statistics, err := shareURL.GetStatistics(ctx); err == nil {
fmt.Printf("Current share usage: %d GB\n", statistics.ShareUsage)
shareUsageGB := statistics.ShareUsageBytes/1024/1024/1024
fmt.Printf("Current share usage: %d GB\n", shareUsageGB)

shareURL.SetQuota(ctx, 10+statistics.ShareUsage)
shareURL.SetQuota(ctx, 10+shareUsageGB)

properties, err := shareURL.GetProperties(ctx)
if err != nil {
Expand Down
47 changes: 46 additions & 1 deletion azfile/zt_url_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ func (s *FileURLSuite) TestFileUploadRangeTransactionalMD5(c *chk.C) {
c.Assert(pResp.ContentMD5(), chk.DeepEquals, md5[:])

// Upload range with empty MD5, nil MD5 is covered by other cases.
pResp, err = fileURL.UploadRange(context.Background(), 1024, bytes.NewReader(contentD[1024:]), []byte{})
pResp, err = fileURL.UploadRange(context.Background(), 1024, bytes.NewReader(contentD[1024:]), nil)
c.Assert(err, chk.IsNil)
c.Assert(pResp.ContentMD5(), chk.NotNil)
c.Assert(pResp.StatusCode(), chk.Equals, http.StatusCreated)
Expand Down Expand Up @@ -1129,6 +1129,51 @@ func (s *FileURLSuite) TestFileUploadRangeIncorrectTransactionalMD5(c *chk.C) {
validateStorageError(c, err, azfile.ServiceCodeMd5Mismatch)
}

func (f *FileURLSuite) TestUploadRangeFromURL(c *chk.C) {
fsu := getFSU()
shareURL, shareName := createNewShare(c, fsu)
defer delShare(c, shareURL, azfile.DeleteSnapshotsOptionNone)

// create the source file and populate it with random data at a specific offset
expectedDataSize := 2048
totalFileSize := 4096
srcOffset := 999
expectedDataReader, expectedData := getRandomDataAndReader(expectedDataSize)
srcFileURL, _ := createNewFileFromShare(c, shareURL, int64(totalFileSize))
_, err := srcFileURL.UploadRange(context.Background(), int64(srcOffset), expectedDataReader, nil)
c.Assert(err, chk.IsNil)

// generate a URL with SAS pointing to the source file
credential, _ := getCredential()
sasQueryParams, err := azfile.FileSASSignatureValues{
Protocol: azfile.SASProtocolHTTPS,
ExpiryTime: time.Now().UTC().Add(48 * time.Hour),
ShareName: shareName,
Permissions: azfile.FileSASPermissions{Create: true, Read: true, Write: true, Delete: true}.String(),
}.NewSASQueryParameters(credential)
c.Assert(err, chk.IsNil)
rawSrcURL := srcFileURL.URL()
rawSrcURL.RawQuery = sasQueryParams.Encode()

// create the destination file
dstFileURL, _ := createNewFileFromShare(c, shareURL, int64(totalFileSize))

// invoke UploadRange on dstFileURL and put the data at a random range
// source and destination have different offsets so we can test both values at the same time
dstOffset := 100
uploadFromURLResp, err := dstFileURL.UploadRangeFromURL(ctx, rawSrcURL, int64(srcOffset),
int64(dstOffset), int64(expectedDataSize))
c.Assert(err, chk.IsNil)
c.Assert(uploadFromURLResp.StatusCode(), chk.Equals, 201)

// verify the destination
resp, err := dstFileURL.Download(context.Background(), int64(dstOffset), int64(expectedDataSize), false)
c.Assert(err, chk.IsNil)
download, err := ioutil.ReadAll(resp.Response().Body)
c.Assert(err, chk.IsNil)
c.Assert(download, chk.DeepEquals, expectedData)
}

// Testings for GetRangeList and ClearRange
func (s *FileURLSuite) TestGetRangeListNonDefaultExact(c *chk.C) {
fsu := getFSU()
Expand Down
3 changes: 1 addition & 2 deletions azfile/zt_url_share_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ func (s *ShareURLSuite) TestShareGetStats(c *chk.C) {
// c.Assert(gResp.LastModified().IsZero(), chk.Equals, false) // TODO: Even share is once updated, no LastModified would be returned.
c.Assert(gResp.RequestID(), chk.Not(chk.Equals), "")
c.Assert(gResp.Version(), chk.Not(chk.Equals), "")
c.Assert(gResp.ShareUsage, chk.Equals, int32(0))
c.Assert(gResp.ShareUsageBytes, chk.Equals, int32(0))
}

func (s *ShareURLSuite) TestShareGetStatsNegative(c *chk.C) {
Expand Down Expand Up @@ -741,7 +741,6 @@ func (s *ShareURLSuite) TestShareDeleteSnapshot(c *chk.C) {
func (s *ShareURLSuite) TestShareDeleteSnapshotsInclude(c *chk.C) {
fsu := getFSU()
share, shareName := createNewShare(c, fsu)
defer delShare(c, share, azfile.DeleteSnapshotsOptionNone)

_, err := share.CreateSnapshot(ctx, nil)
c.Assert(err, chk.IsNil)
Expand Down
2 changes: 1 addition & 1 deletion azfile/zz_generated_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 825ad79

Please sign in to comment.