From 9403f858b6b6f36b1ddb05a63caaa8587da8c742 Mon Sep 17 00:00:00 2001 From: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Date: Mon, 17 Jul 2023 17:18:45 -0400 Subject: [PATCH] Copy Blob from URL/Put Blob from URL copy source tags (#21128) * Regenerating AzBlob to STG 85/86 (#20724) * Regenerating azblob to stg 85/86 * Updating CopyFromURL * minor change * minor fixes * undo some minor fixes * Updating Go code generator * Fixing calls to pipeline * Adding custom UnmarshalXML for BlobItem and BlobPrefix * Updating constructor method for AppendBlobClient * Updating Client constructors * Undoing minor fixes to blob examples * Fixing authpolicy * Updating azcore version * Fixing client strings * Const for service client * Minor fix * fixing go mod files * Shared constants client name * Addressing comments * [Feature STG 85/86] Cold Tier (#21032) * Adding Cold Tier + tests * Recorded tests * Updated CHANGELOG.md * Fixing linting issues * Updating Cold tier test and recording * Addressing commits * Adding CopySourceBlobTags * Fixing enum variable name, adding default test, changelog update * Cleaning up constants * Moving const to constants.go * Small change --- sdk/storage/azblob/CHANGELOG.md | 1 + sdk/storage/azblob/blockblob/client_test.go | 117 +++++++++++++++++++- sdk/storage/azblob/blockblob/constants.go | 8 ++ sdk/storage/azblob/blockblob/models.go | 4 + 4 files changed, 129 insertions(+), 1 deletion(-) diff --git a/sdk/storage/azblob/CHANGELOG.md b/sdk/storage/azblob/CHANGELOG.md index 946886d57b6e..29355db9707e 100644 --- a/sdk/storage/azblob/CHANGELOG.md +++ b/sdk/storage/azblob/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features Added * Added support for [Cold tier](https://learn.microsoft.com/azure/storage/blobs/access-tiers-overview?tabs=azure-portal). +* Added CopySourceTag option for UploadBlobFromURLOptions ### Breaking Changes diff --git a/sdk/storage/azblob/blockblob/client_test.go b/sdk/storage/azblob/blockblob/client_test.go index f0e8af99c17f..89fe17e5e232 100644 --- a/sdk/storage/azblob/blockblob/client_test.go +++ b/sdk/storage/azblob/blockblob/client_test.go @@ -851,7 +851,7 @@ func setUpPutBlobFromURLTest(testName string, _require *require.Assertions, svcC sasQueryParams, err := sas.AccountSignatureValues{ Protocol: sas.ProtocolHTTPS, ExpiryTime: expiryTime, - Permissions: to.Ptr(sas.AccountPermissions{Read: true, List: true}).String(), + Permissions: to.Ptr(sas.AccountPermissions{Read: true, List: true, Tag: true}).String(), ResourceTypes: to.Ptr(sas.AccountResourceTypes{Container: true, Object: true}).String(), }.SignWithSharedKey(credential) _require.Nil(err) @@ -884,6 +884,121 @@ func (s *BlockBlobUnrecordedTestsSuite) TestPutBlobFromURL() { _require.Equal(destBuffer, sourceData) } +func (s *BlockBlobUnrecordedTestsSuite) TestPutBlobFromURLWithCopySourceTagsDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + containerClient, srcBlob, destBlob, srcBlobURLWithSAS, _ := setUpPutBlobFromURLTest(testName, _require, svcClient) + defer testcommon.DeleteContainer(context.Background(), _require, containerClient) + + // Set tags to source + srcBlobTagsMap := map[string]string{ + "source": "tags", + } + _, err = srcBlob.SetTags(context.Background(), srcBlobTagsMap, nil) + _require.NoError(err) + + // Dest tags + destBlobTagsMap := map[string]string{ + "dest": "tags", + } + + // By default, the CopySourceTag header is Replace + options := blockblob.UploadBlobFromURLOptions{ + Tags: destBlobTagsMap, + } + + // Invoke UploadBlobFromURL + pbResp, err := destBlob.UploadBlobFromURL(context.Background(), srcBlobURLWithSAS, &options) + _require.NotNil(pbResp) + _require.NoError(err) + + // Get tags from dest and check if tags got replaced with dest tags + resp, err := destBlob.GetTags(context.Background(), nil) + _require.NoError(err) + _require.Equal(*resp.BlobTagSet[0].Key, "dest") + _require.Equal(*resp.BlobTagSet[0].Value, "tags") +} + +func (s *BlockBlobUnrecordedTestsSuite) TestPutBlobFromURLWithCopySourceTagsReplace() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + containerClient, srcBlob, destBlob, srcBlobURLWithSAS, _ := setUpPutBlobFromURLTest(testName, _require, svcClient) + defer testcommon.DeleteContainer(context.Background(), _require, containerClient) + + // Set tags to source + srcBlobTagsMap := map[string]string{ + "source": "tags", + } + _, err = srcBlob.SetTags(context.Background(), srcBlobTagsMap, nil) + _require.NoError(err) + + // Dest tags + destBlobTagsMap := map[string]string{ + "dest": "tags", + } + + options := blockblob.UploadBlobFromURLOptions{ + Tags: destBlobTagsMap, + CopySourceTags: to.Ptr(blockblob.BlobCopySourceTagsReplace), + } + + // Invoke UploadBlobFromURL + pbResp, err := destBlob.UploadBlobFromURL(context.Background(), srcBlobURLWithSAS, &options) + _require.NotNil(pbResp) + _require.NoError(err) + + // Get tags from dest and check if tags got replaced with dest tags + resp, err := destBlob.GetTags(context.Background(), nil) + _require.NoError(err) + _require.Equal(*resp.BlobTagSet[0].Key, "dest") + _require.Equal(*resp.BlobTagSet[0].Value, "tags") +} + +func (s *BlockBlobUnrecordedTestsSuite) TestPutBlobFromURLWithCopySourceTagsCopy() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + containerClient, srcBlob, destBlob, srcBlobURLWithSAS, _ := setUpPutBlobFromURLTest(testName, _require, svcClient) + defer testcommon.DeleteContainer(context.Background(), _require, containerClient) + + // Set tags to source + srcBlobTagsMap := map[string]string{ + "source": "tags", + } + _, err = srcBlob.SetTags(context.Background(), srcBlobTagsMap, nil) + _require.NoError(err) + + // Set tags to dest to ensure that COPY works + destBlobTagsMap := map[string]string{ + "dest": "tags", + } + _, err = destBlob.SetTags(context.Background(), destBlobTagsMap, nil) + _require.NoError(err) + + options := blockblob.UploadBlobFromURLOptions{ + CopySourceTags: to.Ptr(blockblob.BlobCopySourceTagsCopy), + } + + // Invoke UploadBlobFromURL + pbResp, err := destBlob.UploadBlobFromURL(context.Background(), srcBlobURLWithSAS, &options) + _require.NotNil(pbResp) + _require.NoError(err) + + // Get tags from dest and check if it matches source tags + resp, err := destBlob.GetTags(context.Background(), nil) + _require.NoError(err) + _require.Equal(*resp.BlobTagSet[0].Key, "source") + _require.Equal(*resp.BlobTagSet[0].Value, "tags") +} + func (s *BlockBlobUnrecordedTestsSuite) TestPutBlobFromURLNegative() { _require := require.New(s.T()) testName := s.T().Name() diff --git a/sdk/storage/azblob/blockblob/constants.go b/sdk/storage/azblob/blockblob/constants.go index cb11626402d7..0f0f8b115e03 100644 --- a/sdk/storage/azblob/blockblob/constants.go +++ b/sdk/storage/azblob/blockblob/constants.go @@ -37,3 +37,11 @@ const ( func PossibleBlockListTypeValues() []BlockListType { return generated.PossibleBlockListTypeValues() } + +// BlobCopySourceTags - can be 'COPY' or 'REPLACE' +type BlobCopySourceTags = generated.BlobCopySourceTags + +const ( + BlobCopySourceTagsCopy = generated.BlobCopySourceTagsCOPY + BlobCopySourceTagsReplace = generated.BlobCopySourceTagsREPLACE +) diff --git a/sdk/storage/azblob/blockblob/models.go b/sdk/storage/azblob/blockblob/models.go index 662e78e5eac7..453d569e5d2d 100644 --- a/sdk/storage/azblob/blockblob/models.go +++ b/sdk/storage/azblob/blockblob/models.go @@ -85,6 +85,9 @@ type UploadBlobFromURLOptions struct { // Optional, default is true. Indicates if properties from the source blob should be copied. CopySourceBlobProperties *bool + // Optional, default 'replace'. Indicates if source tags should be copied or replaced with the tags specified by x-ms-tags. + CopySourceTags *BlobCopySourceTags + // Optional. Specifies a user-defined name-value pair associated with the blob. Metadata map[string]*string @@ -113,6 +116,7 @@ func (o *UploadBlobFromURLOptions) format() (*generated.BlockBlobClientPutBlobFr BlobTagsString: shared.SerializeBlobTagsToStrPtr(o.Tags), CopySourceAuthorization: o.CopySourceAuthorization, CopySourceBlobProperties: o.CopySourceBlobProperties, + CopySourceTags: o.CopySourceTags, Metadata: o.Metadata, SourceContentMD5: o.SourceContentMD5, Tier: o.Tier,