diff --git a/sdk/storage/assets.json b/sdk/storage/assets.json index 20cba4eaa9..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_f12afa9550", + "Tag": "rust/azure_storage_blob_c561afee00", "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 1c2564d279..697241638c 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -5,20 +5,22 @@ use crate::{ generated::clients::BlobClient as GeneratedBlobClient, generated::models::{ BlobClientAcquireLeaseResult, BlobClientBreakLeaseResult, BlobClientChangeLeaseResult, - BlobClientDownloadResult, BlobClientGetPropertiesResult, BlobClientReleaseLeaseResult, - BlobClientRenewLeaseResult, BlockBlobClientCommitBlockListResult, - BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, + BlobClientDownloadResult, BlobClientGetAccountInfoResult, BlobClientGetPropertiesResult, + BlobClientReleaseLeaseResult, BlobClientRenewLeaseResult, BlobClientStartCopyFromUrlResult, + BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, + BlockBlobClientUploadResult, }, models::{ AccessTier, BlobClientAcquireLeaseOptions, BlobClientBreakLeaseOptions, BlobClientChangeLeaseOptions, BlobClientDeleteOptions, BlobClientDownloadOptions, - BlobClientGetPropertiesOptions, BlobClientReleaseLeaseOptions, BlobClientRenewLeaseOptions, - BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, - BlockBlobClientCommitBlockListOptions, BlockBlobClientUploadOptions, BlockList, - BlockListType, BlockLookupList, + 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, @@ -28,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. @@ -313,4 +316,69 @@ 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. + /// * `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. + /// + /// # 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 1f2c04bec8..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,8 +3,10 @@ use crate::{ generated::clients::BlobServiceClient as GeneratedBlobServiceClient, + generated::models::BlobServiceClientGetAccountInfoResult, models::{ - BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, + BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetPropertiesOptions, + BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, ListContainersSegmentResponse, StorageServiceProperties, }, pipeline::StorageHeadersPolicy, @@ -14,7 +16,7 @@ use azure_core::{ credentials::TokenCredential, http::{ policies::{BearerTokenCredentialPolicy, Policy}, - PageIterator, Response, Url, XmlFormat, + NoFormat, PageIterator, RequestContent, Response, Url, XmlFormat, }, Result, }; @@ -104,4 +106,33 @@ 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 + } + + /// 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/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 cd90fd3616..13ce3b9f13 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,24 +14,30 @@ 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, - BlobContainerClientAcquireLeaseOptions, BlobContainerClientAcquireLeaseResult, - BlobContainerClientAcquireLeaseResultHeaders, BlobContainerClientBreakLeaseOptions, - BlobContainerClientBreakLeaseResult, BlobContainerClientBreakLeaseResultHeaders, - BlobContainerClientChangeLeaseOptions, BlobContainerClientChangeLeaseResult, - BlobContainerClientChangeLeaseResultHeaders, BlobContainerClientCreateOptions, - BlobContainerClientDeleteOptions, BlobContainerClientGetPropertiesOptions, - BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, - BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientReleaseLeaseOptions, - BlobContainerClientReleaseLeaseResult, BlobContainerClientReleaseLeaseResultHeaders, - BlobContainerClientRenewLeaseOptions, BlobContainerClientRenewLeaseResult, - BlobContainerClientSetMetadataOptions, BlobImmutabilityPolicyMode, - BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, BlobType, + BlobClientDownloadResult, BlobClientDownloadResultHeaders, BlobClientGetAccountInfoOptions, + BlobClientGetAccountInfoResult, BlobClientGetAccountInfoResultHeaders, + BlobClientGetPropertiesOptions, BlobClientGetPropertiesResult, + BlobClientGetPropertiesResultHeaders, BlobClientGetTagsOptions, BlobClientReleaseLeaseOptions, + 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, BlockBlobClientCommitBlockListResultHeaders, BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, diff --git a/sdk/storage/azure_storage_blob/src/parsers.rs b/sdk/storage/azure_storage_blob/src/parsers.rs index e3c36c42d5..4d05fcf447 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 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![]; + + 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 5d5818b2f9..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, BlockBlobClientUploadOptions, - LeaseState, + 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, }; -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; @@ -423,3 +427,89 @@ 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 + 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 db5ac45d91..83cc9a454e 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,12 @@ // 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::{ + AccountKind, BlobServiceClientGetAccountInfoResultHeaders, BlobServiceClientGetPropertiesOptions, BlobServiceClientListContainersSegmentOptions, + StorageServiceProperties, }; use azure_storage_blob_test::{get_blob_service_client, get_container_name}; use futures::StreamExt; @@ -122,3 +125,46 @@ 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(()) +} + +#[recorded::test] +async fn test_get_account_info(ctx: TestContext) -> 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/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: 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() +}