diff --git a/sdk/storage/assets.json b/sdk/storage/assets.json index f749f6b24a..789d95a75d 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_231754d877", + "Tag": "rust/azure_storage_blob_5c826b7898", "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 cf0a42c751..2a92011142 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -4,7 +4,7 @@ use crate::{ generated::clients::BlobClient as GeneratedBlobClient, generated::models::{ - BlobClientDownloadResult, BlobClientGetPropertiesResult, + BlobClientDownloadResult, BlobClientGetPropertiesResult, BlobClientStartCopyFromUrlResult, BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, }, @@ -12,8 +12,8 @@ use crate::{ AccessTier, BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, - BlockBlobClientCommitBlockListOptions, BlockBlobClientUploadOptions, BlockList, - BlockListType, BlockLookupList, + BlobClientStartCopyFromUrlOptions, BlockBlobClientCommitBlockListOptions, + BlockBlobClientUploadOptions, BlockList, BlockListType, BlockLookupList, }, pipeline::StorageHeadersPolicy, BlobClientOptions, BlockBlobClient, @@ -211,4 +211,23 @@ impl BlobClient { ) -> Result> { self.client.set_tier(tier, 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 9f593c9ec7..888c1bde3f 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,7 +3,10 @@ use crate::{ generated::clients::BlobServiceClient as GeneratedBlobServiceClient, - models::{BlobServiceClientGetPropertiesOptions, StorageServiceProperties}, + models::{ + BlobServiceClientGetPropertiesOptions, BlobServiceClientSetPropertiesOptions, + StorageServiceProperties, + }, pipeline::StorageHeadersPolicy, BlobContainerClient, BlobServiceClientOptions, }; @@ -11,7 +14,7 @@ use azure_core::{ credentials::TokenCredential, http::{ policies::{BearerTokenCredentialPolicy, Policy}, - Response, Url, + RequestContent, Response, Url, }, Result, }; @@ -89,4 +92,20 @@ impl BlobServiceClient { ) -> Result> { self.client.get_properties(options).await } + + /// 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/generated/clients/append_blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs index a9bfe32a7e..6e052566f2 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs @@ -334,7 +334,6 @@ impl AppendBlobClient { let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); - request.insert_header("content-type", "application/xml"); if let Some(if_match) = options.if_match { request.insert_header("if-match", if_match); } 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 974e609213..59dc308c8e 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 @@ -801,7 +801,6 @@ impl BlobClient { } let mut request = Request::new(url, Method::Head); request.insert_header("accept", "application/json"); - request.insert_header("content-type", ""); if let Some(if_match) = options.if_match { request.insert_header("if-match", if_match); } diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs index 4c3380885c..8fa6879811 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs @@ -304,7 +304,6 @@ impl BlockBlobClient { if let Some(transactional_content_md5) = options.transactional_content_md5 { request.insert_header("content-md5", base64::encode(transactional_content_md5)); } - request.insert_header("content-type", "application/xml"); if let Some(if_match) = options.if_match { request.insert_header("if-match", if_match); } diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs index 5e2ffc6ba9..158946f234 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs @@ -123,7 +123,6 @@ impl PageBlobClient { let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); - request.insert_header("content-type", "application/xml"); if let Some(if_match) = options.if_match { request.insert_header("if-match", if_match); } @@ -276,7 +275,6 @@ impl PageBlobClient { let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); - request.insert_header("content-type", ""); if let Some(if_match) = options.if_match { request.insert_header("if-match", if_match); } @@ -805,7 +803,6 @@ impl PageBlobClient { let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); - request.insert_header("content-type", "application/xml"); if let Some(if_match) = options.if_match { request.insert_header("if-match", if_match); } diff --git a/sdk/storage/azure_storage_blob/src/lib.rs b/sdk/storage/azure_storage_blob/src/lib.rs index 0e8fa822ae..30dd6b05a0 100644 --- a/sdk/storage/azure_storage_blob/src/lib.rs +++ b/sdk/storage/azure_storage_blob/src/lib.rs @@ -19,16 +19,17 @@ pub mod models { BlobClientDownloadResult, BlobClientDownloadResultHeaders, BlobClientGetPropertiesOptions, BlobClientGetPropertiesResult, BlobClientGetPropertiesResultHeaders, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, + BlobClientStartCopyFromUrlOptions, BlobClientStartCopyFromUrlResultHeaders, BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientSetMetadataOptions, - BlobImmutabilityPolicyMode, BlobServiceClientGetPropertiesOptions, BlobType, - BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, - BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, - BlockBlobClientStageBlockResult, BlockBlobClientUploadOptions, BlockBlobClientUploadResult, - BlockList, BlockListType, BlockLookupList, CopyStatus, LeaseState, LeaseStatus, - ListBlobsFlatSegmentResponse, PublicAccessType, RehydratePriority, - StorageServiceProperties, + BlobImmutabilityPolicyMode, BlobServiceClientGetPropertiesOptions, + BlobServiceClientSetPropertiesOptions, BlobType, BlockBlobClientCommitBlockListOptions, + BlockBlobClientCommitBlockListResult, BlockBlobClientGetBlockListOptions, + BlockBlobClientStageBlockOptions, BlockBlobClientStageBlockResult, + BlockBlobClientUploadOptions, BlockBlobClientUploadResult, BlockList, BlockListType, + BlockLookupList, CopyStatus, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, + PublicAccessType, RehydratePriority, StorageServiceProperties, }; } diff --git a/sdk/storage/azure_storage_blob/tests/blob_client.rs b/sdk/storage/azure_storage_blob/tests/blob_client.rs index 16a9d3a2de..4cd35aaa32 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -8,8 +8,8 @@ use azure_core::{ use azure_core_test::{recorded, TestContext}; use azure_storage_blob::models::{ AccessTier, BlobClientDownloadResultHeaders, BlobClientGetPropertiesResultHeaders, - BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlockBlobClientUploadOptions, - LeaseState, + BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, + BlobClientStartCopyFromUrlResultHeaders, BlockBlobClientUploadOptions, CopyStatus, LeaseState, }; use azure_storage_blob_test::{create_test_blob, get_blob_name, get_container_client}; use std::{collections::HashMap, error::Error}; @@ -276,3 +276,69 @@ async fn test_set_access_tier(ctx: TestContext) -> Result<(), Box> { container_client.delete_container(None).await?; Ok(()) } + +#[recorded::test] +async fn test_start_copy_from_url(ctx: TestContext) -> 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_start_copy_from_url2(ctx: TestContext) -> 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 0077ef903b..72c076555c 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs @@ -1,8 +1,9 @@ // 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; +use azure_storage_blob::models::{BlobServiceClientGetPropertiesOptions, StorageServiceProperties}; use azure_storage_blob_test::get_blob_service_client; use std::error::Error; @@ -22,3 +23,27 @@ async fn test_get_service_properties(ctx: TestContext) -> Result<(), Box 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(()) +} diff --git a/sdk/storage/azure_storage_blob/tsp-location.yaml b/sdk/storage/azure_storage_blob/tsp-location.yaml index 630396183b..04d816fc10 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: a0463864e021c00771eb01510e2eecd800ad05e2 +commit: f848853e5880d2b1e3375a6517aa59ada57d60d3 repo: Azure/azure-rest-api-specs additionalDirectories: