diff --git a/sdk/storage/Azure.Storage.Blobs/assets.json b/sdk/storage/Azure.Storage.Blobs/assets.json index 377294f47b99..355b8279e12f 100644 --- a/sdk/storage/Azure.Storage.Blobs/assets.json +++ b/sdk/storage/Azure.Storage.Blobs/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/storage/Azure.Storage.Blobs", - "Tag": "net/storage/Azure.Storage.Blobs_730bf5e40e" + "Tag": "net/storage/Azure.Storage.Blobs_be439321c1" } diff --git a/sdk/storage/Azure.Storage.Blobs/src/Generated/BlobRestClient.cs b/sdk/storage/Azure.Storage.Blobs/src/Generated/BlobRestClient.cs index 4cb72cdf210a..d627d63506ca 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/Generated/BlobRestClient.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/Generated/BlobRestClient.cs @@ -778,7 +778,7 @@ public ResponseWithHeaders SetHttpHeaders(int? timeou } } - internal HttpMessage CreateSetImmutabilityPolicyRequest(int? timeout, DateTimeOffset? ifUnmodifiedSince, DateTimeOffset? immutabilityPolicyExpiry, BlobImmutabilityPolicyMode? immutabilityPolicyMode) + internal HttpMessage CreateSetImmutabilityPolicyRequest(int? timeout, DateTimeOffset? ifUnmodifiedSince, DateTimeOffset? immutabilityPolicyExpiry, BlobImmutabilityPolicyMode? immutabilityPolicyMode, string snapshot, string versionId) { var message = _pipeline.CreateMessage(); var request = message.Request; @@ -790,6 +790,14 @@ internal HttpMessage CreateSetImmutabilityPolicyRequest(int? timeout, DateTimeOf { uri.AppendQuery("timeout", timeout.Value, true); } + if (snapshot != null) + { + uri.AppendQuery("snapshot", snapshot, true); + } + if (versionId != null) + { + uri.AppendQuery("versionid", versionId, true); + } request.Uri = uri; request.Headers.Add("x-ms-version", _version); if (ifUnmodifiedSince != null) @@ -813,10 +821,12 @@ internal HttpMessage CreateSetImmutabilityPolicyRequest(int? timeout, DateTimeOf /// Specify this header value to operate only on a blob if it has not been modified since the specified date/time. /// Specifies the date time when the blobs immutability policy is set to expire. /// Specifies the immutability policy mode to set on the blob. + /// The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob">Creating a Snapshot of a Blob.</a>. + /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. It's for service version 2019-10-10 and newer. /// The cancellation token to use. - public async Task> SetImmutabilityPolicyAsync(int? timeout = null, DateTimeOffset? ifUnmodifiedSince = null, DateTimeOffset? immutabilityPolicyExpiry = null, BlobImmutabilityPolicyMode? immutabilityPolicyMode = null, CancellationToken cancellationToken = default) + public async Task> SetImmutabilityPolicyAsync(int? timeout = null, DateTimeOffset? ifUnmodifiedSince = null, DateTimeOffset? immutabilityPolicyExpiry = null, BlobImmutabilityPolicyMode? immutabilityPolicyMode = null, string snapshot = null, string versionId = null, CancellationToken cancellationToken = default) { - using var message = CreateSetImmutabilityPolicyRequest(timeout, ifUnmodifiedSince, immutabilityPolicyExpiry, immutabilityPolicyMode); + using var message = CreateSetImmutabilityPolicyRequest(timeout, ifUnmodifiedSince, immutabilityPolicyExpiry, immutabilityPolicyMode, snapshot, versionId); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); var headers = new BlobSetImmutabilityPolicyHeaders(message.Response); switch (message.Response.Status) @@ -833,10 +843,12 @@ public async Task> SetImmu /// Specify this header value to operate only on a blob if it has not been modified since the specified date/time. /// Specifies the date time when the blobs immutability policy is set to expire. /// Specifies the immutability policy mode to set on the blob. + /// The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob">Creating a Snapshot of a Blob.</a>. + /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. It's for service version 2019-10-10 and newer. /// The cancellation token to use. - public ResponseWithHeaders SetImmutabilityPolicy(int? timeout = null, DateTimeOffset? ifUnmodifiedSince = null, DateTimeOffset? immutabilityPolicyExpiry = null, BlobImmutabilityPolicyMode? immutabilityPolicyMode = null, CancellationToken cancellationToken = default) + public ResponseWithHeaders SetImmutabilityPolicy(int? timeout = null, DateTimeOffset? ifUnmodifiedSince = null, DateTimeOffset? immutabilityPolicyExpiry = null, BlobImmutabilityPolicyMode? immutabilityPolicyMode = null, string snapshot = null, string versionId = null, CancellationToken cancellationToken = default) { - using var message = CreateSetImmutabilityPolicyRequest(timeout, ifUnmodifiedSince, immutabilityPolicyExpiry, immutabilityPolicyMode); + using var message = CreateSetImmutabilityPolicyRequest(timeout, ifUnmodifiedSince, immutabilityPolicyExpiry, immutabilityPolicyMode, snapshot, versionId); _pipeline.Send(message, cancellationToken); var headers = new BlobSetImmutabilityPolicyHeaders(message.Response); switch (message.Response.Status) @@ -848,7 +860,7 @@ public ResponseWithHeaders SetImmutabilityPoli } } - internal HttpMessage CreateDeleteImmutabilityPolicyRequest(int? timeout) + internal HttpMessage CreateDeleteImmutabilityPolicyRequest(int? timeout, string snapshot, string versionId) { var message = _pipeline.CreateMessage(); var request = message.Request; @@ -860,6 +872,14 @@ internal HttpMessage CreateDeleteImmutabilityPolicyRequest(int? timeout) { uri.AppendQuery("timeout", timeout.Value, true); } + if (snapshot != null) + { + uri.AppendQuery("snapshot", snapshot, true); + } + if (versionId != null) + { + uri.AppendQuery("versionid", versionId, true); + } request.Uri = uri; request.Headers.Add("x-ms-version", _version); request.Headers.Add("Accept", "application/xml"); @@ -868,10 +888,12 @@ internal HttpMessage CreateDeleteImmutabilityPolicyRequest(int? timeout) /// The Delete Immutability Policy operation deletes the immutability policy on the blob. /// The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations">Setting Timeouts for Blob Service Operations.</a>. + /// The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob">Creating a Snapshot of a Blob.</a>. + /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. It's for service version 2019-10-10 and newer. /// The cancellation token to use. - public async Task> DeleteImmutabilityPolicyAsync(int? timeout = null, CancellationToken cancellationToken = default) + public async Task> DeleteImmutabilityPolicyAsync(int? timeout = null, string snapshot = null, string versionId = null, CancellationToken cancellationToken = default) { - using var message = CreateDeleteImmutabilityPolicyRequest(timeout); + using var message = CreateDeleteImmutabilityPolicyRequest(timeout, snapshot, versionId); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); var headers = new BlobDeleteImmutabilityPolicyHeaders(message.Response); switch (message.Response.Status) @@ -885,10 +907,12 @@ public async Task> Dele /// The Delete Immutability Policy operation deletes the immutability policy on the blob. /// The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations">Setting Timeouts for Blob Service Operations.</a>. + /// The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob">Creating a Snapshot of a Blob.</a>. + /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. It's for service version 2019-10-10 and newer. /// The cancellation token to use. - public ResponseWithHeaders DeleteImmutabilityPolicy(int? timeout = null, CancellationToken cancellationToken = default) + public ResponseWithHeaders DeleteImmutabilityPolicy(int? timeout = null, string snapshot = null, string versionId = null, CancellationToken cancellationToken = default) { - using var message = CreateDeleteImmutabilityPolicyRequest(timeout); + using var message = CreateDeleteImmutabilityPolicyRequest(timeout, snapshot, versionId); _pipeline.Send(message, cancellationToken); var headers = new BlobDeleteImmutabilityPolicyHeaders(message.Response); switch (message.Response.Status) @@ -900,7 +924,7 @@ public ResponseWithHeaders DeleteImmutabili } } - internal HttpMessage CreateSetLegalHoldRequest(bool legalHold, int? timeout) + internal HttpMessage CreateSetLegalHoldRequest(bool legalHold, int? timeout, string snapshot, string versionId) { var message = _pipeline.CreateMessage(); var request = message.Request; @@ -912,6 +936,14 @@ internal HttpMessage CreateSetLegalHoldRequest(bool legalHold, int? timeout) { uri.AppendQuery("timeout", timeout.Value, true); } + if (snapshot != null) + { + uri.AppendQuery("snapshot", snapshot, true); + } + if (versionId != null) + { + uri.AppendQuery("versionid", versionId, true); + } request.Uri = uri; request.Headers.Add("x-ms-version", _version); request.Headers.Add("x-ms-legal-hold", legalHold); @@ -922,10 +954,12 @@ internal HttpMessage CreateSetLegalHoldRequest(bool legalHold, int? timeout) /// The Set Legal Hold operation sets a legal hold on the blob. /// Specified if a legal hold should be set on the blob. /// The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations">Setting Timeouts for Blob Service Operations.</a>. + /// The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob">Creating a Snapshot of a Blob.</a>. + /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. It's for service version 2019-10-10 and newer. /// The cancellation token to use. - public async Task> SetLegalHoldAsync(bool legalHold, int? timeout = null, CancellationToken cancellationToken = default) + public async Task> SetLegalHoldAsync(bool legalHold, int? timeout = null, string snapshot = null, string versionId = null, CancellationToken cancellationToken = default) { - using var message = CreateSetLegalHoldRequest(legalHold, timeout); + using var message = CreateSetLegalHoldRequest(legalHold, timeout, snapshot, versionId); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); var headers = new BlobSetLegalHoldHeaders(message.Response); switch (message.Response.Status) @@ -940,10 +974,12 @@ public async Task> SetLegalHoldAsyn /// The Set Legal Hold operation sets a legal hold on the blob. /// Specified if a legal hold should be set on the blob. /// The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations">Setting Timeouts for Blob Service Operations.</a>. + /// The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob">Creating a Snapshot of a Blob.</a>. + /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. It's for service version 2019-10-10 and newer. /// The cancellation token to use. - public ResponseWithHeaders SetLegalHold(bool legalHold, int? timeout = null, CancellationToken cancellationToken = default) + public ResponseWithHeaders SetLegalHold(bool legalHold, int? timeout = null, string snapshot = null, string versionId = null, CancellationToken cancellationToken = default) { - using var message = CreateSetLegalHoldRequest(legalHold, timeout); + using var message = CreateSetLegalHoldRequest(legalHold, timeout, snapshot, versionId); _pipeline.Send(message, cancellationToken); var headers = new BlobSetLegalHoldHeaders(message.Response); switch (message.Response.Status) diff --git a/sdk/storage/Azure.Storage.Blobs/src/autorest.md b/sdk/storage/Azure.Storage.Blobs/src/autorest.md index cda269a135e8..6407445e7bf1 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/autorest.md +++ b/sdk/storage/Azure.Storage.Blobs/src/autorest.md @@ -4,7 +4,7 @@ Run `dotnet build /t:GenerateCode` to generate code. ``` yaml input-file: - - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/7c58ab44b9cdd08fa5aae782a34bc42bd67ff59b/specification/storage/data-plane/Microsoft.BlobStorage/stable/2025-01-05/blob.json + - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/2d3b08fe43bc4a573acd166d3d2ba0c631b016fb/specification/storage/data-plane/Microsoft.BlobStorage/stable/2025-01-05/blob.json generation1-convenience-client: true # https://github.com/Azure/autorest/issues/4075 skip-semantics-validation: true diff --git a/sdk/storage/Azure.Storage.Blobs/tests/ImmutableStorageWithVersioningTests.cs b/sdk/storage/Azure.Storage.Blobs/tests/ImmutableStorageWithVersioningTests.cs index 3eac647db9cf..af473b946047 100644 --- a/sdk/storage/Azure.Storage.Blobs/tests/ImmutableStorageWithVersioningTests.cs +++ b/sdk/storage/Azure.Storage.Blobs/tests/ImmutableStorageWithVersioningTests.cs @@ -562,6 +562,92 @@ public async Task DeleteImmutibilityPolicyAsync() Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); } + [Test] + [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_06_12)] + public async Task SetDeleteImmutibilityPolicyAsync_Snapshot() + { + // Arrange + BlobBaseClient blob = await GetNewBlobClient(_containerClient); + + Response createSnapshotResponse = await blob.CreateSnapshotAsync(); + BlobBaseClient snapshotClient = blob.WithSnapshot(createSnapshotResponse.Value.Snapshot); + try + { + BlobImmutabilityPolicy immutabilityPolicy = new BlobImmutabilityPolicy + { + ExpiresOn = Recording.UtcNow.AddSeconds(5), + PolicyMode = BlobImmutabilityPolicyMode.Unlocked + }; + + // Act + await snapshotClient.SetImmutabilityPolicyAsync(immutabilityPolicy); + + // Assert that the base blob does not have an immutability policy. + Response propertiesResponse = await blob.GetPropertiesAsync(); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.ExpiresOn); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); + + // Assert that the blob snapshot has an immuability policy. + propertiesResponse = await snapshotClient.GetPropertiesAsync(); + Assert.IsNotNull(propertiesResponse.Value.ImmutabilityPolicy.ExpiresOn); + Assert.IsNotNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); + + await snapshotClient.DeleteImmutabilityPolicyAsync(); + + // Assert + propertiesResponse = await snapshotClient.GetPropertiesAsync(); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.ExpiresOn); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); + } + finally + { + await snapshotClient.DeleteAsync(); + } + } + + [Test] + [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_06_12)] + public async Task SetDeleteImmutibilityPolicyAsync_BlobVersion() + { + // Arrange + BlobBaseClient blob = await GetNewBlobClient(_containerClient); + + IDictionary metadata = BuildMetadata(); + + // Create Blob Version + Response setMetadataResponse = await blob.SetMetadataAsync(metadata); + BlobBaseClient versionClient = blob.WithVersion(setMetadataResponse.Value.VersionId); + + // Create another blob Version + await blob.SetMetadataAsync(new Dictionary()); + + BlobImmutabilityPolicy immutabilityPolicy = new BlobImmutabilityPolicy + { + ExpiresOn = Recording.UtcNow.AddSeconds(5), + PolicyMode = BlobImmutabilityPolicyMode.Unlocked + }; + + // Act + await versionClient.SetImmutabilityPolicyAsync(immutabilityPolicy); + + // Assert that the base blob does not have an immutability policy + Response propertiesResponse = await blob.GetPropertiesAsync(); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.ExpiresOn); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); + + // Assert that the blob version does have an immutability policy + propertiesResponse = await versionClient.GetPropertiesAsync(); + Assert.IsNotNull(propertiesResponse.Value.ImmutabilityPolicy.ExpiresOn); + Assert.IsNotNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); + + await versionClient.DeleteImmutabilityPolicyAsync(); + + // Assert blob version does not have an immutability policy + propertiesResponse = await versionClient.GetPropertiesAsync(); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.ExpiresOn); + Assert.IsNull(propertiesResponse.Value.ImmutabilityPolicy.PolicyMode); + } + [Test] [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_06_12)] public async Task DeleteImmutibilityPolicyAsync_Error() @@ -621,6 +707,67 @@ public async Task SetLegalHoldAsync() Assert.IsFalse(response.Value.HasLegalHold); } + [Test] + [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_06_12)] + public async Task SetLegalHoldAsync_Snapshot() + { + // Arrange + BlobBaseClient blob = await GetNewBlobClient(_containerClient); + + Response createSnapshotResponse = await blob.CreateSnapshotAsync(); + BlobBaseClient snapshotClient = blob.WithSnapshot(createSnapshotResponse.Value.Snapshot); + + try + { + // Act + await snapshotClient.SetLegalHoldAsync(true); + + // Assert the blob snapshot has a legal hold + Response propertiesResponse = await snapshotClient.GetPropertiesAsync(); + Assert.IsTrue(propertiesResponse.Value.HasLegalHold); + + // Assert the base blob does not have a legal hold + propertiesResponse = await blob.GetPropertiesAsync(); + Assert.IsFalse(propertiesResponse.Value.HasLegalHold); + + await snapshotClient.SetLegalHoldAsync(false); + } + finally + { + await snapshotClient.DeleteAsync(); + } + } + + [Test] + [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_06_12)] + public async Task SetLegalHoldAsync_BlobVersion() + { + // Arrange + BlobBaseClient blob = await GetNewBlobClient(_containerClient); + + IDictionary metadata = BuildMetadata(); + + // Create Blob Version + Response setMetadataResponse = await blob.SetMetadataAsync(metadata); + BlobBaseClient versionClient = blob.WithVersion(setMetadataResponse.Value.VersionId); + + // Create another blob Version + await blob.SetMetadataAsync(new Dictionary()); + + // Act + await versionClient.SetLegalHoldAsync(true); + + // Assert the blob version has a legal hold + Response propertiesResponse = await versionClient.GetPropertiesAsync(); + Assert.IsTrue(propertiesResponse.Value.HasLegalHold); + + // Assert the base blob does not have a legal hold + propertiesResponse = await blob.GetPropertiesAsync(); + Assert.IsFalse(propertiesResponse.Value.HasLegalHold); + + await versionClient.SetLegalHoldAsync(false); + } + [Test] [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2020_06_12)] public async Task SetLegalHoldAsync_Error()