Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/storage/Azure.Storage.Blobs/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "net",
"TagPrefix": "net/storage/Azure.Storage.Blobs",
"Tag": "net/storage/Azure.Storage.Blobs_d36a42e966"
"Tag": "net/storage/Azure.Storage.Blobs_7f00602cb3"
}
2 changes: 2 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/BlobClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ private void AddHeadersAndQueryParameters()
Diagnostics.LoggedHeaderNames.Add("x-ms-source-if-unmodified-since");
Diagnostics.LoggedHeaderNames.Add("x-ms-tag-count");
Diagnostics.LoggedHeaderNames.Add("x-ms-encryption-key-sha256");
Diagnostics.LoggedHeaderNames.Add("x-ms-copy-source-error-code");
Diagnostics.LoggedHeaderNames.Add("x-ms-copy-source-status-code");

Diagnostics.LoggedQueryParameters.Add("comp");
Diagnostics.LoggedQueryParameters.Add("maxresults");
Expand Down

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

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

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

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

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

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

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

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

2 changes: 1 addition & 1 deletion sdk/storage/Azure.Storage.Blobs/src/autorest.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Run `dotnet build /t:GenerateCode` to generate code.

``` yaml
input-file:
- https://raw.githubusercontent.com/Azure/azure-rest-api-specs/a32d0b2423d19835246bb2ef92941503bfd5e734/specification/storage/data-plane/Microsoft.BlobStorage/preview/2021-12-02/blob.json
- C:\azure-rest-api-specs\specification\storage\data-plane\Microsoft.BlobStorage\stable\2024-08-04\blob.json
Comment thread
seanmcc-msft marked this conversation as resolved.
Outdated
generation1-convenience-client: true
# https://github.com/Azure/autorest/issues/4075
skip-semantics-validation: true
Expand Down
21 changes: 21 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/AppendBlobClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,27 @@ public async Task AppendBlockFromUriAsync_Min()
}
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2024_08_04)]
public async Task AppendBlockFromUriAsync_SourceErrorAndStatusCode()
{
await using DisposingContainer test = await GetTestContainerAsync(publicAccessType: PublicAccessType.None);

AppendBlobClient sourceBlob = InstrumentClient(test.Container.GetAppendBlobClient(GetNewBlobName()));
AppendBlobClient destBlob = InstrumentClient(test.Container.GetAppendBlobClient(GetNewBlobName()));
await destBlob.CreateIfNotExistsAsync();

// Act
await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
destBlob.AppendBlockFromUriAsync(sourceBlob.Uri),
e =>
{
Assert.IsTrue(e.Message.Contains("CopySourceStatusCode: 409"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorCode: PublicAccessNotPermitted"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorMessage: Public access is not permitted on this storage account."));
});
}

[RecordedTest]
[TestCase(nameof(AppendBlobRequestConditions.LeaseId))]
[TestCase(nameof(AppendBlobRequestConditions.TagConditions))]
Expand Down
44 changes: 44 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1996,6 +1996,29 @@ public async Task StartCopyFromUriAsync()
Assert.IsTrue(operation.HasValue);
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2024_08_04)]
public async Task StartCopyFromUriAsync_SourceErrorAndStatusCode()
{
await using DisposingContainer test = await GetTestContainerAsync(publicAccessType: PublicAccessType.None);

// Arrange
BlobBaseClient srcBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));
BlockBlobClient destBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));

Uri sourceUri = srcBlob.GenerateSasUri(BlobSasPermissions.Read, GetUtcNow().AddDays(1));

// Act
await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
destBlob.StartCopyFromUriAsync(sourceUri),
e =>
{
Assert.IsTrue(e.Message.Contains("CopySourceStatusCode: 404"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorCode: BlobNotFound"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorMessage: The specified blob does not exist."));
});
}

[RecordedTest]
[TestCase(nameof(BlobRequestConditions.LeaseId))]
public async Task StartCopyFromUriAsync_InvalidSourceRequestConditions(string invalidSourceCondition)
Expand Down Expand Up @@ -3329,6 +3352,27 @@ await destBlob.SyncCopyFromUriAsync(
}
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2024_08_04)]
public async Task SyncCopyFromUriAsync_SourceErrorAndStatusCode()
{
await using DisposingContainer test = await GetTestContainerAsync(publicAccessType: PublicAccessType.None);

// Arrange
BlockBlobClient srcBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));
BlockBlobClient destBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));

// Act
await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
destBlob.SyncCopyFromUriAsync(srcBlob.Uri),
e =>
{
Assert.IsTrue(e.Message.Contains("CopySourceStatusCode: 409"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorCode: PublicAccessNotPermitted"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorMessage: Public access is not permitted on this storage account."));
});
}

[RecordedTest]
public async Task DeleteAsync()
{
Expand Down
42 changes: 42 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/BlockBlobClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,27 @@ await RetryAsync(
_retryStageBlockFromUri);
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2024_08_04)]
public async Task StageBlobFromUriAsync_SourceErrorAndStatusCode()
{
// Arrange
var constants = TestConstants.Create(this);
await using DisposingContainer test = await GetTestContainerAsync(publicAccessType: PublicAccessType.None);
BlockBlobClient sourceBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));
BlockBlobClient destBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));

// Act
await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
destBlob.StageBlockFromUriAsync(sourceBlob.Uri, ToBase64(GetNewBlockName())),
e =>
{
Assert.IsTrue(e.Message.Contains("CopySourceStatusCode: 409"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorCode: PublicAccessNotPermitted"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorMessage: Public access is not permitted on this storage account."));
});
}

[RecordedTest]
[TestCase(nameof(BlobRequestConditions.IfModifiedSince))]
[TestCase(nameof(BlobRequestConditions.IfUnmodifiedSince))]
Expand Down Expand Up @@ -2818,6 +2839,27 @@ await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
e => Assert.AreEqual(BlobErrorCode.CannotVerifyCopySource.ToString(), e.ErrorCode));
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2024_08_04)]
public async Task SyncUploadFromUriAsync_SourceErrorAndStatusCode()
{
// Arrange
var constants = TestConstants.Create(this);
await using DisposingContainer test = await GetTestContainerAsync(publicAccessType: PublicAccessType.None);
BlockBlobClient sourceBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));
BlockBlobClient destBlob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));

// Act
await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
destBlob.SyncUploadFromUriAsync(sourceBlob.Uri),
e =>
{
Assert.IsTrue(e.Message.Contains("CopySourceStatusCode: 409"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorCode: PublicAccessNotPermitted"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorMessage: Public access is not permitted on this storage account."));
});
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_04_08)]
public async Task SyncUploadFromUriAsync_OverwriteSourceBlobProperties()
Expand Down
25 changes: 25 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/PageBlobClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3368,6 +3368,31 @@ public async Task UploadPagesFromUriAsync_Min()
}
}

[RecordedTest]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2024_08_04)]
public async Task UploadPagesFromUriAsync_SourceErrorAndStatusCode()
{
// Arrange
await using DisposingContainer test = await GetTestContainerAsync(publicAccessType: PublicAccessType.None);

PageBlobClient sourceBlob = InstrumentClient(test.Container.GetPageBlobClient(GetNewBlobName()));

PageBlobClient destBlob = InstrumentClient(test.Container.GetPageBlobClient(GetNewBlobName()));
await destBlob.CreateIfNotExistsAsync(Constants.KB);

HttpRange range = new HttpRange(0, Constants.KB);

// Act
await TestHelper.AssertExpectedExceptionAsync<RequestFailedException>(
destBlob.UploadPagesFromUriAsync(sourceBlob.Uri, range, range),
e =>
{
Assert.IsTrue(e.Message.Contains("CopySourceStatusCode: 409"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorCode: PublicAccessNotPermitted"));
Assert.IsTrue(e.Message.Contains("CopySourceErrorMessage: Public access is not permitted on this storage account."));
});
}

[RecordedTest]
[TestCase(nameof(PageBlobRequestConditions.LeaseId))]
[TestCase(nameof(PageBlobRequestConditions.IfSequenceNumberLessThanOrEqual))]
Expand Down
1 change: 1 addition & 0 deletions sdk/storage/Azure.Storage.Common/src/Shared/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ internal static class HeaderNames
public const string LeaseId = "x-ms-lease-id";
public const string LastModified = "Last-Modified";
public const string ETag = "ETag";
public const string CopySourceErrorCode = "x-ms-copy-source-error-code";
}

internal static class ErrorCodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ public override bool IsRetriableResponse(HttpMessage message)
return true;
}
}

// Retry select Copy Source Error Codes
if (message.Response.Headers.TryGetValue(Constants.HeaderNames.CopySourceErrorCode, out string copySourceError))
Comment thread
seanmcc-msft marked this conversation as resolved.
Outdated
{
switch (copySourceError)
{
case Constants.ErrorCodes.InternalError:
case Constants.ErrorCodes.OperationTimedOut:
case Constants.ErrorCodes.ServerBusy:
return true;
}
}

return base.IsRetriableResponse(message);
}

Expand Down
2 changes: 1 addition & 1 deletion sdk/storage/Azure.Storage.Files.Shares/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "net",
"TagPrefix": "net/storage/Azure.Storage.Files.Shares",
"Tag": "net/storage/Azure.Storage.Files.Shares_0b948bad37"
"Tag": "net/storage/Azure.Storage.Files.Shares_ad3f7e8674"
}
Loading