Skip to content

Commit 63b51bd

Browse files
CRC64 not optional in UploadRangeFromURL (Azure#21890)
* changed crc64 uint to general implementation interface * add documentation and changelog * push azfile recordings * added test and updated changelog
1 parent 2cf2485 commit 63b51bd

File tree

5 files changed

+108
-16
lines changed

5 files changed

+108
-16
lines changed

sdk/storage/azfile/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
### Bugs Fixed
1010

1111
* Fixed a bug where Optional fields which were mandatory earlier create a failure when passed an older service version
12+
* Made SourceContentCRC64 header as optional. Changed the type from uint64 to a generic interface implementation.
13+
These changes impact: `file.UploadRangeFromURL()`
1214

1315
### Other Changes
1416

sdk/storage/azfile/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "go",
44
"TagPrefix": "go/storage/azfile",
5-
"Tag": "go/storage/azfile_249bf38076"
5+
"Tag": "go/storage/azfile_f1d39931a0"
66
}

sdk/storage/azfile/file/client_test.go

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,9 +1782,8 @@ func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURL() {
17821782
destFClient := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName))
17831783
_, err = destFClient.Create(context.Background(), fileSize, nil)
17841784
_require.NoError(err)
1785-
17861785
uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{
1787-
SourceContentCRC64: contentCRC64,
1786+
SourceContentValidation: file.SourceContentValidationTypeCRC64(contentCRC64),
17881787
})
17891788
_require.NoError(err)
17901789
_require.NotNil(uResp.XMSContentCRC64)
@@ -1834,7 +1833,7 @@ func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLNegative() {
18341833
destFClient := testcommon.CreateNewFileFromShare(context.Background(), _require, "dest"+testcommon.GenerateFileName(testName), fileSize, shareClient)
18351834

18361835
_, err = destFClient.UploadRangeFromURL(context.Background(), srcFClient.URL(), 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{
1837-
SourceContentCRC64: contentCRC64,
1836+
SourceContentValidation: file.SourceContentValidationTypeCRC64(contentCRC64),
18381837
})
18391838
_require.Error(err)
18401839
}
@@ -1915,7 +1914,7 @@ func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuthBlob(
19151914

19161915
blobURL := blobClient.ServiceClient().NewContainerClient(containerName).NewBlockBlobClient(blobName).URL()
19171916
uResp, err := destFClient.UploadRangeFromURL(context.Background(), blobURL, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{
1918-
SourceContentCRC64: contentCRC64,
1917+
SourceContentValidation: file.SourceContentValidationTypeCRC64(contentCRC64),
19191918
CopySourceAuthorization: to.Ptr("Bearer " + accessToken.Token),
19201919
})
19211920
_require.NoError(err)
@@ -1937,6 +1936,72 @@ func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuthBlob(
19371936
_require.EqualValues(data, content)
19381937
}
19391938

1939+
func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLWithEmptyUploadRangeFromURLOptions() {
1940+
_require := require.New(f.T())
1941+
testName := f.T().Name()
1942+
1943+
cred, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault)
1944+
_require.NoError(err)
1945+
1946+
svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil)
1947+
_require.NoError(err)
1948+
1949+
shareName := testcommon.GenerateShareName(testName)
1950+
shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient)
1951+
defer testcommon.DeleteShare(context.Background(), _require, shareClient)
1952+
1953+
var fileSize int64 = 1024 * 20
1954+
srcFileName := "src" + testcommon.GenerateFileName(testName)
1955+
srcFClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName)
1956+
_, err = srcFClient.Create(context.Background(), fileSize, nil)
1957+
_require.NoError(err)
1958+
1959+
gResp, err := srcFClient.GetProperties(context.Background(), nil)
1960+
_require.NoError(err)
1961+
_require.Equal(*gResp.ContentLength, fileSize)
1962+
1963+
contentSize := 1024 * 8 // 8KB
1964+
content := make([]byte, contentSize)
1965+
body := bytes.NewReader(content)
1966+
rsc := streaming.NopCloser(body)
1967+
1968+
_, err = srcFClient.UploadRange(context.Background(), 0, rsc, nil)
1969+
_require.NoError(err)
1970+
1971+
perms := sas.FilePermissions{Read: true, Write: true}
1972+
sasQueryParams, err := sas.SignatureValues{
1973+
Protocol: sas.ProtocolHTTPS, // Users MUST use HTTPS (not HTTP)
1974+
ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
1975+
ShareName: shareName,
1976+
FilePath: srcFileName,
1977+
Permissions: perms.String(),
1978+
}.SignWithSharedKey(cred)
1979+
_require.NoError(err)
1980+
1981+
srcFileSAS := srcFClient.URL() + "?" + sasQueryParams.Encode()
1982+
1983+
destFClient := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName))
1984+
_, err = destFClient.Create(context.Background(), fileSize, nil)
1985+
_require.NoError(err)
1986+
uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{})
1987+
_require.NoError(err)
1988+
_require.NotNil(uResp.XMSContentCRC64)
1989+
1990+
rangeList, err := destFClient.GetRangeList(context.Background(), nil)
1991+
_require.NoError(err)
1992+
_require.Len(rangeList.Ranges, 1)
1993+
_require.Equal(*rangeList.Ranges[0].Start, int64(0))
1994+
_require.Equal(*rangeList.Ranges[0].End, int64(contentSize-1))
1995+
1996+
cResp, err := destFClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: int64(contentSize)}, nil)
1997+
_require.NoError(err)
1998+
_require.Nil(cResp.ContentMD5)
1999+
2000+
rangeList2, err := destFClient.GetRangeList(context.Background(), nil)
2001+
_require.NoError(err)
2002+
_require.Len(rangeList2.Ranges, 0)
2003+
}
2004+
19402005
func (f *FileUnrecordedTestsSuite) TestFileUploadBuffer() {
19412006
_require := require.New(f.T())
19422007
testName := f.T().Name()
@@ -4074,7 +4139,7 @@ func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLTrailingDot() {
40744139
destFClient := testcommon.CreateNewFileFromShare(context.Background(), _require, "destFile..", fileSize, shareClient)
40754140

40764141
uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{
4077-
SourceContentCRC64: contentCRC64,
4142+
SourceContentValidation: file.SourceContentValidationTypeCRC64(contentCRC64),
40784143
})
40794144
_require.NoError(err)
40804145
_require.NotNil(uResp.XMSContentCRC64)
@@ -4210,8 +4275,8 @@ func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLPreserve() {
42104275
_require.NotNil(cResp.FileLastWriteTime)
42114276

42124277
uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{
4213-
SourceContentCRC64: contentCRC64,
4214-
LastWrittenMode: to.Ptr(file.LastWrittenModePreserve),
4278+
SourceContentValidation: file.SourceContentValidationTypeCRC64(contentCRC64),
4279+
LastWrittenMode: to.Ptr(file.LastWrittenModePreserve),
42154280
})
42164281
_require.NoError(err)
42174282
_require.NotNil(uResp.XMSContentCRC64)
@@ -4265,8 +4330,8 @@ func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLNow() {
42654330
_require.NotNil(cResp.FileLastWriteTime)
42664331

42674332
uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{
4268-
SourceContentCRC64: contentCRC64,
4269-
LastWrittenMode: to.Ptr(file.LastWrittenModeNow),
4333+
SourceContentValidation: file.SourceContentValidationTypeCRC64(contentCRC64),
4334+
LastWrittenMode: to.Ptr(file.LastWrittenModeNow),
42704335
})
42714336
_require.NoError(err)
42724337
_require.NotNil(uResp.XMSContentCRC64)

sdk/storage/azfile/file/constants.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package file
88

99
import (
10+
"encoding/binary"
1011
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported"
1112
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated"
1213
)
@@ -71,6 +72,25 @@ func PossibleRangeWriteTypeValues() []RangeWriteType {
7172
return generated.PossibleFileRangeWriteTypeValues()
7273
}
7374

75+
// SourceContentValidationType abstracts mechanisms used to validate source content
76+
type SourceContentValidationType interface {
77+
Apply(generated.SourceContentSetter) error
78+
notPubliclyImplementable()
79+
}
80+
81+
// SourceContentValidationTypeCRC64 is a SourceContentValidationType used to provide a precomputed CRC64.
82+
type SourceContentValidationTypeCRC64 uint64
83+
84+
// Apply implements the SourceContentValidationType interface for type SourceContentValidationTypeCRC64.
85+
func (s SourceContentValidationTypeCRC64) Apply(cfg generated.SourceContentSetter) error {
86+
buf := make([]byte, 8)
87+
binary.LittleEndian.PutUint64(buf, uint64(s))
88+
cfg.SetSourceContentCRC64(buf)
89+
return nil
90+
}
91+
92+
func (SourceContentValidationTypeCRC64) notPubliclyImplementable() {}
93+
7494
// TransferValidationType abstracts the various mechanisms used to verify a transfer.
7595
type TransferValidationType = exported.TransferValidationType
7696

sdk/storage/azfile/file/models.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
package file
88

99
import (
10-
"encoding/binary"
1110
"errors"
1211
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
1312
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported"
@@ -633,12 +632,15 @@ func (o *ClearRangeOptions) format(contentRange HTTPRange) (string, *generated.L
633632
type UploadRangeFromURLOptions struct {
634633
// Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source.
635634
CopySourceAuthorization *string
636-
// Specify the crc64 calculated for the range of bytes that must be read from the copy source.
637-
SourceContentCRC64 uint64
635+
// SourceContentValidation contains the validation mechanism used on the range of bytes read from the source.
636+
SourceContentValidation SourceContentValidationType
638637
SourceModifiedAccessConditions *SourceModifiedAccessConditions
639638
LeaseAccessConditions *LeaseAccessConditions
640639
// LastWrittenMode specifies if the file last write time should be preserved or overwritten.
641640
LastWrittenMode *LastWrittenMode
641+
642+
// Deprecated: Specify the crc64 calculated for the range of bytes that must be read from the copy source.
643+
SourceContentCRC64 uint64
642644
}
643645

644646
func (o *UploadRangeFromURLOptions) format(sourceOffset int64, destinationOffset int64, count int64) (string, *generated.FileClientUploadRangeFromURLOptions, *generated.SourceModifiedAccessConditions, *generated.LeaseAccessConditions, error) {
@@ -666,9 +668,12 @@ func (o *UploadRangeFromURLOptions) format(sourceOffset int64, destinationOffset
666668
sourceModifiedAccessConditions = o.SourceModifiedAccessConditions
667669
leaseAccessConditions = o.LeaseAccessConditions
668670

669-
buf := make([]byte, 8)
670-
binary.LittleEndian.PutUint64(buf, o.SourceContentCRC64)
671-
opts.SourceContentCRC64 = buf
671+
if o.SourceContentValidation != nil {
672+
err := o.SourceContentValidation.Apply(opts)
673+
if err != nil {
674+
return "", nil, nil, nil, err
675+
}
676+
}
672677
}
673678

674679
return destRange, opts, sourceModifiedAccessConditions, leaseAccessConditions, nil

0 commit comments

Comments
 (0)