diff --git a/sdk/storage/.dict.txt b/sdk/storage/.dict.txt index 2b621213189..bd3cb830d22 100644 --- a/sdk/storage/.dict.txt +++ b/sdk/storage/.dict.txt @@ -29,5 +29,6 @@ testblob3 testblob4 testcontainer uncommittedblobs +Undeletes westus yourtagname diff --git a/sdk/storage/azure_storage_blob/CHANGELOG.md b/sdk/storage/azure_storage_blob/CHANGELOG.md index 88bbbbbe415..aea8a605cc2 100644 --- a/sdk/storage/azure_storage_blob/CHANGELOG.md +++ b/sdk/storage/azure_storage_blob/CHANGELOG.md @@ -7,6 +7,9 @@ - Added support for `set_access_policy` to `BlobContainerClient`. - Added support for `get_access_policy` to `BlobContainerClient`. - Added support for `set_legal_hold` to `BlobClient`. +- Added support for `set_immutability_policy` to `BlobClient`. +- Added support for `delete_immutability_policy` to `BlobClient`. +- Added support for `undelete` to `BlobClient`. ### Breaking Changes diff --git a/sdk/storage/azure_storage_blob/assets.json b/sdk/storage/azure_storage_blob/assets.json index 9372383be3f..d35714c0e71 100644 --- a/sdk/storage/azure_storage_blob/assets.json +++ b/sdk/storage/azure_storage_blob/assets.json @@ -1,6 +1,6 @@ { "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "rust", - "Tag": "rust/azure_storage_blob_e65f06b06d", + "Tag": "rust/azure_storage_blob_68cf9d0b19", "TagPrefix": "rust/azure_storage_blob" } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs index 100d9fc2d73..a81ec0b47ed 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -19,7 +19,7 @@ use crate::{ BlobClientRenewLeaseOptions, BlobClientSetImmutabilityPolicyOptions, BlobClientSetLegalHoldOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, - BlobTags, BlockBlobClientUploadOptions, StorageErrorCode, + BlobClientUndeleteOptions, BlobTags, BlockBlobClientUploadOptions, StorageErrorCode, }, pipeline::StorageHeadersPolicy, AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient, @@ -479,4 +479,16 @@ impl BlobClient { ) -> Result> { self.client.set_legal_hold(legal_hold, options).await } + + /// Undeletes a blob that was previously soft-deleted. + /// + /// # Arguments + /// + /// * `options` - Optional configuration for the request. + pub async fn undelete( + &self, + options: Option>, + ) -> Result> { + self.client.undelete(options).await + } } diff --git a/sdk/storage/azure_storage_blob/src/models/mod.rs b/sdk/storage/azure_storage_blob/src/models/mod.rs index 37ad40496ab..c74d3bedfe2 100644 --- a/sdk/storage/azure_storage_blob/src/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/models/mod.rs @@ -27,48 +27,48 @@ pub use crate::generated::models::{ BlobClientSetExpiryResultHeaders, BlobClientSetImmutabilityPolicyOptions, BlobClientSetLegalHoldOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, BlobClientStartCopyFromUrlResult, - BlobClientStartCopyFromUrlResultHeaders, BlobContainerClientAcquireLeaseOptions, - BlobContainerClientAcquireLeaseResult, BlobContainerClientAcquireLeaseResultHeaders, - BlobContainerClientBreakLeaseOptions, BlobContainerClientBreakLeaseResult, - BlobContainerClientBreakLeaseResultHeaders, BlobContainerClientChangeLeaseOptions, - BlobContainerClientChangeLeaseResult, BlobContainerClientChangeLeaseResultHeaders, - BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, - BlobContainerClientFindBlobsByTagsOptions, BlobContainerClientGetAccessPolicyOptions, - BlobContainerClientGetAccountInfoResult, BlobContainerClientGetAccountInfoResultHeaders, - BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult, - BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientListBlobFlatSegmentOptions, - BlobContainerClientReleaseLeaseOptions, BlobContainerClientReleaseLeaseResult, - BlobContainerClientReleaseLeaseResultHeaders, BlobContainerClientRenameResult, - BlobContainerClientRenameResultHeaders, BlobContainerClientRenewLeaseOptions, - BlobContainerClientRenewLeaseResult, BlobContainerClientRenewLeaseResultHeaders, - BlobContainerClientRestoreResult, BlobContainerClientRestoreResultHeaders, - BlobContainerClientSetAccessPolicyOptions, BlobContainerClientSetMetadataOptions, - BlobCopySourceTags, BlobDeleteType, BlobExpiryOptions, BlobFlatListSegment, BlobItemInternal, - BlobMetadata, BlobName, BlobPropertiesInternal, BlobServiceClientFindBlobsByTagsOptions, - BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetAccountInfoResult, - BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, - BlobServiceClientGetStatisticsOptions, BlobServiceClientListContainersSegmentOptions, - BlobServiceClientSetPropertiesOptions, BlobServiceProperties, BlobTag, BlobTags, - BlobTagsHeaders, BlobType, Block, BlockBlobClientCommitBlockListOptions, - BlockBlobClientCommitBlockListResult, BlockBlobClientCommitBlockListResultHeaders, - BlockBlobClientGetBlockListOptions, BlockBlobClientQueryResult, - BlockBlobClientQueryResultHeaders, BlockBlobClientStageBlockFromUrlResult, - BlockBlobClientStageBlockFromUrlResultHeaders, BlockBlobClientStageBlockOptions, - BlockBlobClientStageBlockResult, BlockBlobClientStageBlockResultHeaders, - BlockBlobClientUploadBlobFromUrlOptions, BlockBlobClientUploadBlobFromUrlResult, - BlockBlobClientUploadBlobFromUrlResultHeaders, BlockBlobClientUploadOptions, - BlockBlobClientUploadResult, BlockBlobClientUploadResultHeaders, BlockList, BlockListHeaders, - BlockListType, BlockLookupList, ContainerItem, CopyStatus, CorsRule, DeleteSnapshotsOptionType, - EncryptionAlgorithmType, FileShareTokenIntent, FilterBlobItem, FilterBlobSegment, - FilterBlobsIncludeItem, GeoReplication, GeoReplicationStatusType, ImmutabilityPolicyMode, - LeaseDuration, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, - ListBlobsFlatSegmentResponseHeaders, ListBlobsHierarchySegmentResponse, - ListBlobsHierarchySegmentResponseHeaders, ListBlobsIncludeItem, ListContainersIncludeType, - ListContainersSegmentResponse, Logging, Metrics, ObjectReplicationMetadata, - PageBlobClientClearPagesOptions, PageBlobClientClearPagesResult, - PageBlobClientClearPagesResultHeaders, PageBlobClientCopyIncrementalResult, - PageBlobClientCopyIncrementalResultHeaders, PageBlobClientCreateOptions, - PageBlobClientCreateResult, PageBlobClientCreateResultHeaders, + BlobClientStartCopyFromUrlResultHeaders, BlobClientUndeleteOptions, + BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, + BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, + BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, + BlobContainerClientChangeLeaseOptions, BlobContainerClientChangeLeaseResult, + BlobContainerClientChangeLeaseResultHeaders, BlobContainerClientCreateOptions, + BlobContainerClientDeleteOptions, BlobContainerClientFindBlobsByTagsOptions, + BlobContainerClientGetAccessPolicyOptions, BlobContainerClientGetAccountInfoResult, + BlobContainerClientGetAccountInfoResultHeaders, BlobContainerClientGetPropertiesOptions, + BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, + BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientReleaseLeaseOptions, + BlobContainerClientReleaseLeaseResult, BlobContainerClientReleaseLeaseResultHeaders, + BlobContainerClientRenameResult, BlobContainerClientRenameResultHeaders, + BlobContainerClientRenewLeaseOptions, BlobContainerClientRenewLeaseResult, + BlobContainerClientRenewLeaseResultHeaders, BlobContainerClientRestoreResult, + BlobContainerClientRestoreResultHeaders, BlobContainerClientSetAccessPolicyOptions, + BlobContainerClientSetMetadataOptions, BlobCopySourceTags, BlobDeleteType, BlobExpiryOptions, + BlobFlatListSegment, BlobItemInternal, BlobMetadata, BlobName, BlobPropertiesInternal, + BlobServiceClientFindBlobsByTagsOptions, BlobServiceClientGetAccountInfoOptions, + BlobServiceClientGetAccountInfoResult, BlobServiceClientGetAccountInfoResultHeaders, + BlobServiceClientGetPropertiesOptions, BlobServiceClientGetStatisticsOptions, + BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, + BlobServiceProperties, BlobTag, BlobTags, BlobTagsHeaders, BlobType, Block, + BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, + BlockBlobClientCommitBlockListResultHeaders, BlockBlobClientGetBlockListOptions, + BlockBlobClientQueryResult, BlockBlobClientQueryResultHeaders, + BlockBlobClientStageBlockFromUrlResult, BlockBlobClientStageBlockFromUrlResultHeaders, + BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, + BlockBlobClientStageBlockResultHeaders, BlockBlobClientUploadBlobFromUrlOptions, + BlockBlobClientUploadBlobFromUrlResult, BlockBlobClientUploadBlobFromUrlResultHeaders, + BlockBlobClientUploadOptions, BlockBlobClientUploadResult, BlockBlobClientUploadResultHeaders, + BlockList, BlockListHeaders, BlockListType, BlockLookupList, ContainerItem, CopyStatus, + CorsRule, DeleteSnapshotsOptionType, EncryptionAlgorithmType, FileShareTokenIntent, + FilterBlobItem, FilterBlobSegment, FilterBlobsIncludeItem, GeoReplication, + GeoReplicationStatusType, ImmutabilityPolicyMode, LeaseDuration, LeaseState, LeaseStatus, + ListBlobsFlatSegmentResponse, ListBlobsFlatSegmentResponseHeaders, + ListBlobsHierarchySegmentResponse, ListBlobsHierarchySegmentResponseHeaders, + ListBlobsIncludeItem, ListContainersIncludeType, ListContainersSegmentResponse, Logging, + Metrics, ObjectReplicationMetadata, PageBlobClientClearPagesOptions, + PageBlobClientClearPagesResult, PageBlobClientClearPagesResultHeaders, + PageBlobClientCopyIncrementalResult, PageBlobClientCopyIncrementalResultHeaders, + PageBlobClientCreateOptions, PageBlobClientCreateResult, PageBlobClientCreateResultHeaders, PageBlobClientGetPageRangesOptions, PageBlobClientResizeOptions, PageBlobClientResizeResult, PageBlobClientResizeResultHeaders, PageBlobClientSetSequenceNumberOptions, PageBlobClientSetSequenceNumberResult, PageBlobClientSetSequenceNumberResultHeaders, diff --git a/sdk/storage/azure_storage_blob/tests/blob_client.rs b/sdk/storage/azure_storage_blob/tests/blob_client.rs index a211a9ab1e2..b2933743cfa 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -191,6 +191,33 @@ async fn test_delete_blob(ctx: TestContext) -> Result<(), Box> { Ok(()) } +#[recorded::test] +async fn test_undelete_blob(ctx: TestContext) -> Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let container_client = get_container_client(recording, true, StorageAccount::Standard).await?; + let blob_client = container_client.blob_client(&get_blob_name(recording)); + create_test_blob(&blob_client, None, None).await?; + + // Existence Check + blob_client.get_properties(None).await?; + + // Delete Blob + blob_client.delete(None).await?; + let response = blob_client.download(None).await; + let error = response.unwrap_err().http_status(); + assert_eq!(StatusCode::NotFound, error.unwrap()); + + // Undelete and Assert + blob_client.undelete(None).await?; + let response = blob_client.get_properties(None).await?; + let content_length = response.content_length()?; + assert_eq!(17, content_length.unwrap()); + + container_client.delete_container(None).await?; + Ok(()) +} + #[recorded::test] async fn test_download_blob(ctx: TestContext) -> Result<(), Box> { // Recording Setup diff --git a/sdk/storage/test-resources.bicep b/sdk/storage/test-resources.bicep index 1503933ddb5..5ed1783dcc9 100644 --- a/sdk/storage/test-resources.bicep +++ b/sdk/storage/test-resources.bicep @@ -57,4 +57,20 @@ resource storage 'Microsoft.Storage/storageAccounts@2024-01-01' = { } } +resource blobServices 'Microsoft.Storage/storageAccounts/blobServices@2024-01-01' = { + parent: storage + name: 'default' + properties: { + deleteRetentionPolicy: { + enabled: true + days: 1 // Number of days to retain deleted blobs (1-365) + allowPermanentDelete: false + } + containerDeleteRetentionPolicy: { + enabled: true + days: 1 // Number of days to retain deleted containers (1-365) + } + } +} + output AZURE_STORAGE_ACCOUNT_NAME string = storage.name