From 4d06e597e040dc2c6b140b54a59b3df704f09ac7 Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Wed, 3 Dec 2025 12:32:32 -0800 Subject: [PATCH 1/2] Add undelete, regen against .tsp changes, change standard acc in bicep to have softdelete enabled --- sdk/storage/.dict.txt | 1 + sdk/storage/azure_storage_blob/assets.json | 2 +- .../src/clients/blob_client.rs | 15 +- .../src/generated/clients/blob_client.rs | 107 ++----------- .../src/generated/models/enums.rs | 19 +-- .../src/generated/models/enums_impl.rs | 62 ++------ .../src/generated/models/enums_serde.rs | 30 +--- .../src/generated/models/header_traits.rs | 140 ++---------------- .../src/generated/models/method_options.rs | 3 - .../src/generated/models/pub_models.rs | 18 +-- .../azure_storage_blob/src/models/mod.rs | 75 +++++----- .../azure_storage_blob/tests/blob_client.rs | 29 ++++ .../azure_storage_blob/tsp-location.yaml | 2 +- sdk/storage/test-resources.bicep | 16 ++ 14 files changed, 151 insertions(+), 368 deletions(-) diff --git a/sdk/storage/.dict.txt b/sdk/storage/.dict.txt index 2b62121318..bd3cb830d2 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/assets.json b/sdk/storage/azure_storage_blob/assets.json index dec754804c..fcf0c1106b 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_0725bcc465", + "Tag": "rust/azure_storage_blob_cf014697d6", "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 2809efa017..92c178aae8 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -17,7 +17,8 @@ use crate::{ BlobClientGetAccountInfoOptions, BlobClientGetPropertiesOptions, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, BlobClientSetLegalHoldOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, - BlobClientSetTierOptions, BlobTags, BlockBlobClientUploadOptions, StorageErrorCode, + BlobClientSetTierOptions, BlobClientUndeleteOptions, BlobTags, + BlockBlobClientUploadOptions, StorageErrorCode, }, pipeline::StorageHeadersPolicy, AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient, @@ -450,4 +451,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/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs index c91c306f58..fc406a6526 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs @@ -9,16 +9,15 @@ use crate::generated::models::{ BlobClientBreakLeaseResult, BlobClientChangeLeaseOptions, BlobClientChangeLeaseResult, BlobClientCopyFromUrlOptions, BlobClientCopyFromUrlResult, BlobClientCreateSnapshotOptions, BlobClientCreateSnapshotResult, BlobClientDeleteImmutabilityPolicyOptions, - BlobClientDeleteImmutabilityPolicyResult, BlobClientDeleteOptions, BlobClientDownloadOptions, - BlobClientDownloadResult, BlobClientGetAccountInfoOptions, BlobClientGetAccountInfoResult, + BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientDownloadResult, + BlobClientGetAccountInfoOptions, BlobClientGetAccountInfoResult, BlobClientGetPropertiesOptions, BlobClientGetPropertiesResult, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, BlobClientReleaseLeaseResult, BlobClientRenewLeaseOptions, BlobClientRenewLeaseResult, BlobClientSetExpiryOptions, BlobClientSetExpiryResult, - BlobClientSetImmutabilityPolicyOptions, BlobClientSetImmutabilityPolicyResult, - BlobClientSetLegalHoldOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, - BlobClientSetTagsOptions, BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, - BlobClientStartCopyFromUrlResult, BlobClientUndeleteOptions, BlobClientUndeleteResult, - BlobExpiryOptions, BlobTags, + BlobClientSetImmutabilityPolicyOptions, BlobClientSetLegalHoldOptions, + BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, + BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, BlobClientStartCopyFromUrlResult, + BlobClientUndeleteOptions, BlobExpiryOptions, BlobTags, }; use azure_core::{ base64::encode, @@ -30,7 +29,7 @@ use azure_core::{ AsyncResponse, ClientOptions, Method, NoFormat, Pipeline, PipelineSendOptions, PipelineStreamOptions, Request, RequestContent, Response, Url, XmlFormat, }, - time::to_rfc7231, + time::{to_rfc7231, OffsetDateTime}, tracing, Result, }; use std::{collections::HashMap, sync::Arc}; @@ -791,34 +790,11 @@ impl BlobClient { /// # Arguments /// /// * `options` - Optional parameters for the request. - /// - /// ## Response Headers - /// - /// The returned [`Response`](azure_core::http::Response) implements the [`BlobClientDeleteImmutabilityPolicyResultHeaders`] trait, which provides - /// access to response headers. For example: - /// - /// ```no_run - /// use azure_core::{Result, http::{Response, NoFormat}}; - /// use azure_storage_blob::models::{BlobClientDeleteImmutabilityPolicyResult, BlobClientDeleteImmutabilityPolicyResultHeaders}; - /// async fn example() -> Result<()> { - /// let response: Response = unimplemented!(); - /// // Access response headers - /// if let Some(date) = response.date()? { - /// println!("Date: {:?}", date); - /// } - /// Ok(()) - /// } - /// ``` - /// - /// ### Available headers - /// * [`date`()](crate::generated::models::BlobClientDeleteImmutabilityPolicyResultHeaders::date) - Date - /// - /// [`BlobClientDeleteImmutabilityPolicyResultHeaders`]: crate::generated::models::BlobClientDeleteImmutabilityPolicyResultHeaders #[tracing::function("Storage.Blob.Blob.deleteImmutabilityPolicy")] pub async fn delete_immutability_policy( &self, options: Option>, - ) -> Result> { + ) -> Result> { let options = options.unwrap_or_default(); let ctx = options.method_options.context.to_borrowed(); let mut url = self.endpoint.clone(); @@ -1553,43 +1529,14 @@ impl BlobClient { /// /// # Arguments /// + /// * `expiry` - Specifies the date time when the blobs immutability policy is set to expire. /// * `options` - Optional parameters for the request. - /// - /// ## Response Headers - /// - /// The returned [`Response`](azure_core::http::Response) implements the [`BlobClientSetImmutabilityPolicyResultHeaders`] trait, which provides - /// access to response headers. For example: - /// - /// ```no_run - /// use azure_core::{Result, http::{Response, NoFormat}}; - /// use azure_storage_blob::models::{BlobClientSetImmutabilityPolicyResult, BlobClientSetImmutabilityPolicyResultHeaders}; - /// async fn example() -> Result<()> { - /// let response: Response = unimplemented!(); - /// // Access response headers - /// if let Some(date) = response.date()? { - /// println!("Date: {:?}", date); - /// } - /// if let Some(immutability_policy_mode) = response.immutability_policy_mode()? { - /// println!("x-ms-immutability-policy-mode: {:?}", immutability_policy_mode); - /// } - /// if let Some(immutability_policy_expires_on) = response.immutability_policy_expires_on()? { - /// println!("x-ms-immutability-policy-until-date: {:?}", immutability_policy_expires_on); - /// } - /// Ok(()) - /// } - /// ``` - /// - /// ### Available headers - /// * [`date`()](crate::generated::models::BlobClientSetImmutabilityPolicyResultHeaders::date) - Date - /// * [`immutability_policy_mode`()](crate::generated::models::BlobClientSetImmutabilityPolicyResultHeaders::immutability_policy_mode) - x-ms-immutability-policy-mode - /// * [`immutability_policy_expires_on`()](crate::generated::models::BlobClientSetImmutabilityPolicyResultHeaders::immutability_policy_expires_on) - x-ms-immutability-policy-until-date - /// - /// [`BlobClientSetImmutabilityPolicyResultHeaders`]: crate::generated::models::BlobClientSetImmutabilityPolicyResultHeaders #[tracing::function("Storage.Blob.Blob.setImmutabilityPolicy")] pub async fn set_immutability_policy( &self, + expiry: &OffsetDateTime, options: Option>, - ) -> Result> { + ) -> Result> { let options = options.unwrap_or_default(); let ctx = options.method_options.context.to_borrowed(); let mut url = self.endpoint.clone(); @@ -1616,12 +1563,7 @@ impl BlobClient { immutability_policy_mode.to_string(), ); } - if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { - request.insert_header( - "x-ms-immutability-policy-until-date", - to_rfc7231(&immutability_policy_expiry), - ); - } + request.insert_header("x-ms-immutability-policy-until-date", to_rfc7231(expiry)); request.insert_header("x-ms-version", &self.version); let rsp = self .pipeline @@ -2099,34 +2041,11 @@ impl BlobClient { /// # Arguments /// /// * `options` - Optional parameters for the request. - /// - /// ## Response Headers - /// - /// The returned [`Response`](azure_core::http::Response) implements the [`BlobClientUndeleteResultHeaders`] trait, which provides - /// access to response headers. For example: - /// - /// ```no_run - /// use azure_core::{Result, http::{Response, NoFormat}}; - /// use azure_storage_blob::models::{BlobClientUndeleteResult, BlobClientUndeleteResultHeaders}; - /// async fn example() -> Result<()> { - /// let response: Response = unimplemented!(); - /// // Access response headers - /// if let Some(date) = response.date()? { - /// println!("Date: {:?}", date); - /// } - /// Ok(()) - /// } - /// ``` - /// - /// ### Available headers - /// * [`date`()](crate::generated::models::BlobClientUndeleteResultHeaders::date) - Date - /// - /// [`BlobClientUndeleteResultHeaders`]: crate::generated::models::BlobClientUndeleteResultHeaders #[tracing::function("Storage.Blob.Blob.undelete")] pub async fn undelete( &self, options: Option>, - ) -> Result> { + ) -> Result> { let options = options.unwrap_or_default(); let ctx = options.method_options.context.to_borrowed(); let mut url = self.endpoint.clone(); diff --git a/sdk/storage/azure_storage_blob/src/generated/models/enums.rs b/sdk/storage/azure_storage_blob/src/generated/models/enums.rs index 74343ff9f9..de9c5df696 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/enums.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/enums.rs @@ -135,20 +135,6 @@ pub enum BlobExpiryOptions { UnknownValue(String), } -/// The immutability policy mode. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum BlobImmutabilityPolicyMode { - /// The immutability policy is locked. - Locked, - - /// The immutability policy is mutable. - Mutable, - - /// The immutability policy is unlocked. - Unlocked, -} - /// The blob type. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[non_exhaustive] @@ -253,13 +239,16 @@ pub enum GeoReplicationStatusType { UnknownValue(String), } -/// The immutability policy mode used in requests. +/// The immutability policy mode used in requests and responses. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[non_exhaustive] pub enum ImmutabilityPolicyMode { /// The immutability policy is locked. Locked, + /// The immutability policy is mutable. Should never be set, only returned. + Mutable, + /// The immutability policy is unlocked. Unlocked, } diff --git a/sdk/storage/azure_storage_blob/src/generated/models/enums_impl.rs b/sdk/storage/azure_storage_blob/src/generated/models/enums_impl.rs index 376b01f54d..7bad409c5f 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/enums_impl.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/enums_impl.rs @@ -5,12 +5,11 @@ use super::{ AccessTier, AccountKind, ArchiveStatus, BlobCopySourceTags, BlobDeleteType, BlobExpiryOptions, - BlobImmutabilityPolicyMode, BlobType, BlockListType, CopyStatus, DeleteSnapshotsOptionType, - EncryptionAlgorithmType, FileShareTokenIntent, FilterBlobsIncludeItem, - GeoReplicationStatusType, ImmutabilityPolicyMode, LeaseDuration, LeaseState, LeaseStatus, - ListBlobsIncludeItem, ListContainersIncludeType, PremiumPageBlobAccessTier, PublicAccessType, - QueryRequestType, QueryType, RehydratePriority, SequenceNumberActionType, SkuName, - StorageErrorCode, + BlobType, BlockListType, CopyStatus, DeleteSnapshotsOptionType, EncryptionAlgorithmType, + FileShareTokenIntent, FilterBlobsIncludeItem, GeoReplicationStatusType, ImmutabilityPolicyMode, + LeaseDuration, LeaseState, LeaseStatus, ListBlobsIncludeItem, ListContainersIncludeType, + PremiumPageBlobAccessTier, PublicAccessType, QueryRequestType, QueryType, RehydratePriority, + SequenceNumberActionType, SkuName, StorageErrorCode, }; use azure_core::error::{Error, ErrorKind}; use std::{ @@ -315,42 +314,6 @@ impl Display for BlobExpiryOptions { } } -impl FromStr for BlobImmutabilityPolicyMode { - type Err = Error; - fn from_str(s: &str) -> ::core::result::Result::Err> { - Ok(match s { - "Locked" => BlobImmutabilityPolicyMode::Locked, - "Mutable" => BlobImmutabilityPolicyMode::Mutable, - "Unlocked" => BlobImmutabilityPolicyMode::Unlocked, - _ => { - return Err(Error::with_message_fn(ErrorKind::DataConversion, || { - format!("unknown variant of BlobImmutabilityPolicyMode found: \"{s}\"") - })) - } - }) - } -} - -impl AsRef for BlobImmutabilityPolicyMode { - fn as_ref(&self) -> &str { - match self { - BlobImmutabilityPolicyMode::Locked => "Locked", - BlobImmutabilityPolicyMode::Mutable => "Mutable", - BlobImmutabilityPolicyMode::Unlocked => "Unlocked", - } - } -} - -impl Display for BlobImmutabilityPolicyMode { - fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result { - match self { - BlobImmutabilityPolicyMode::Locked => Display::fmt("Locked", f), - BlobImmutabilityPolicyMode::Mutable => Display::fmt("Mutable", f), - BlobImmutabilityPolicyMode::Unlocked => Display::fmt("Unlocked", f), - } - } -} - impl FromStr for BlobType { type Err = Error; fn from_str(s: &str) -> ::core::result::Result::Err> { @@ -644,8 +607,9 @@ impl FromStr for ImmutabilityPolicyMode { type Err = Error; fn from_str(s: &str) -> ::core::result::Result::Err> { Ok(match s { - "Locked" => ImmutabilityPolicyMode::Locked, - "Unlocked" => ImmutabilityPolicyMode::Unlocked, + "locked" => ImmutabilityPolicyMode::Locked, + "mutable" => ImmutabilityPolicyMode::Mutable, + "unlocked" => ImmutabilityPolicyMode::Unlocked, _ => { return Err(Error::with_message_fn(ErrorKind::DataConversion, || { format!("unknown variant of ImmutabilityPolicyMode found: \"{s}\"") @@ -658,8 +622,9 @@ impl FromStr for ImmutabilityPolicyMode { impl AsRef for ImmutabilityPolicyMode { fn as_ref(&self) -> &str { match self { - ImmutabilityPolicyMode::Locked => "Locked", - ImmutabilityPolicyMode::Unlocked => "Unlocked", + ImmutabilityPolicyMode::Locked => "locked", + ImmutabilityPolicyMode::Mutable => "mutable", + ImmutabilityPolicyMode::Unlocked => "unlocked", } } } @@ -667,8 +632,9 @@ impl AsRef for ImmutabilityPolicyMode { impl Display for ImmutabilityPolicyMode { fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result { match self { - ImmutabilityPolicyMode::Locked => Display::fmt("Locked", f), - ImmutabilityPolicyMode::Unlocked => Display::fmt("Unlocked", f), + ImmutabilityPolicyMode::Locked => Display::fmt("locked", f), + ImmutabilityPolicyMode::Mutable => Display::fmt("mutable", f), + ImmutabilityPolicyMode::Unlocked => Display::fmt("unlocked", f), } } } diff --git a/sdk/storage/azure_storage_blob/src/generated/models/enums_serde.rs b/sdk/storage/azure_storage_blob/src/generated/models/enums_serde.rs index 216765cd2e..df6d8aca99 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/enums_serde.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/enums_serde.rs @@ -5,12 +5,11 @@ use super::{ AccessTier, AccountKind, ArchiveStatus, BlobCopySourceTags, BlobDeleteType, BlobExpiryOptions, - BlobImmutabilityPolicyMode, BlobType, BlockListType, CopyStatus, DeleteSnapshotsOptionType, - EncryptionAlgorithmType, FileShareTokenIntent, FilterBlobsIncludeItem, - GeoReplicationStatusType, ImmutabilityPolicyMode, LeaseDuration, LeaseState, LeaseStatus, - ListBlobsIncludeItem, ListContainersIncludeType, PremiumPageBlobAccessTier, PublicAccessType, - QueryRequestType, QueryType, RehydratePriority, SequenceNumberActionType, SkuName, - StorageErrorCode, + BlobType, BlockListType, CopyStatus, DeleteSnapshotsOptionType, EncryptionAlgorithmType, + FileShareTokenIntent, FilterBlobsIncludeItem, GeoReplicationStatusType, ImmutabilityPolicyMode, + LeaseDuration, LeaseState, LeaseStatus, ListBlobsIncludeItem, ListContainersIncludeType, + PremiumPageBlobAccessTier, PublicAccessType, QueryRequestType, QueryType, RehydratePriority, + SequenceNumberActionType, SkuName, StorageErrorCode, }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -128,25 +127,6 @@ impl Serialize for BlobExpiryOptions { } } -impl<'de> Deserialize<'de> for BlobImmutabilityPolicyMode { - fn deserialize(deserializer: D) -> ::core::result::Result - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - s.parse().map_err(serde::de::Error::custom) - } -} - -impl Serialize for BlobImmutabilityPolicyMode { - fn serialize(&self, s: S) -> ::core::result::Result - where - S: Serializer, - { - s.serialize_str(self.as_ref()) - } -} - impl<'de> Deserialize<'de> for BlobType { fn deserialize(deserializer: D) -> ::core::result::Result where diff --git a/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs b/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs index 4236dd618d..57771c402a 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs @@ -8,20 +8,18 @@ use super::{ AppendBlobClientCreateResult, AppendBlobClientSealResult, ArchiveStatus, BlobClientAbortCopyFromUrlResult, BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, BlobClientCopyFromUrlResult, BlobClientCreateSnapshotResult, - BlobClientDeleteImmutabilityPolicyResult, BlobClientDownloadResult, - BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, - BlobClientRenewLeaseResult, BlobClientSetExpiryResult, BlobClientSetImmutabilityPolicyResult, - BlobClientStartCopyFromUrlResult, BlobClientUndeleteResult, - BlobContainerClientAcquireLeaseResult, BlobContainerClientBreakLeaseResult, - BlobContainerClientChangeLeaseResult, BlobContainerClientGetAccountInfoResult, - BlobContainerClientGetPropertiesResult, BlobContainerClientReleaseLeaseResult, - BlobContainerClientRenameResult, BlobContainerClientRenewLeaseResult, - BlobContainerClientRestoreResult, BlobImmutabilityPolicyMode, + BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, + BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientSetExpiryResult, + BlobClientStartCopyFromUrlResult, BlobContainerClientAcquireLeaseResult, + BlobContainerClientBreakLeaseResult, BlobContainerClientChangeLeaseResult, + BlobContainerClientGetAccountInfoResult, BlobContainerClientGetPropertiesResult, + BlobContainerClientReleaseLeaseResult, BlobContainerClientRenameResult, + BlobContainerClientRenewLeaseResult, BlobContainerClientRestoreResult, BlobServiceClientGetAccountInfoResult, BlobTags, BlobType, BlockBlobClientCommitBlockListResult, BlockBlobClientQueryResult, BlockBlobClientStageBlockFromUrlResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadBlobFromUrlResult, BlockBlobClientUploadResult, BlockList, CopyStatus, - LeaseDuration, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, + ImmutabilityPolicyMode, LeaseDuration, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, ListBlobsHierarchySegmentResponse, PageBlobClientClearPagesResult, PageBlobClientCopyIncrementalResult, PageBlobClientCreateResult, PageBlobClientResizeResult, PageBlobClientSetSequenceNumberResult, PageBlobClientUploadPagesFromUrlResult, @@ -737,35 +735,6 @@ impl BlobClientCreateSnapshotResultHeaders for Response Result<()> { -/// let response: Response = unimplemented!(); -/// // Access response headers -/// if let Some(date) = response.date()? { -/// println!("Date: {:?}", date); -/// } -/// Ok(()) -/// } -/// ``` -pub trait BlobClientDeleteImmutabilityPolicyResultHeaders: private::Sealed { - fn date(&self) -> Result>; -} - -impl BlobClientDeleteImmutabilityPolicyResultHeaders - for Response -{ - /// UTC date/time value generated by the service that indicates the time at which the response was initiated - fn date(&self) -> Result> { - Headers::get_optional_with(self.headers(), &DATE, |h| parse_rfc7231(h.as_str())) - } -} - /// Provides access to typed response headers for `BlobClient::download()` /// /// # Examples @@ -813,7 +782,7 @@ pub trait BlobClientDownloadResultHeaders: private::Sealed { fn creation_time(&self) -> Result>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; - fn immutability_policy_mode(&self) -> Result>; + fn immutability_policy_mode(&self) -> Result>; fn immutability_policy_expires_on(&self) -> Result>; fn is_current_version(&self) -> Result>; fn last_accessed(&self) -> Result>; @@ -979,7 +948,7 @@ impl BlobClientDownloadResultHeaders for AsyncResponse } /// Indicates the immutability policy mode of the blob. - fn immutability_policy_mode(&self) -> Result> { + fn immutability_policy_mode(&self) -> Result> { Headers::get_optional_as(self.headers(), &IMMUTABILITY_POLICY_MODE) } @@ -1173,7 +1142,7 @@ pub trait BlobClientGetPropertiesResultHeaders: private::Sealed { fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn expires_on(&self) -> Result>; - fn immutability_policy_mode(&self) -> Result>; + fn immutability_policy_mode(&self) -> Result>; fn immutability_policy_expires_on(&self) -> Result>; fn is_incremental_copy(&self) -> Result>; fn is_current_version(&self) -> Result>; @@ -1361,7 +1330,7 @@ impl BlobClientGetPropertiesResultHeaders for Response Result> { + fn immutability_policy_mode(&self) -> Result> { Headers::get_optional_as(self.headers(), &IMMUTABILITY_POLICY_MODE) } @@ -1597,55 +1566,6 @@ impl BlobClientSetExpiryResultHeaders for Response Result<()> { -/// let response: Response = unimplemented!(); -/// // Access response headers -/// if let Some(date) = response.date()? { -/// println!("Date: {:?}", date); -/// } -/// if let Some(immutability_policy_mode) = response.immutability_policy_mode()? { -/// println!("x-ms-immutability-policy-mode: {:?}", immutability_policy_mode); -/// } -/// if let Some(immutability_policy_expires_on) = response.immutability_policy_expires_on()? { -/// println!("x-ms-immutability-policy-until-date: {:?}", immutability_policy_expires_on); -/// } -/// Ok(()) -/// } -/// ``` -pub trait BlobClientSetImmutabilityPolicyResultHeaders: private::Sealed { - fn date(&self) -> Result>; - fn immutability_policy_mode(&self) -> Result>; - fn immutability_policy_expires_on(&self) -> Result>; -} - -impl BlobClientSetImmutabilityPolicyResultHeaders - for Response -{ - /// UTC date/time value generated by the service that indicates the time at which the response was initiated - fn date(&self) -> Result> { - Headers::get_optional_with(self.headers(), &DATE, |h| parse_rfc7231(h.as_str())) - } - - /// Indicates the immutability policy mode of the blob. - fn immutability_policy_mode(&self) -> Result> { - Headers::get_optional_as(self.headers(), &IMMUTABILITY_POLICY_MODE) - } - - /// UTC date/time value generated by the service that indicates the time at which the blob immutability policy will expire. - fn immutability_policy_expires_on(&self) -> Result> { - Headers::get_optional_with(self.headers(), &IMMUTABILITY_POLICY_UNTIL_DATE, |h| { - parse_rfc7231(h.as_str()) - }) - } -} - /// Provides access to typed response headers for `BlobClient::start_copy_from_url()` /// /// # Examples @@ -1715,33 +1635,6 @@ impl BlobClientStartCopyFromUrlResultHeaders } } -/// Provides access to typed response headers for `BlobClient::undelete()` -/// -/// # Examples -/// -/// ```no_run -/// use azure_core::{Result, http::{Response, NoFormat}}; -/// use azure_storage_blob::models::{BlobClientUndeleteResult, BlobClientUndeleteResultHeaders}; -/// async fn example() -> Result<()> { -/// let response: Response = unimplemented!(); -/// // Access response headers -/// if let Some(date) = response.date()? { -/// println!("Date: {:?}", date); -/// } -/// Ok(()) -/// } -/// ``` -pub trait BlobClientUndeleteResultHeaders: private::Sealed { - fn date(&self) -> Result>; -} - -impl BlobClientUndeleteResultHeaders for Response { - /// UTC date/time value generated by the service that indicates the time at which the response was initiated - fn date(&self) -> Result> { - Headers::get_optional_with(self.headers(), &DATE, |h| parse_rfc7231(h.as_str())) - } -} - /// Provides access to typed response headers for `BlobContainerClient::acquire_lease()` /// /// # Examples @@ -3604,12 +3497,10 @@ mod private { AppendBlobClientAppendBlockFromUrlResult, AppendBlobClientAppendBlockResult, AppendBlobClientCreateResult, AppendBlobClientSealResult, BlobClientAbortCopyFromUrlResult, BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, - BlobClientCopyFromUrlResult, BlobClientCreateSnapshotResult, - BlobClientDeleteImmutabilityPolicyResult, BlobClientDownloadResult, + BlobClientCopyFromUrlResult, BlobClientCreateSnapshotResult, BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientSetExpiryResult, - BlobClientSetImmutabilityPolicyResult, BlobClientStartCopyFromUrlResult, - BlobClientUndeleteResult, BlobContainerClientAcquireLeaseResult, + BlobClientStartCopyFromUrlResult, BlobContainerClientAcquireLeaseResult, BlobContainerClientBreakLeaseResult, BlobContainerClientChangeLeaseResult, BlobContainerClientGetAccountInfoResult, BlobContainerClientGetPropertiesResult, BlobContainerClientReleaseLeaseResult, BlobContainerClientRenameResult, @@ -3640,15 +3531,12 @@ mod private { impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} - impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} - impl Sealed for Response {} impl Sealed for Response {} - impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} impl Sealed for Response {} diff --git a/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs b/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs index 2e7ac54d82..01227331e4 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs @@ -781,9 +781,6 @@ pub struct BlobClientSetImmutabilityPolicyOptions<'a> { /// A date-time value. A request is made under the condition that the resource has not been modified since the specified date-time. pub if_unmodified_since: Option, - /// Specifies the date time when the blobs immutability policy is set to expire. - pub immutability_policy_expiry: Option, - /// Specifies the immutability policy mode to set on the blob. pub immutability_policy_mode: Option, diff --git a/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs b/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs index 4c509d07fa..4389bed7e2 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs @@ -9,8 +9,8 @@ use super::{ Blob_tag_setTag, BlobsBlob, Committed_blocksBlock, Container_itemsContainer, CorsCorsRule, SchemaField, Uncommitted_blocksBlock, }, - AccessTier, ArchiveStatus, BlobImmutabilityPolicyMode, BlobType, CopyStatus, - GeoReplicationStatusType, LeaseDuration, LeaseState, LeaseStatus, PublicAccessType, + AccessTier, ArchiveStatus, BlobType, CopyStatus, GeoReplicationStatusType, + ImmutabilityPolicyMode, LeaseDuration, LeaseState, LeaseStatus, PublicAccessType, QueryRequestType, QueryType, RehydratePriority, }; use azure_core::{ @@ -123,10 +123,6 @@ pub struct BlobClientCopyFromUrlResult; #[derive(SafeDebug)] pub struct BlobClientCreateSnapshotResult; -/// Contains results for `BlobClient::delete_immutability_policy()` -#[derive(SafeDebug)] -pub struct BlobClientDeleteImmutabilityPolicyResult; - /// Contains results for `BlobClient::download()` #[derive(SafeDebug)] pub struct BlobClientDownloadResult; @@ -151,18 +147,10 @@ pub struct BlobClientRenewLeaseResult; #[derive(SafeDebug)] pub struct BlobClientSetExpiryResult; -/// Contains results for `BlobClient::set_immutability_policy()` -#[derive(SafeDebug)] -pub struct BlobClientSetImmutabilityPolicyResult; - /// Contains results for `BlobClient::start_copy_from_url()` #[derive(SafeDebug)] pub struct BlobClientStartCopyFromUrlResult; -/// Contains results for `BlobClient::undelete()` -#[derive(SafeDebug)] -pub struct BlobClientUndeleteResult; - /// Contains results for `BlobContainerClient::acquire_lease()` #[derive(SafeDebug)] pub struct BlobContainerClientAcquireLeaseResult; @@ -469,7 +457,7 @@ pub struct BlobPropertiesInternal { rename = "ImmutabilityPolicyMode", skip_serializing_if = "Option::is_none" )] - pub immutability_policy_mode: Option, + pub immutability_policy_mode: Option, /// Whether the blob is incremental copy. #[serde(rename = "IncrementalCopy", skip_serializing_if = "Option::is_none")] diff --git a/sdk/storage/azure_storage_blob/src/models/mod.rs b/sdk/storage/azure_storage_blob/src/models/mod.rs index 17c4782f04..5be3cd26c9 100644 --- a/sdk/storage/azure_storage_blob/src/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/models/mod.rs @@ -16,20 +16,17 @@ pub use crate::generated::models::{ BlobClientBreakLeaseResultHeaders, BlobClientChangeLeaseOptions, BlobClientChangeLeaseResult, BlobClientChangeLeaseResultHeaders, BlobClientCopyFromUrlResult, BlobClientCopyFromUrlResultHeaders, BlobClientCreateSnapshotResult, - BlobClientCreateSnapshotResultHeaders, BlobClientDeleteImmutabilityPolicyResult, - BlobClientDeleteImmutabilityPolicyResultHeaders, BlobClientDeleteOptions, - BlobClientDownloadOptions, BlobClientDownloadResult, BlobClientDownloadResultHeaders, - BlobClientGetAccountInfoOptions, BlobClientGetAccountInfoResult, - BlobClientGetAccountInfoResultHeaders, BlobClientGetPropertiesOptions, - BlobClientGetPropertiesResult, BlobClientGetPropertiesResultHeaders, BlobClientGetTagsOptions, - BlobClientReleaseLeaseOptions, BlobClientReleaseLeaseResult, - BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, BlobClientRenewLeaseResult, - BlobClientRenewLeaseResultHeaders, BlobClientSetExpiryResult, BlobClientSetExpiryResultHeaders, - BlobClientSetImmutabilityPolicyResult, BlobClientSetImmutabilityPolicyResultHeaders, - BlobClientSetLegalHoldOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, - BlobClientSetTagsOptions, BlobClientSetTierOptions, BlobClientStartCopyFromUrlResult, - BlobClientStartCopyFromUrlResultHeaders, BlobClientUndeleteResult, - BlobClientUndeleteResultHeaders, BlobContainerClientAcquireLeaseOptions, + BlobClientCreateSnapshotResultHeaders, BlobClientDeleteOptions, BlobClientDownloadOptions, + BlobClientDownloadResult, BlobClientDownloadResultHeaders, BlobClientGetAccountInfoOptions, + BlobClientGetAccountInfoResult, BlobClientGetAccountInfoResultHeaders, + BlobClientGetPropertiesOptions, BlobClientGetPropertiesResult, + BlobClientGetPropertiesResultHeaders, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, + BlobClientReleaseLeaseResult, BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, + BlobClientRenewLeaseResult, BlobClientRenewLeaseResultHeaders, BlobClientSetExpiryResult, + BlobClientSetExpiryResultHeaders, BlobClientSetLegalHoldOptions, BlobClientSetMetadataOptions, + BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, + BlobClientStartCopyFromUrlResult, BlobClientStartCopyFromUrlResultHeaders, + BlobClientUndeleteOptions, BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, BlobContainerClientChangeLeaseOptions, @@ -45,31 +42,31 @@ pub use crate::generated::models::{ BlobContainerClientRenewLeaseResult, BlobContainerClientRenewLeaseResultHeaders, BlobContainerClientRestoreResult, BlobContainerClientRestoreResultHeaders, BlobContainerClientSetAccessPolicyOptions, BlobContainerClientSetMetadataOptions, - BlobCopySourceTags, BlobDeleteType, BlobExpiryOptions, BlobFlatListSegment, - BlobImmutabilityPolicyMode, BlobItemInternal, BlobMetadata, BlobName, BlobPropertiesInternal, - BlobServiceClientFindBlobsByTagsOptions, BlobServiceClientGetAccountInfoOptions, - BlobServiceClientGetAccountInfoResult, BlobServiceClientGetAccountInfoResultHeaders, - BlobServiceClientGetPropertiesOptions, 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, GeoReplicationStatusType, ImmutabilityPolicyMode, LeaseDuration, - LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, ListBlobsFlatSegmentResponseHeaders, - ListBlobsHierarchySegmentResponse, ListBlobsHierarchySegmentResponseHeaders, - ListBlobsIncludeItem, ListContainersIncludeType, ListContainersSegmentResponse, Logging, - Metrics, ObjectReplicationMetadata, PageBlobClientClearPagesOptions, - PageBlobClientClearPagesResult, PageBlobClientClearPagesResultHeaders, - PageBlobClientCopyIncrementalResult, PageBlobClientCopyIncrementalResultHeaders, - PageBlobClientCreateOptions, PageBlobClientCreateResult, PageBlobClientCreateResultHeaders, + BlobCopySourceTags, BlobDeleteType, BlobExpiryOptions, BlobFlatListSegment, BlobItemInternal, + BlobMetadata, BlobName, BlobPropertiesInternal, BlobServiceClientFindBlobsByTagsOptions, + BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetAccountInfoResult, + BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, + 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, 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 f7f108c803..b34a52b511 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -187,6 +187,35 @@ 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).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?; + + blob_client.delete(None).await?; + + let response = blob_client.download(None).await; + + // Assert + 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/azure_storage_blob/tsp-location.yaml b/sdk/storage/azure_storage_blob/tsp-location.yaml index 68483e5e13..2a93f114ce 100644 --- a/sdk/storage/azure_storage_blob/tsp-location.yaml +++ b/sdk/storage/azure_storage_blob/tsp-location.yaml @@ -1,4 +1,4 @@ directory: specification/storage/Microsoft.BlobStorage -commit: 76ab9e72c8747dc01f2f406caa796d03160b813d +commit: c944e7a69343bca09148d268e57427028a037868 repo: Azure/azure-rest-api-specs additionalDirectories: diff --git a/sdk/storage/test-resources.bicep b/sdk/storage/test-resources.bicep index 1503933ddb..5ed1783dcc 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 From 1f8826cbbb5fad49908652cb830c4486caa654fd Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Thu, 4 Dec 2025 15:53:29 -0800 Subject: [PATCH 2/2] regen against blob feature branch --- sdk/storage/azure_storage_blob/tsp-location.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure_storage_blob/tsp-location.yaml b/sdk/storage/azure_storage_blob/tsp-location.yaml index 2a93f114ce..a3e4bc01c7 100644 --- a/sdk/storage/azure_storage_blob/tsp-location.yaml +++ b/sdk/storage/azure_storage_blob/tsp-location.yaml @@ -1,4 +1,4 @@ directory: specification/storage/Microsoft.BlobStorage -commit: c944e7a69343bca09148d268e57427028a037868 +commit: e7ed1502f278035e93d6b0c50c69a48747bb01e3 repo: Azure/azure-rest-api-specs additionalDirectories: