From b5bed2e016acdd5f2f6946c044425440fb3dabbb Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Tue, 15 Jul 2025 14:00:16 -0700 Subject: [PATCH 01/10] start_copy_from_url, set_properties --- .../src/clients/blob_client.rs | 28 ++++++++++++-- .../src/clients/blob_service_client.rs | 21 ++++++++++- .../azure_storage_blob/src/models/mod.rs | 30 ++++++++------- .../azure_storage_blob/tests/blob_client.rs | 37 ++++++++++++++++++- .../tests/blob_service_client.rs | 26 +++++++++++++ 5 files changed, 120 insertions(+), 22 deletions(-) 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 1c2564d279..72ebd82665 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -6,16 +6,17 @@ use crate::{ generated::models::{ BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, BlobClientDownloadResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, - BlobClientRenewLeaseResult, BlockBlobClientCommitBlockListResult, - BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, + BlobClientRenewLeaseResult, BlobClientStartCopyFromUrlResult, + BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, + BlockBlobClientUploadResult, }, models::{ AccessTier, BlobClientAcquireLeaseOptions, BlobClientBreakLeaseOptions, BlobClientChangeLeaseOptions, BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions, BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, - BlockBlobClientCommitBlockListOptions, BlockBlobClientUploadOptions, BlockList, - BlockListType, BlockLookupList, + BlobClientStartCopyFromUrlOptions, BlockBlobClientCommitBlockListOptions, + BlockBlobClientUploadOptions, BlockList, BlockListType, BlockLookupList, }, pipeline::StorageHeadersPolicy, AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient, @@ -313,4 +314,23 @@ impl BlobClient { ) -> Result> { self.client.renew_lease(lease_id, options).await } + + /// Copies a blob or an internet resource to a new blob. + /// + /// # Arguments + /// + /// * `copy_source` - A URL of up to 2 KB in length that specifies a file or blob. + /// The value should be URL-encoded as it would appear in a request URI. + /// If the source is in another account, the source must either be public + /// or must be authenticated via a shared access signature. If the source + /// is public, no authentication is required. + /// Example: https://myaccount.blob.core.windows.net/mycontainer/myblob + /// * `options` - Optional configuration for the request. + pub async fn start_copy_from_url( + &self, + copy_source: String, + options: Option>, + ) -> Result> { + self.client.start_copy_from_url(copy_source, options).await + } } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs index 1f2c04bec8..60b1d8156b 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs @@ -5,7 +5,8 @@ use crate::{ generated::clients::BlobServiceClient as GeneratedBlobServiceClient, models::{ BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, - ListContainersSegmentResponse, StorageServiceProperties, + BlobServiceClientSetPropertiesOptions, ListContainersSegmentResponse, + StorageServiceProperties, }, pipeline::StorageHeadersPolicy, BlobContainerClient, BlobServiceClientOptions, @@ -14,7 +15,7 @@ use azure_core::{ credentials::TokenCredential, http::{ policies::{BearerTokenCredentialPolicy, Policy}, - PageIterator, Response, Url, XmlFormat, + NoFormat, PageIterator, RequestContent, Response, Url, XmlFormat, }, Result, }; @@ -104,4 +105,20 @@ impl BlobServiceClient { ) -> Result>> { self.client.list_containers_segment(options) } + + /// Sets properties for a Storage account's Blob service endpoint, including properties for Storage Analytics and CORS rules. + /// + /// # Arguments + /// + /// * `storage_service_properties` - The Storage service properties to set. + /// * `options` - Optional configuration for the request. + pub async fn set_properties( + &self, + storage_service_properties: RequestContent, + options: Option>, + ) -> Result> { + self.client + .set_properties(storage_service_properties, 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 cd90fd3616..9bd29d7540 100644 --- a/sdk/storage/azure_storage_blob/src/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/models/mod.rs @@ -19,7 +19,8 @@ pub use crate::generated::models::{ BlobClientReleaseLeaseOptions, BlobClientReleaseLeaseResult, BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, BlobClientRenewLeaseResult, BlobClientRenewLeaseResultHeaders, BlobClientSetMetadataOptions, - BlobClientSetPropertiesOptions, BlobClientSetTierOptions, + BlobClientSetPropertiesOptions, BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, + BlobClientStartCopyFromUrlResult, BlobClientStartCopyFromUrlResultHeaders, BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, @@ -31,18 +32,19 @@ pub use crate::generated::models::{ BlobContainerClientReleaseLeaseResult, BlobContainerClientReleaseLeaseResultHeaders, BlobContainerClientRenewLeaseOptions, BlobContainerClientRenewLeaseResult, BlobContainerClientSetMetadataOptions, BlobImmutabilityPolicyMode, - BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, BlobType, - BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, - BlockBlobClientCommitBlockListResultHeaders, BlockBlobClientGetBlockListOptions, - BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, - BlockBlobClientStageBlockResultHeaders, BlockBlobClientUploadOptions, - BlockBlobClientUploadResult, BlockBlobClientUploadResultHeaders, BlockList, BlockListType, - BlockLookupList, CopyStatus, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, - ListContainersSegmentResponse, PageBlobClientClearPagesOptions, PageBlobClientClearPagesResult, - PageBlobClientClearPagesResultHeaders, PageBlobClientCreateOptions, PageBlobClientCreateResult, - PageBlobClientCreateResultHeaders, PageBlobClientResizeOptions, PageBlobClientResizeResult, - PageBlobClientResizeResultHeaders, PageBlobClientUploadPagesOptions, - PageBlobClientUploadPagesResult, PageBlobClientUploadPagesResultHeaders, PublicAccessType, - RehydratePriority, StorageServiceProperties, + BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, + BlobServiceClientSetPropertiesOptions, BlobType, BlockBlobClientCommitBlockListOptions, + BlockBlobClientCommitBlockListResult, BlockBlobClientCommitBlockListResultHeaders, + BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, + BlockBlobClientStageBlockResult, BlockBlobClientStageBlockResultHeaders, + BlockBlobClientUploadOptions, BlockBlobClientUploadResult, BlockBlobClientUploadResultHeaders, + BlockList, BlockListType, BlockLookupList, CopyStatus, LeaseState, LeaseStatus, + ListBlobsFlatSegmentResponse, ListContainersSegmentResponse, PageBlobClientClearPagesOptions, + PageBlobClientClearPagesResult, PageBlobClientClearPagesResultHeaders, + PageBlobClientCreateOptions, PageBlobClientCreateResult, PageBlobClientCreateResultHeaders, + PageBlobClientResizeOptions, PageBlobClientResizeResult, PageBlobClientResizeResultHeaders, + PageBlobClientUploadPagesOptions, PageBlobClientUploadPagesResult, + PageBlobClientUploadPagesResultHeaders, PublicAccessType, RehydratePriority, + StorageServiceProperties, }; pub use extensions::*; diff --git a/sdk/storage/azure_storage_blob/tests/blob_client.rs b/sdk/storage/azure_storage_blob/tests/blob_client.rs index 5d5818b2f9..759a12111a 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -10,8 +10,8 @@ use azure_storage_blob::models::{ AccessTier, BlobClientAcquireLeaseResultHeaders, BlobClientChangeLeaseResultHeaders, BlobClientDownloadOptions, BlobClientDownloadResultHeaders, BlobClientGetPropertiesOptions, BlobClientGetPropertiesResultHeaders, BlobClientSetMetadataOptions, - BlobClientSetPropertiesOptions, BlobClientSetTierOptions, BlockBlobClientUploadOptions, - LeaseState, + BlobClientSetPropertiesOptions, BlobClientSetTierOptions, + BlobClientStartCopyFromUrlResultHeaders, BlockBlobClientUploadOptions, CopyStatus, LeaseState, }; use azure_storage_blob_test::{create_test_blob, get_blob_name, get_container_client}; use std::{collections::HashMap, error::Error, time::Duration}; @@ -423,3 +423,36 @@ async fn test_leased_blob_operations(ctx: TestContext) -> Result<(), Box Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let container_client = get_container_client(recording, true).await?; + let source_blob_client = container_client.blob_client(get_blob_name(recording)); + create_test_blob(&source_blob_client).await?; + + let blob_client = container_client.blob_client("destination_blob".to_string()); + let source_url = format!( + "{}{}/{}", + source_blob_client.endpoint().as_str(), + source_blob_client.container_name(), + source_blob_client.blob_name() + ); + let response = blob_client.start_copy_from_url(source_url, None).await?; + let (_, _, source_content) = source_blob_client.download(None).await?.deconstruct(); + let (_, _, copied_content) = blob_client.download(None).await?.deconstruct(); + + // Assert + let copy_status = response.copy_status()?; + let copy_id = response.copy_id()?; + assert_eq!(CopyStatus::Success, copy_status.unwrap()); + assert!(copy_id.is_some()); + assert_eq!( + source_content.collect().await?, + copied_content.collect().await? + ); + + container_client.delete_container(None).await?; + Ok(()) +} diff --git a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs index db5ac45d91..80dc8cb06e 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use azure_core::http::RequestContent; use azure_core_test::{recorded, TestContext}; use azure_storage_blob::models::{ BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, + StorageServiceProperties, }; use azure_storage_blob_test::{get_blob_service_client, get_container_name}; use futures::StreamExt; @@ -122,3 +124,27 @@ async fn test_list_containers_with_continuation(ctx: TestContext) -> Result<(), Ok(()) } + +#[recorded::test] +async fn test_set_service_properties(ctx: TestContext) -> Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let service_client = get_blob_service_client(recording)?; + + // Storage Service Properties + let storage_service_properties = StorageServiceProperties { + default_service_version: Some("2022-11-02".to_string()), + ..Default::default() + }; + let request_content: RequestContent = + storage_service_properties.try_into()?; + + service_client.set_properties(request_content, None).await?; + + // Assert + let response = service_client.get_properties(None).await?; + let storage_service_properties = response.into_body().await?; + let default_service_version = storage_service_properties.default_service_version; + assert_eq!("2022-11-02".to_string(), default_service_version.unwrap()); + Ok(()) +} From 7e7f9a90f6525432efa9e19594de862a0b799eff Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Tue, 15 Jul 2025 14:21:25 -0700 Subject: [PATCH 02/10] get_account_info, set/get tags --- .../src/clients/blob_client.rs | 65 ++++++++++++++++--- .../src/clients/blob_container_client.rs | 26 ++++++-- .../src/clients/blob_service_client.rs | 20 +++++- .../azure_storage_blob/src/models/mod.rs | 48 +++++++------- sdk/storage/azure_storage_blob/src/parsers.rs | 23 +++++++ .../azure_storage_blob/tests/blob_client.rs | 63 +++++++++++++++++- .../tests/blob_container_client.rs | 22 ++++++- .../tests/blob_service_client.rs | 20 ++++++ .../azure_storage_blob_test/src/lib.rs | 31 ++++++++- 9 files changed, 273 insertions(+), 45 deletions(-) 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 72ebd82665..cb38776779 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -5,21 +5,22 @@ use crate::{ generated::clients::BlobClient as GeneratedBlobClient, generated::models::{ BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, - BlobClientDownloadResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, - BlobClientRenewLeaseResult, BlobClientStartCopyFromUrlResult, - BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, - BlockBlobClientUploadResult, + BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, + BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientSetTagsResult, + BlobClientStartCopyFromUrlResult, BlockBlobClientCommitBlockListResult, + BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, }, models::{ AccessTier, BlobClientAcquireLeaseOptions, BlobClientBreakLeaseOptions, BlobClientChangeLeaseOptions, BlobClientDeleteOptions, BlobClientDownloadOptions, - BlobClientGetPropertiesOptions, BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, - BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, - BlobClientStartCopyFromUrlOptions, BlockBlobClientCommitBlockListOptions, + BlobClientGetAccountInfoOptions, BlobClientGetPropertiesOptions, BlobClientGetTagsOptions, + BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, BlobClientSetMetadataOptions, + BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, + BlobClientStartCopyFromUrlOptions, BlobTags, BlockBlobClientCommitBlockListOptions, BlockBlobClientUploadOptions, BlockList, BlockListType, BlockLookupList, }, pipeline::StorageHeadersPolicy, - AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient, + serialize_blob_tags, AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient, }; use azure_core::{ credentials::TokenCredential, @@ -29,6 +30,7 @@ use azure_core::{ }, Bytes, Result, }; +use std::collections::HashMap; use std::sync::Arc; /// A client to interact with a specific Azure storage blob, although that blob may not yet exist. @@ -333,4 +335,51 @@ impl BlobClient { ) -> Result> { self.client.start_copy_from_url(copy_source, options).await } + + /// Sets tags on a blob. Note that each call to this operation replaces all existing tags. To remove + /// all tags from the blob, call this operation with no tags specified. + /// + /// # Arguments + /// + /// * `tags` - Name-value pairs associated with the blob as tag. Tags are case-sensitive. + /// The tag set may contain at most 10 tags. Tag keys must be between 1 and 128 characters, + /// and tag values must be between 0 and 256 characters. + /// Valid tag key and value characters include: lowercase and uppercase letters, digits (0-9), + /// space (' '), plus (+), minus (-), period (.), solidus (/), colon (:), equals (=), underscore (_) + /// * `options` - Optional configuration for the request. + pub async fn set_tags( + &self, + tags: HashMap, + options: Option>, + ) -> Result> { + let blob_tags = serialize_blob_tags(tags); + self.client + .set_tags(RequestContent::try_from(blob_tags)?, options) + .await + } + + /// Gets the tags on a blob. + /// + /// # Arguments + /// + /// * `options` - Optional configuration for the request. + pub async fn get_tags( + &self, + options: Option>, + ) -> Result> { + self.client.get_tags(options).await + } + + /// Gets information related to the Storage account in which the blob resides. + /// This includes the `sku_name` and `account_kind`. + /// + /// # Arguments + /// + /// * `options` - Optional configuration for the request. + pub async fn get_account_info( + &self, + options: Option>, + ) -> Result> { + self.client.get_account_info(options).await + } } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs index 01a785cb26..1b397e2ca3 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs @@ -5,16 +5,17 @@ use crate::{ generated::clients::BlobContainerClient as GeneratedBlobContainerClient, generated::models::{ BlobContainerClientAcquireLeaseResult, BlobContainerClientBreakLeaseResult, - BlobContainerClientChangeLeaseResult, BlobContainerClientGetPropertiesResult, - BlobContainerClientReleaseLeaseResult, BlobContainerClientRenewLeaseResult, + BlobContainerClientChangeLeaseResult, BlobContainerClientGetAccountInfoResult, + BlobContainerClientGetPropertiesResult, BlobContainerClientReleaseLeaseResult, + BlobContainerClientRenewLeaseResult, }, models::{ BlobContainerClientAcquireLeaseOptions, BlobContainerClientBreakLeaseOptions, BlobContainerClientChangeLeaseOptions, BlobContainerClientCreateOptions, - BlobContainerClientDeleteOptions, BlobContainerClientGetPropertiesOptions, - BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientReleaseLeaseOptions, - BlobContainerClientRenewLeaseOptions, BlobContainerClientSetMetadataOptions, - ListBlobsFlatSegmentResponse, + BlobContainerClientDeleteOptions, BlobContainerClientGetAccountInfoOptions, + BlobContainerClientGetPropertiesOptions, BlobContainerClientListBlobFlatSegmentOptions, + BlobContainerClientReleaseLeaseOptions, BlobContainerClientRenewLeaseOptions, + BlobContainerClientSetMetadataOptions, ListBlobsFlatSegmentResponse, }, pipeline::StorageHeadersPolicy, BlobClient, BlobContainerClientOptions, @@ -242,4 +243,17 @@ impl BlobContainerClient { ) -> Result> { self.client.renew_lease(lease_id, options).await } + + /// Gets information related to the Storage account in which the container resides. + /// This includes the `sku_name` and `account_kind`. + /// + /// # Arguments + /// + /// * `options` - Optional configuration for the request. + pub async fn get_account_info( + &self, + options: Option>, + ) -> Result> { + self.client.get_account_info(options).await + } } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs index 60b1d8156b..1b049f7265 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs @@ -3,10 +3,11 @@ use crate::{ generated::clients::BlobServiceClient as GeneratedBlobServiceClient, + generated::models::BlobServiceClientGetAccountInfoResult, models::{ - BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, - BlobServiceClientSetPropertiesOptions, ListContainersSegmentResponse, - StorageServiceProperties, + BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetPropertiesOptions, + BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, + ListContainersSegmentResponse, StorageServiceProperties, }, pipeline::StorageHeadersPolicy, BlobContainerClient, BlobServiceClientOptions, @@ -121,4 +122,17 @@ impl BlobServiceClient { .set_properties(storage_service_properties, options) .await } + + /// Gets information related to the Storage account. + /// This includes the `sku_name` and `account_kind`. + /// + /// # Arguments + /// + /// * `options` - Optional configuration for the request. + pub async fn get_account_info( + &self, + options: Option>, + ) -> Result> { + self.client.get_account_info(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 9bd29d7540..5f9c3a3b68 100644 --- a/sdk/storage/azure_storage_blob/src/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/models/mod.rs @@ -4,7 +4,7 @@ mod extensions; pub use crate::generated::models::{ - AccessTier, AppendBlobClientAppendBlockFromUrlOptions, + AccessTier, AccountKind, AppendBlobClientAppendBlockFromUrlOptions, AppendBlobClientAppendBlockFromUrlResult, AppendBlobClientAppendBlockFromUrlResultHeaders, AppendBlobClientAppendBlockOptions, AppendBlobClientAppendBlockResult, AppendBlobClientAppendBlockResultHeaders, AppendBlobClientCreateOptions, @@ -14,37 +14,41 @@ pub use crate::generated::models::{ BlobClientAcquireLeaseResultHeaders, BlobClientBreakLeaseOptions, BlobClientBreakLeaseResult, BlobClientBreakLeaseResultHeaders, BlobClientChangeLeaseOptions, BlobClientChangeLeaseResult, BlobClientChangeLeaseResultHeaders, BlobClientDeleteOptions, BlobClientDownloadOptions, - BlobClientDownloadResult, BlobClientDownloadResultHeaders, BlobClientGetPropertiesOptions, - BlobClientGetPropertiesResult, BlobClientGetPropertiesResultHeaders, - BlobClientReleaseLeaseOptions, BlobClientReleaseLeaseResult, - BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, BlobClientRenewLeaseResult, - BlobClientRenewLeaseResultHeaders, BlobClientSetMetadataOptions, - BlobClientSetPropertiesOptions, BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, + BlobClientDownloadResult, BlobClientDownloadResultHeaders, BlobClientGetAccountInfoOptions, + BlobClientGetAccountInfoResult, BlobClientGetAccountInfoResultHeaders, + BlobClientGetPropertiesOptions, BlobClientGetPropertiesResult, + BlobClientGetPropertiesResultHeaders, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, + BlobClientReleaseLeaseResult, BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, + BlobClientRenewLeaseResult, BlobClientRenewLeaseResultHeaders, BlobClientSetMetadataOptions, + BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTagsResult, + BlobClientSetTagsResultHeaders, BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, BlobClientStartCopyFromUrlResult, BlobClientStartCopyFromUrlResultHeaders, BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, BlobContainerClientChangeLeaseOptions, BlobContainerClientChangeLeaseResult, BlobContainerClientChangeLeaseResultHeaders, BlobContainerClientCreateOptions, - BlobContainerClientDeleteOptions, BlobContainerClientGetPropertiesOptions, + BlobContainerClientDeleteOptions, BlobContainerClientGetAccountInfoOptions, + BlobContainerClientGetAccountInfoResultHeaders, BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientReleaseLeaseOptions, BlobContainerClientReleaseLeaseResult, BlobContainerClientReleaseLeaseResultHeaders, BlobContainerClientRenewLeaseOptions, BlobContainerClientRenewLeaseResult, BlobContainerClientSetMetadataOptions, BlobImmutabilityPolicyMode, - BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, - BlobServiceClientSetPropertiesOptions, BlobType, BlockBlobClientCommitBlockListOptions, - BlockBlobClientCommitBlockListResult, BlockBlobClientCommitBlockListResultHeaders, - BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, - BlockBlobClientStageBlockResult, BlockBlobClientStageBlockResultHeaders, - BlockBlobClientUploadOptions, BlockBlobClientUploadResult, BlockBlobClientUploadResultHeaders, - BlockList, BlockListType, BlockLookupList, CopyStatus, LeaseState, LeaseStatus, - ListBlobsFlatSegmentResponse, ListContainersSegmentResponse, PageBlobClientClearPagesOptions, - PageBlobClientClearPagesResult, PageBlobClientClearPagesResultHeaders, - PageBlobClientCreateOptions, PageBlobClientCreateResult, PageBlobClientCreateResultHeaders, - PageBlobClientResizeOptions, PageBlobClientResizeResult, PageBlobClientResizeResultHeaders, - PageBlobClientUploadPagesOptions, PageBlobClientUploadPagesResult, - PageBlobClientUploadPagesResultHeaders, PublicAccessType, RehydratePriority, - StorageServiceProperties, + BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetAccountInfoResult, + BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, + BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, BlobTags, + BlobType, BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, + BlockBlobClientCommitBlockListResultHeaders, BlockBlobClientGetBlockListOptions, + BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, + BlockBlobClientStageBlockResultHeaders, BlockBlobClientUploadOptions, + BlockBlobClientUploadResult, BlockBlobClientUploadResultHeaders, BlockList, BlockListType, + BlockLookupList, CopyStatus, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, + ListContainersSegmentResponse, PageBlobClientClearPagesOptions, PageBlobClientClearPagesResult, + PageBlobClientClearPagesResultHeaders, PageBlobClientCreateOptions, PageBlobClientCreateResult, + PageBlobClientCreateResultHeaders, PageBlobClientResizeOptions, PageBlobClientResizeResult, + PageBlobClientResizeResultHeaders, PageBlobClientUploadPagesOptions, + PageBlobClientUploadPagesResult, PageBlobClientUploadPagesResultHeaders, PublicAccessType, + RehydratePriority, StorageServiceProperties, }; pub use extensions::*; diff --git a/sdk/storage/azure_storage_blob/src/parsers.rs b/sdk/storage/azure_storage_blob/src/parsers.rs index e3c36c42d5..be6de8576b 100644 --- a/sdk/storage/azure_storage_blob/src/parsers.rs +++ b/sdk/storage/azure_storage_blob/src/parsers.rs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use crate::generated::models::{BlobTag, BlobTags}; +use azure_core::http::RequestContent; +use std::collections::HashMap; use std::io::{Error, ErrorKind}; /// Takes in an offset and a length, verifies alignment to a 512-byte boundary, and @@ -35,3 +38,23 @@ pub fn format_page_range(offset: u64, length: u64) -> Result { let content_range = format!("bytes={}-{}", offset, end_range); Ok(content_range) } + +/// Takes in an offset and a length and returns the HTTP range in string format. +/// +/// # Arguments +/// +/// * `tags` - A hash map containing the name-value pairs associated with the blob as tags. +pub fn serialize_blob_tags(tags: HashMap) -> BlobTags { + let mut blob_tags: Vec = vec![]; + + for (k, v) in tags.into_iter() { + let blob_tag = BlobTag { + key: Some(k), + value: Some(v), + }; + blob_tags.push(blob_tag); + } + BlobTags { + blob_tag_set: Some(blob_tags), + } +} diff --git a/sdk/storage/azure_storage_blob/tests/blob_client.rs b/sdk/storage/azure_storage_blob/tests/blob_client.rs index 759a12111a..fc5f011753 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -7,13 +7,17 @@ use azure_core::{ }; use azure_core_test::{recorded, TestContext}; use azure_storage_blob::models::{ - AccessTier, BlobClientAcquireLeaseResultHeaders, BlobClientChangeLeaseResultHeaders, - BlobClientDownloadOptions, BlobClientDownloadResultHeaders, BlobClientGetPropertiesOptions, + AccessTier, AccountKind, BlobClientAcquireLeaseResultHeaders, + BlobClientChangeLeaseResultHeaders, BlobClientDownloadOptions, BlobClientDownloadResultHeaders, + BlobClientGetAccountInfoResultHeaders, BlobClientGetPropertiesOptions, BlobClientGetPropertiesResultHeaders, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, BlobClientStartCopyFromUrlResultHeaders, BlockBlobClientUploadOptions, CopyStatus, LeaseState, }; -use azure_storage_blob_test::{create_test_blob, get_blob_name, get_container_client}; +use azure_storage_blob::serialize_blob_tags; +use azure_storage_blob_test::{ + create_test_blob, get_blob_name, get_container_client, test_blob_tag_equality, +}; use std::{collections::HashMap, error::Error, time::Duration}; use tokio::time; @@ -456,3 +460,56 @@ async fn test_start_copy_from_url(ctx: TestContext) -> Result<(), Box container_client.delete_container(None).await?; Ok(()) } + +#[recorded::test] +async fn test_blob_tags(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).await?; + + // Set Tags with Tags Specified + let blob_tags = HashMap::from([ + ("hello".to_string(), "world".to_string()), + ("ferris".to_string(), "crab".to_string()), + ]); + blob_client.set_tags(blob_tags.clone(), None).await?; + + // Assert + let response_tags = blob_client.get_tags(None).await?.into_body().await?; + assert!(test_blob_tag_equality( + serialize_blob_tags(blob_tags), + response_tags + )); + + // Set Tags with No Tags (Clear Tags) + blob_client.set_tags(HashMap::new(), None).await?; + + // Assert + let response_tags = blob_client.get_tags(None).await?.into_body().await?; + assert!(response_tags.blob_tag_set.is_none()); + + container_client.delete_container(None).await?; + Ok(()) +} + +#[recorded::test] +async fn test_get_account_info(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)); + + // Act + let response = blob_client.get_account_info(None).await?; + + // Assert + let sku_name = response.sku_name()?; + let account_kind = response.account_kind()?; + + assert!(sku_name.is_some()); + assert_eq!(AccountKind::StorageV2, account_kind.unwrap()); + + Ok(()) +} diff --git a/sdk/storage/azure_storage_blob/tests/blob_container_client.rs b/sdk/storage/azure_storage_blob/tests/blob_container_client.rs index 65420e18fb..3b9ca10e75 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_container_client.rs @@ -4,7 +4,8 @@ use azure_core::http::StatusCode; use azure_core_test::{recorded, TestContext}; use azure_storage_blob::models::{ - BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientChangeLeaseResultHeaders, + AccountKind, BlobContainerClientAcquireLeaseResultHeaders, + BlobContainerClientChangeLeaseResultHeaders, BlobContainerClientGetAccountInfoResultHeaders, BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientSetMetadataOptions, BlobType, LeaseState, }; @@ -275,3 +276,22 @@ async fn test_container_lease_operations(ctx: TestContext) -> Result<(), Box Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let container_client = get_container_client(recording, true).await?; + + // Act + let response = container_client.get_account_info(None).await?; + + // Assert + let sku_name = response.sku_name()?; + let account_kind = response.account_kind()?; + + assert!(sku_name.is_some()); + assert_eq!(AccountKind::StorageV2, account_kind.unwrap()); + + Ok(()) +} diff --git a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs index 80dc8cb06e..83cc9a454e 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs @@ -4,6 +4,7 @@ use azure_core::http::RequestContent; use azure_core_test::{recorded, TestContext}; use azure_storage_blob::models::{ + AccountKind, BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, StorageServiceProperties, }; @@ -148,3 +149,22 @@ async fn test_set_service_properties(ctx: TestContext) -> Result<(), Box Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let service_client = get_blob_service_client(recording)?; + + // Act + let response = service_client.get_account_info(None).await?; + + // Assert + let sku_name = response.sku_name()?; + let account_kind = response.account_kind()?; + + assert!(sku_name.is_some()); + assert_eq!(AccountKind::StorageV2, account_kind.unwrap()); + + Ok(()) +} diff --git a/sdk/storage/azure_storage_blob_test/src/lib.rs b/sdk/storage/azure_storage_blob_test/src/lib.rs index cb6b164896..958d503237 100644 --- a/sdk/storage/azure_storage_blob_test/src/lib.rs +++ b/sdk/storage/azure_storage_blob_test/src/lib.rs @@ -7,9 +7,11 @@ use azure_core::{ }; use azure_core_test::Recording; use azure_storage_blob::{ - models::BlockBlobClientUploadResult, BlobClient, BlobContainerClient, - BlobContainerClientOptions, BlobServiceClient, BlobServiceClientOptions, + models::{BlobTags, BlockBlobClientUploadResult}, + BlobClient, BlobContainerClient, BlobContainerClientOptions, BlobServiceClient, + BlobServiceClientOptions, }; +use std::collections::HashMap; /// Takes in a Recording instance and returns an instrumented options bag and endpoint. /// @@ -112,3 +114,28 @@ pub async fn create_test_blob( ) .await } + +/// Takes in two separate BlobTags instances and compares their contents to check for equality. +/// +/// # Arguments +/// +/// * `tags1` - The first BlobTags to be compared. +/// * `tags2` - The second BlobTags to be compared. +pub fn test_blob_tag_equality(tags1: BlobTags, tags2: BlobTags) -> bool { + let mut count_map = HashMap::new(); + // Iterate through first set of tags, populate HashMap + for blob_tag in tags1.blob_tag_set.unwrap() { + count_map.insert(blob_tag.key.unwrap(), blob_tag.value.unwrap()); + } + // Iterate through second set of tags + for blob_tag in tags2.blob_tag_set.unwrap() { + // If tag is not found, return false + if !count_map.contains_key(&blob_tag.key.clone().unwrap()) { + return false; + } else { + count_map.remove(&blob_tag.key.unwrap()); + } + } + // Ensure HashMap has been completely consumed + count_map.is_empty() +} From 2c40e8666bd0756cbb0a75e8a98326ceb543798d Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Tue, 15 Jul 2025 14:34:23 -0700 Subject: [PATCH 03/10] Regenerate against .tsp --- .../src/clients/blob_client.rs | 8 +-- .../src/generated/clients/blob_client.rs | 9 ++-- .../src/generated/models/header_traits.rs | 54 +++---------------- .../src/generated/models/pub_models.rs | 4 -- .../azure_storage_blob/src/models/mod.rs | 38 ++++++------- .../azure_storage_blob/tsp-location.yaml | 2 +- 6 files changed, 36 insertions(+), 79 deletions(-) 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 cb38776779..e95e228b8e 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -6,9 +6,9 @@ use crate::{ generated::models::{ BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, - BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientSetTagsResult, - BlobClientStartCopyFromUrlResult, BlockBlobClientCommitBlockListResult, - BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, + BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientStartCopyFromUrlResult, + BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, + BlockBlobClientUploadResult, }, models::{ AccessTier, BlobClientAcquireLeaseOptions, BlobClientBreakLeaseOptions, @@ -351,7 +351,7 @@ impl BlobClient { &self, tags: HashMap, options: Option>, - ) -> Result> { + ) -> Result> { let blob_tags = serialize_blob_tags(tags); self.client .set_tags(RequestContent::try_from(blob_tags)?, options) 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 9dac2880bf..be6a013b7b 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 @@ -19,10 +19,9 @@ use crate::generated::{ BlobClientSetExpiryOptions, BlobClientSetExpiryResult, BlobClientSetImmutabilityPolicyOptions, BlobClientSetImmutabilityPolicyResult, BlobClientSetLegalHoldOptions, BlobClientSetLegalHoldResult, BlobClientSetMetadataOptions, - BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTagsResult, - BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, - BlobClientStartCopyFromUrlResult, BlobClientUndeleteOptions, BlobClientUndeleteResult, - BlobExpiryOptions, BlobTags, + BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, + BlobClientStartCopyFromUrlOptions, BlobClientStartCopyFromUrlResult, + BlobClientUndeleteOptions, BlobClientUndeleteResult, BlobExpiryOptions, BlobTags, }, }; use azure_core::{ @@ -1251,7 +1250,7 @@ impl BlobClient { &self, tags: RequestContent, options: Option>, - ) -> Result> { + ) -> Result> { let options = options.unwrap_or_default(); let ctx = Context::with_context(&options.method_options.context); let mut url = self.endpoint.clone(); 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 7a09d50746..abc65d07ea 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 @@ -11,14 +11,13 @@ use super::{ BlobClientDeleteImmutabilityPolicyResult, BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientSetExpiryResult, BlobClientSetImmutabilityPolicyResult, - BlobClientSetLegalHoldResult, BlobClientSetTagsResult, BlobClientStartCopyFromUrlResult, - BlobClientUndeleteResult, BlobContainerClientAcquireLeaseResult, - BlobContainerClientBreakLeaseResult, BlobContainerClientChangeLeaseResult, - BlobContainerClientGetAccountInfoResult, BlobContainerClientGetPropertiesResult, - BlobContainerClientReleaseLeaseResult, BlobContainerClientRenameResult, - BlobContainerClientRenewLeaseResult, BlobContainerClientRestoreResult, - BlobContainerClientSetAccessPolicyResult, BlobImmutabilityPolicyMode, - BlobServiceClientGetAccountInfoResult, BlobTags, BlobType, + BlobClientSetLegalHoldResult, BlobClientStartCopyFromUrlResult, BlobClientUndeleteResult, + BlobContainerClientAcquireLeaseResult, BlobContainerClientBreakLeaseResult, + BlobContainerClientChangeLeaseResult, BlobContainerClientGetAccountInfoResult, + BlobContainerClientGetPropertiesResult, BlobContainerClientReleaseLeaseResult, + BlobContainerClientRenameResult, BlobContainerClientRenewLeaseResult, + BlobContainerClientRestoreResult, BlobContainerClientSetAccessPolicyResult, + BlobImmutabilityPolicyMode, BlobServiceClientGetAccountInfoResult, BlobTags, BlobType, BlockBlobClientCommitBlockListResult, BlockBlobClientPutBlobFromUrlResult, BlockBlobClientQueryResult, BlockBlobClientStageBlockFromUrlResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, BlockList, CopyStatus, @@ -835,18 +834,12 @@ impl BlobClientDownloadResultHeaders for Response Result>; fn account_kind(&self) -> Result>; fn is_hierarchical_namespace_enabled(&self) -> Result>; fn sku_name(&self) -> Result>; } impl BlobClientGetAccountInfoResultHeaders 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())) - } - /// Identifies the account kind fn account_kind(&self) -> Result> { Headers::get_optional_as(self.headers(), &ACCOUNT_KIND) @@ -1302,21 +1295,8 @@ impl BlobClientSetLegalHoldResultHeaders for Response Result>; -} - -impl BlobClientSetTagsResultHeaders 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::start_copy_from_url()` pub trait BlobClientStartCopyFromUrlResultHeaders: private::Sealed { - fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn copy_id(&self) -> Result>; @@ -1327,11 +1307,6 @@ pub trait BlobClientStartCopyFromUrlResultHeaders: private::Sealed { impl BlobClientStartCopyFromUrlResultHeaders 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())) - } - /// The date/time that the container was last modified. fn last_modified(&self) -> Result> { Headers::get_optional_with(self.headers(), &LAST_MODIFIED, |h| { @@ -1460,7 +1435,6 @@ impl BlobContainerClientChangeLeaseResultHeaders /// Provides access to typed response headers for `BlobContainerClient::get_account_info()` pub trait BlobContainerClientGetAccountInfoResultHeaders: private::Sealed { - fn date(&self) -> Result>; fn account_kind(&self) -> Result>; fn is_hierarchical_namespace_enabled(&self) -> Result>; fn sku_name(&self) -> Result>; @@ -1469,11 +1443,6 @@ pub trait BlobContainerClientGetAccountInfoResultHeaders: private::Sealed { impl BlobContainerClientGetAccountInfoResultHeaders 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())) - } - /// Identifies the account kind fn account_kind(&self) -> Result> { Headers::get_optional_as(self.headers(), &ACCOUNT_KIND) @@ -1689,7 +1658,6 @@ impl BlobContainerClientSetAccessPolicyResultHeaders /// Provides access to typed response headers for `BlobServiceClient::get_account_info()` pub trait BlobServiceClientGetAccountInfoResultHeaders: private::Sealed { - fn date(&self) -> Result>; fn account_kind(&self) -> Result>; fn is_hierarchical_namespace_enabled(&self) -> Result>; fn sku_name(&self) -> Result>; @@ -1698,11 +1666,6 @@ pub trait BlobServiceClientGetAccountInfoResultHeaders: private::Sealed { impl BlobServiceClientGetAccountInfoResultHeaders 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())) - } - /// Identifies the account kind fn account_kind(&self) -> Result> { Headers::get_optional_as(self.headers(), &ACCOUNT_KIND) @@ -2716,7 +2679,7 @@ mod private { BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientSetExpiryResult, BlobClientSetImmutabilityPolicyResult, BlobClientSetLegalHoldResult, - BlobClientSetTagsResult, BlobClientStartCopyFromUrlResult, BlobClientUndeleteResult, + BlobClientStartCopyFromUrlResult, BlobClientUndeleteResult, BlobContainerClientAcquireLeaseResult, BlobContainerClientBreakLeaseResult, BlobContainerClientChangeLeaseResult, BlobContainerClientGetAccountInfoResult, BlobContainerClientGetPropertiesResult, BlobContainerClientReleaseLeaseResult, @@ -2755,7 +2718,6 @@ 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 {} 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 c53356b7a9..f57fb555c0 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 @@ -159,10 +159,6 @@ pub struct BlobClientSetImmutabilityPolicyResult; #[derive(SafeDebug)] pub struct BlobClientSetLegalHoldResult; -/// Contains results for `BlobClient::set_tags()` -#[derive(SafeDebug)] -pub struct BlobClientSetTagsResult; - /// Contains results for `BlobClient::start_copy_from_url()` #[derive(SafeDebug)] pub struct BlobClientStartCopyFromUrlResult; diff --git a/sdk/storage/azure_storage_blob/src/models/mod.rs b/sdk/storage/azure_storage_blob/src/models/mod.rs index 5f9c3a3b68..13ce3b9f13 100644 --- a/sdk/storage/azure_storage_blob/src/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/models/mod.rs @@ -20,25 +20,25 @@ pub use crate::generated::models::{ BlobClientGetPropertiesResultHeaders, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, BlobClientReleaseLeaseResult, BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, BlobClientRenewLeaseResult, BlobClientRenewLeaseResultHeaders, BlobClientSetMetadataOptions, - BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTagsResult, - BlobClientSetTagsResultHeaders, BlobClientSetTierOptions, BlobClientStartCopyFromUrlOptions, - BlobClientStartCopyFromUrlResult, BlobClientStartCopyFromUrlResultHeaders, - BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, - BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, - BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, - BlobContainerClientChangeLeaseOptions, BlobContainerClientChangeLeaseResult, - BlobContainerClientChangeLeaseResultHeaders, BlobContainerClientCreateOptions, - BlobContainerClientDeleteOptions, BlobContainerClientGetAccountInfoOptions, - BlobContainerClientGetAccountInfoResultHeaders, BlobContainerClientGetPropertiesOptions, - BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, - BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientReleaseLeaseOptions, - BlobContainerClientReleaseLeaseResult, BlobContainerClientReleaseLeaseResultHeaders, - BlobContainerClientRenewLeaseOptions, BlobContainerClientRenewLeaseResult, - BlobContainerClientSetMetadataOptions, BlobImmutabilityPolicyMode, - BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetAccountInfoResult, - BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, - BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, BlobTags, - BlobType, BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, + BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, + BlobClientStartCopyFromUrlOptions, BlobClientStartCopyFromUrlResult, + BlobClientStartCopyFromUrlResultHeaders, BlobContainerClientAcquireLeaseOptions, + BlobContainerClientAcquireLeaseResult, BlobContainerClientAcquireLeaseResultHeaders, + BlobContainerClientBreakLeaseOptions, BlobContainerClientBreakLeaseResult, + BlobContainerClientBreakLeaseResultHeaders, BlobContainerClientChangeLeaseOptions, + BlobContainerClientChangeLeaseResult, BlobContainerClientChangeLeaseResultHeaders, + BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, + BlobContainerClientGetAccountInfoOptions, BlobContainerClientGetAccountInfoResultHeaders, + BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult, + BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientListBlobFlatSegmentOptions, + BlobContainerClientReleaseLeaseOptions, BlobContainerClientReleaseLeaseResult, + BlobContainerClientReleaseLeaseResultHeaders, BlobContainerClientRenewLeaseOptions, + BlobContainerClientRenewLeaseResult, BlobContainerClientSetMetadataOptions, + BlobImmutabilityPolicyMode, BlobServiceClientGetAccountInfoOptions, + BlobServiceClientGetAccountInfoResult, BlobServiceClientGetAccountInfoResultHeaders, + BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, + BlobServiceClientSetPropertiesOptions, BlobTags, BlobType, + BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, BlockBlobClientCommitBlockListResultHeaders, BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, BlockBlobClientStageBlockResultHeaders, BlockBlobClientUploadOptions, diff --git a/sdk/storage/azure_storage_blob/tsp-location.yaml b/sdk/storage/azure_storage_blob/tsp-location.yaml index 73d9db1736..33d5d00cc7 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: ac2d7f6cf9e37d6d4d35bd917bd2a06c31f9c1c4 +commit: a4d4ef47d3cffcaf30aa2449c251d62dc4c62b59 repo: Azure/azure-rest-api-specs additionalDirectories: From d1332838b85c7dcee8209db1272f82423fe83e61 Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Tue, 15 Jul 2025 14:39:22 -0700 Subject: [PATCH 04/10] Test recordings --- sdk/storage/assets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/assets.json b/sdk/storage/assets.json index 20cba4eaa9..69e79923d5 100644 --- a/sdk/storage/assets.json +++ b/sdk/storage/assets.json @@ -1,6 +1,6 @@ { "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "rust", - "Tag": "rust/azure_storage_blob_f12afa9550", + "Tag": "rust/azure_storage_blob_37bd13b584", "TagPrefix": "rust/azure_storage_blob" } \ No newline at end of file From c47b704172e9b1156f6bdbd33882a3cef9d595b1 Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Tue, 15 Jul 2025 14:54:29 -0700 Subject: [PATCH 05/10] Resolve rustdoc error bare-urls --- sdk/storage/azure_storage_blob/src/clients/blob_client.rs | 1 - 1 file changed, 1 deletion(-) 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 e95e228b8e..697241638c 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -326,7 +326,6 @@ impl BlobClient { /// If the source is in another account, the source must either be public /// or must be authenticated via a shared access signature. If the source /// is public, no authentication is required. - /// Example: https://myaccount.blob.core.windows.net/mycontainer/myblob /// * `options` - Optional configuration for the request. pub async fn start_copy_from_url( &self, From 4fc6dba4e4d675f1b85ca3f3f0571e8e12c2739f Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Tue, 15 Jul 2025 15:03:08 -0700 Subject: [PATCH 06/10] Recordings update --- sdk/storage/assets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/assets.json b/sdk/storage/assets.json index 69e79923d5..e6c60f7d02 100644 --- a/sdk/storage/assets.json +++ b/sdk/storage/assets.json @@ -1,6 +1,6 @@ { "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "rust", - "Tag": "rust/azure_storage_blob_37bd13b584", + "Tag": "rust/azure_storage_blob_c561afee00", "TagPrefix": "rust/azure_storage_blob" } \ No newline at end of file From 6e36e3a99fecfd0670cc1ebfb8e2c61991961516 Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Thu, 17 Jul 2025 17:20:09 -0700 Subject: [PATCH 07/10] nit --- sdk/storage/azure_storage_blob/src/parsers.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/storage/azure_storage_blob/src/parsers.rs b/sdk/storage/azure_storage_blob/src/parsers.rs index be6de8576b..4d05fcf447 100644 --- a/sdk/storage/azure_storage_blob/src/parsers.rs +++ b/sdk/storage/azure_storage_blob/src/parsers.rs @@ -39,13 +39,13 @@ pub fn format_page_range(offset: u64, length: u64) -> Result { Ok(content_range) } -/// Takes in an offset and a length and returns the HTTP range in string format. +/// Takes in a HashMap of blob tags and serializes them into the `BlobTags` model. /// /// # Arguments /// /// * `tags` - A hash map containing the name-value pairs associated with the blob as tags. pub fn serialize_blob_tags(tags: HashMap) -> BlobTags { - let mut blob_tags: Vec = vec![]; + let mut blob_tags = vec![]; for (k, v) in tags.into_iter() { let blob_tag = BlobTag { From b8a375b82a9965b40a9673fe4124304a65d41cdf Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Mon, 21 Jul 2025 12:35:25 -0700 Subject: [PATCH 08/10] Regen after omitting start_copy_from_url --- .../src/generated/models/header_traits.rs | 6 ++++++ sdk/storage/azure_storage_blob/tsp-location.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) 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 abc65d07ea..77555c4b4b 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 @@ -1297,6 +1297,7 @@ impl BlobClientSetLegalHoldResultHeaders for Response Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn copy_id(&self) -> Result>; @@ -1307,6 +1308,11 @@ pub trait BlobClientStartCopyFromUrlResultHeaders: private::Sealed { impl BlobClientStartCopyFromUrlResultHeaders 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())) + } + /// The date/time that the container was last modified. fn last_modified(&self) -> Result> { Headers::get_optional_with(self.headers(), &LAST_MODIFIED, |h| { diff --git a/sdk/storage/azure_storage_blob/tsp-location.yaml b/sdk/storage/azure_storage_blob/tsp-location.yaml index 33d5d00cc7..5df3685349 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: a4d4ef47d3cffcaf30aa2449c251d62dc4c62b59 +commit: 7b55a1dba199a8f9cb269d9cc76b9879d376aa37 repo: Azure/azure-rest-api-specs additionalDirectories: From 2633e4dcf2551ad11aaf63d946cf8c5d15b6a4ec Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Mon, 21 Jul 2025 13:48:09 -0700 Subject: [PATCH 09/10] Refactor that any cx facing is HashMap --- sdk/storage/assets.json | 2 +- .../src/clients/blob_client.rs | 30 +++-------- .../azure_storage_blob/src/models/mod.rs | 34 ++++++------- sdk/storage/azure_storage_blob/src/parsers.rs | 31 +++++++++++- .../azure_storage_blob/tests/blob_client.rs | 50 +++---------------- .../azure_storage_blob_test/src/lib.rs | 25 ---------- 6 files changed, 59 insertions(+), 113 deletions(-) diff --git a/sdk/storage/assets.json b/sdk/storage/assets.json index e6c60f7d02..e583470309 100644 --- a/sdk/storage/assets.json +++ b/sdk/storage/assets.json @@ -1,6 +1,6 @@ { "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "rust", - "Tag": "rust/azure_storage_blob_c561afee00", + "Tag": "rust/azure_storage_blob_a2540ce0f0", "TagPrefix": "rust/azure_storage_blob" } \ No newline at end of file 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 697241638c..0e322f8ca7 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -2,11 +2,12 @@ // Licensed under the MIT License. use crate::{ + deserialize_blob_tags, generated::clients::BlobClient as GeneratedBlobClient, generated::models::{ BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, - BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientStartCopyFromUrlResult, + BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, }, @@ -16,8 +17,8 @@ use crate::{ BlobClientGetAccountInfoOptions, BlobClientGetPropertiesOptions, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, - BlobClientStartCopyFromUrlOptions, BlobTags, BlockBlobClientCommitBlockListOptions, - BlockBlobClientUploadOptions, BlockList, BlockListType, BlockLookupList, + BlobTags, BlockBlobClientCommitBlockListOptions, BlockBlobClientUploadOptions, BlockList, + BlockListType, BlockLookupList, }, pipeline::StorageHeadersPolicy, serialize_blob_tags, AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient, @@ -317,24 +318,6 @@ impl BlobClient { self.client.renew_lease(lease_id, options).await } - /// Copies a blob or an internet resource to a new blob. - /// - /// # Arguments - /// - /// * `copy_source` - A URL of up to 2 KB in length that specifies a file or blob. - /// The value should be URL-encoded as it would appear in a request URI. - /// If the source is in another account, the source must either be public - /// or must be authenticated via a shared access signature. If the source - /// is public, no authentication is required. - /// * `options` - Optional configuration for the request. - pub async fn start_copy_from_url( - &self, - copy_source: String, - options: Option>, - ) -> Result> { - self.client.start_copy_from_url(copy_source, options).await - } - /// Sets tags on a blob. Note that each call to this operation replaces all existing tags. To remove /// all tags from the blob, call this operation with no tags specified. /// @@ -365,8 +348,9 @@ impl BlobClient { pub async fn get_tags( &self, options: Option>, - ) -> Result> { - self.client.get_tags(options).await + ) -> Result, XmlFormat>> { + let response = self.client.get_tags(options).await?; + deserialize_blob_tags(response).await } /// Gets information related to the Storage account in which the blob resides. diff --git a/sdk/storage/azure_storage_blob/src/models/mod.rs b/sdk/storage/azure_storage_blob/src/models/mod.rs index 13ce3b9f13..8abc456f10 100644 --- a/sdk/storage/azure_storage_blob/src/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/models/mod.rs @@ -21,24 +21,22 @@ pub use crate::generated::models::{ BlobClientReleaseLeaseResult, BlobClientReleaseLeaseResultHeaders, BlobClientRenewLeaseOptions, BlobClientRenewLeaseResult, BlobClientRenewLeaseResultHeaders, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTagsOptions, BlobClientSetTierOptions, - BlobClientStartCopyFromUrlOptions, BlobClientStartCopyFromUrlResult, - BlobClientStartCopyFromUrlResultHeaders, BlobContainerClientAcquireLeaseOptions, - BlobContainerClientAcquireLeaseResult, BlobContainerClientAcquireLeaseResultHeaders, - BlobContainerClientBreakLeaseOptions, BlobContainerClientBreakLeaseResult, - BlobContainerClientBreakLeaseResultHeaders, BlobContainerClientChangeLeaseOptions, - BlobContainerClientChangeLeaseResult, BlobContainerClientChangeLeaseResultHeaders, - BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, - BlobContainerClientGetAccountInfoOptions, BlobContainerClientGetAccountInfoResultHeaders, - BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult, - BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientListBlobFlatSegmentOptions, - BlobContainerClientReleaseLeaseOptions, BlobContainerClientReleaseLeaseResult, - BlobContainerClientReleaseLeaseResultHeaders, BlobContainerClientRenewLeaseOptions, - BlobContainerClientRenewLeaseResult, BlobContainerClientSetMetadataOptions, - BlobImmutabilityPolicyMode, BlobServiceClientGetAccountInfoOptions, - BlobServiceClientGetAccountInfoResult, BlobServiceClientGetAccountInfoResultHeaders, - BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, - BlobServiceClientSetPropertiesOptions, BlobTags, BlobType, - BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, + BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, + BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, + BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, + BlobContainerClientChangeLeaseOptions, BlobContainerClientChangeLeaseResult, + BlobContainerClientChangeLeaseResultHeaders, BlobContainerClientCreateOptions, + BlobContainerClientDeleteOptions, BlobContainerClientGetAccountInfoOptions, + BlobContainerClientGetAccountInfoResultHeaders, BlobContainerClientGetPropertiesOptions, + BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, + BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientReleaseLeaseOptions, + BlobContainerClientReleaseLeaseResult, BlobContainerClientReleaseLeaseResultHeaders, + BlobContainerClientRenewLeaseOptions, BlobContainerClientRenewLeaseResult, + BlobContainerClientSetMetadataOptions, BlobImmutabilityPolicyMode, + BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetAccountInfoResult, + BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, + BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, BlobTags, + BlobType, BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, BlockBlobClientCommitBlockListResultHeaders, BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, BlockBlobClientStageBlockResultHeaders, BlockBlobClientUploadOptions, diff --git a/sdk/storage/azure_storage_blob/src/parsers.rs b/sdk/storage/azure_storage_blob/src/parsers.rs index 4d05fcf447..dad66991c7 100644 --- a/sdk/storage/azure_storage_blob/src/parsers.rs +++ b/sdk/storage/azure_storage_blob/src/parsers.rs @@ -2,7 +2,8 @@ // Licensed under the MIT License. use crate::generated::models::{BlobTag, BlobTags}; -use azure_core::http::RequestContent; +use azure_core::http::{RawResponse, RequestContent, Response, XmlFormat}; +use azure_core::xml; use std::collections::HashMap; use std::io::{Error, ErrorKind}; @@ -44,7 +45,7 @@ pub fn format_page_range(offset: u64, length: u64) -> Result { /// # Arguments /// /// * `tags` - A hash map containing the name-value pairs associated with the blob as tags. -pub fn serialize_blob_tags(tags: HashMap) -> BlobTags { +pub(crate) fn serialize_blob_tags(tags: HashMap) -> BlobTags { let mut blob_tags = vec![]; for (k, v) in tags.into_iter() { @@ -58,3 +59,29 @@ pub fn serialize_blob_tags(tags: HashMap) -> BlobTags { blob_tag_set: Some(blob_tags), } } + +/// Takes in a `get_tags()` response and deserializes the `BlobTags` model into a HashMap of blob tags. +/// +/// # Arguments +/// +/// * `response` - The `get_tags()` response to be deserialized. +pub(crate) async fn deserialize_blob_tags( + response: Response, +) -> azure_core::Result, XmlFormat>> +where +{ + let mut blob_tags_map = HashMap::new(); + let status = response.status(); + let headers = response.headers().clone(); + let blob_tags = response.into_body().await?; + + if let Some(blob_tag_set) = blob_tags.blob_tag_set { + for blob_tag in blob_tag_set { + blob_tags_map.insert(blob_tag.key, blob_tag.value); + } + } + + let xml_body = xml::to_xml_with_root("HashMap", &blob_tags_map)?; + let raw_response = RawResponse::from_bytes(status, headers, xml_body); + Ok(raw_response.into()) +} diff --git a/sdk/storage/azure_storage_blob/tests/blob_client.rs b/sdk/storage/azure_storage_blob/tests/blob_client.rs index fc5f011753..f850784dea 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -11,13 +11,10 @@ use azure_storage_blob::models::{ BlobClientChangeLeaseResultHeaders, BlobClientDownloadOptions, BlobClientDownloadResultHeaders, BlobClientGetAccountInfoResultHeaders, BlobClientGetPropertiesOptions, BlobClientGetPropertiesResultHeaders, BlobClientSetMetadataOptions, - BlobClientSetPropertiesOptions, BlobClientSetTierOptions, - BlobClientStartCopyFromUrlResultHeaders, BlockBlobClientUploadOptions, CopyStatus, LeaseState, -}; -use azure_storage_blob::serialize_blob_tags; -use azure_storage_blob_test::{ - create_test_blob, get_blob_name, get_container_client, test_blob_tag_equality, + BlobClientSetPropertiesOptions, BlobClientSetTierOptions, BlockBlobClientUploadOptions, + LeaseState, }; +use azure_storage_blob_test::{create_test_blob, get_blob_name, get_container_client}; use std::{collections::HashMap, error::Error, time::Duration}; use tokio::time; @@ -428,39 +425,6 @@ async fn test_leased_blob_operations(ctx: TestContext) -> Result<(), Box Result<(), Box> { - // Recording Setup - let recording = ctx.recording(); - let container_client = get_container_client(recording, true).await?; - let source_blob_client = container_client.blob_client(get_blob_name(recording)); - create_test_blob(&source_blob_client).await?; - - let blob_client = container_client.blob_client("destination_blob".to_string()); - let source_url = format!( - "{}{}/{}", - source_blob_client.endpoint().as_str(), - source_blob_client.container_name(), - source_blob_client.blob_name() - ); - let response = blob_client.start_copy_from_url(source_url, None).await?; - let (_, _, source_content) = source_blob_client.download(None).await?.deconstruct(); - let (_, _, copied_content) = blob_client.download(None).await?.deconstruct(); - - // Assert - let copy_status = response.copy_status()?; - let copy_id = response.copy_id()?; - assert_eq!(CopyStatus::Success, copy_status.unwrap()); - assert!(copy_id.is_some()); - assert_eq!( - source_content.collect().await?, - copied_content.collect().await? - ); - - container_client.delete_container(None).await?; - Ok(()) -} - #[recorded::test] async fn test_blob_tags(ctx: TestContext) -> Result<(), Box> { // Recording Setup @@ -478,17 +442,15 @@ async fn test_blob_tags(ctx: TestContext) -> Result<(), Box> { // Assert let response_tags = blob_client.get_tags(None).await?.into_body().await?; - assert!(test_blob_tag_equality( - serialize_blob_tags(blob_tags), - response_tags - )); + println!("response:{:?}", response_tags.clone()); + assert_eq!(blob_tags, response_tags); // Set Tags with No Tags (Clear Tags) blob_client.set_tags(HashMap::new(), None).await?; // Assert let response_tags = blob_client.get_tags(None).await?.into_body().await?; - assert!(response_tags.blob_tag_set.is_none()); + assert_eq!(HashMap::new(), response_tags); container_client.delete_container(None).await?; Ok(()) diff --git a/sdk/storage/azure_storage_blob_test/src/lib.rs b/sdk/storage/azure_storage_blob_test/src/lib.rs index 958d503237..e94d242327 100644 --- a/sdk/storage/azure_storage_blob_test/src/lib.rs +++ b/sdk/storage/azure_storage_blob_test/src/lib.rs @@ -114,28 +114,3 @@ pub async fn create_test_blob( ) .await } - -/// Takes in two separate BlobTags instances and compares their contents to check for equality. -/// -/// # Arguments -/// -/// * `tags1` - The first BlobTags to be compared. -/// * `tags2` - The second BlobTags to be compared. -pub fn test_blob_tag_equality(tags1: BlobTags, tags2: BlobTags) -> bool { - let mut count_map = HashMap::new(); - // Iterate through first set of tags, populate HashMap - for blob_tag in tags1.blob_tag_set.unwrap() { - count_map.insert(blob_tag.key.unwrap(), blob_tag.value.unwrap()); - } - // Iterate through second set of tags - for blob_tag in tags2.blob_tag_set.unwrap() { - // If tag is not found, return false - if !count_map.contains_key(&blob_tag.key.clone().unwrap()) { - return false; - } else { - count_map.remove(&blob_tag.key.unwrap()); - } - } - // Ensure HashMap has been completely consumed - count_map.is_empty() -} From 3c3d7165bbf81ca3fb0e0d90fa4fcd400585cb8a Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Mon, 21 Jul 2025 13:54:22 -0700 Subject: [PATCH 10/10] nit --- sdk/storage/azure_storage_blob_test/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/storage/azure_storage_blob_test/src/lib.rs b/sdk/storage/azure_storage_blob_test/src/lib.rs index e94d242327..cb6b164896 100644 --- a/sdk/storage/azure_storage_blob_test/src/lib.rs +++ b/sdk/storage/azure_storage_blob_test/src/lib.rs @@ -7,11 +7,9 @@ use azure_core::{ }; use azure_core_test::Recording; use azure_storage_blob::{ - models::{BlobTags, BlockBlobClientUploadResult}, - BlobClient, BlobContainerClient, BlobContainerClientOptions, BlobServiceClient, - BlobServiceClientOptions, + models::BlockBlobClientUploadResult, BlobClient, BlobContainerClient, + BlobContainerClientOptions, BlobServiceClient, BlobServiceClientOptions, }; -use std::collections::HashMap; /// Takes in a Recording instance and returns an instrumented options bag and endpoint. ///