Skip to content

Commit e132848

Browse files
[Storage] AppendBlobClient, PageBlobClient, Initial create APIs, other PageBlobClient APIs (#2667)
* AppendBlobClient and PageBlobClient first draft * nit * Regenerate against latest version + removed response headers * Refactor handwritten layer to match generated code changes * Regen feature/blob-tsp * Need generated code support * PR feedback, regen against corrected .tsp * Added create-if-not-exists scenario to create_page_blob test suite * Add helper concept, refactor after helper * Regen against v0.17 & tsp changes * PR feedback * Fix test recordings for CI * Refactor on PR feedback, move to extension traits, still wip helper * nit * Refactor both to be extension traits * nit docs * Refactor, storage_utils for common helpers, storage_traits for options bag extension methods * Refactor to helpers, extension traits in models folder, add models folder * nit * Rename to parsers, regen against feature/blob-tsp
1 parent e7d46f3 commit e132848

File tree

16 files changed

+603
-80
lines changed

16 files changed

+603
-80
lines changed

sdk/storage/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "rust",
4-
"Tag": "rust/azure_storage_blob_a55c38eec2",
4+
"Tag": "rust/azure_storage_blob_83b2698a78",
55
"TagPrefix": "rust/azure_storage_blob"
66
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
use crate::{
5+
generated::clients::AppendBlobClient as GeneratedAppendBlobClient,
6+
models::{AppendBlobClientCreateOptions, AppendBlobClientCreateResult},
7+
pipeline::StorageHeadersPolicy,
8+
AppendBlobClientOptions, BlobClientOptions,
9+
};
10+
use azure_core::{
11+
credentials::TokenCredential,
12+
http::{
13+
policies::{BearerTokenCredentialPolicy, Policy},
14+
NoFormat, RequestContent, Response, Url,
15+
},
16+
Bytes, Result,
17+
};
18+
use std::sync::Arc;
19+
20+
/// A client to interact with a specific Azure storage Append blob, although that blob may not yet exist.
21+
pub struct AppendBlobClient {
22+
pub(crate) endpoint: Url,
23+
pub(crate) client: GeneratedAppendBlobClient,
24+
}
25+
26+
impl AppendBlobClient {
27+
/// Creates a new AppendBlobClient, using Entra ID authentication.
28+
///
29+
/// # Arguments
30+
///
31+
/// * `endpoint` - The full URL of the Azure storage account, for example `https://myaccount.blob.core.windows.net/`
32+
/// * `container_name` - The name of the container containing this Append blob.
33+
/// * `blob_name` - The name of the Append blob to interact with.
34+
/// * `credential` - An implementation of [`TokenCredential`] that can provide an Entra ID token to use when authenticating.
35+
/// * `options` - Optional configuration for the client.
36+
pub fn new(
37+
endpoint: &str,
38+
container_name: String,
39+
blob_name: String,
40+
credential: Arc<dyn TokenCredential>,
41+
options: Option<AppendBlobClientOptions>,
42+
) -> Result<Self> {
43+
let mut options = options.unwrap_or_default();
44+
45+
let storage_headers_policy = Arc::new(StorageHeadersPolicy);
46+
options
47+
.client_options
48+
.per_call_policies
49+
.push(storage_headers_policy);
50+
51+
let oauth_token_policy = BearerTokenCredentialPolicy::new(
52+
credential.clone(),
53+
["https://storage.azure.com/.default"],
54+
);
55+
options
56+
.client_options
57+
.per_try_policies
58+
.push(Arc::new(oauth_token_policy) as Arc<dyn Policy>);
59+
60+
let client = GeneratedAppendBlobClient::new(
61+
endpoint,
62+
credential.clone(),
63+
container_name.clone(),
64+
blob_name.clone(),
65+
Some(options),
66+
)?;
67+
Ok(Self {
68+
endpoint: endpoint.parse()?,
69+
client,
70+
})
71+
}
72+
73+
/// Gets the endpoint of the Storage account this client is connected to.
74+
pub fn endpoint(&self) -> &Url {
75+
&self.endpoint
76+
}
77+
78+
/// Gets the container name of the Storage account this client is connected to.
79+
pub fn container_name(&self) -> &str {
80+
&self.client.container_name
81+
}
82+
83+
/// Gets the blob name of the Storage account this client is connected to.
84+
pub fn blob_name(&self) -> &str {
85+
&self.client.blob_name
86+
}
87+
88+
/// Creates a new Append blob.
89+
///
90+
/// # Arguments
91+
///
92+
/// * `content_length` - Total length of the blob data to be uploaded.
93+
/// * `options` - Optional configuration for the request.
94+
pub async fn create(
95+
&self,
96+
options: Option<AppendBlobClientCreateOptions<'_>>,
97+
) -> Result<Response<AppendBlobClientCreateResult, NoFormat>> {
98+
self.client.create(options).await
99+
}
100+
}

sdk/storage/azure_storage_blob/src/clients/blob_client.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
BlockListType, BlockLookupList,
1717
},
1818
pipeline::StorageHeadersPolicy,
19-
BlobClientOptions, BlockBlobClient,
19+
AppendBlobClient, BlobClientOptions, BlockBlobClient, PageBlobClient,
2020
};
2121
use azure_core::{
2222
credentials::TokenCredential,
@@ -81,6 +81,17 @@ impl BlobClient {
8181
})
8282
}
8383

84+
/// Returns a new instance of AppendBlobClient.
85+
///
86+
/// # Arguments
87+
///
88+
pub fn append_blob_client(&self) -> AppendBlobClient {
89+
AppendBlobClient {
90+
endpoint: self.client.endpoint.clone(),
91+
client: self.client.get_append_blob_client(),
92+
}
93+
}
94+
8495
/// Returns a new instance of BlockBlobClient.
8596
///
8697
/// # Arguments
@@ -92,6 +103,17 @@ impl BlobClient {
92103
}
93104
}
94105

106+
/// Returns a new instance of PageBlobClient.
107+
///
108+
/// # Arguments
109+
///
110+
pub fn page_blob_client(&self) -> PageBlobClient {
111+
PageBlobClient {
112+
endpoint: self.client.endpoint.clone(),
113+
client: self.client.get_page_blob_client(),
114+
}
115+
}
116+
95117
/// Gets the endpoint of the Storage account this client is connected to.
96118
pub fn endpoint(&self) -> &Url {
97119
&self.endpoint

sdk/storage/azure_storage_blob/src/clients/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@
33
// Licensed under the MIT License. See License.txt in the project root for license information.
44
// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT.
55

6+
mod append_blob_client;
67
mod blob_client;
78
mod blob_container_client;
89
mod blob_service_client;
910
mod block_blob_client;
11+
mod page_blob_client;
1012

13+
pub use append_blob_client::AppendBlobClient;
1114
pub use blob_client::BlobClient;
1215
pub use blob_container_client::BlobContainerClient;
1316
pub use blob_service_client::BlobServiceClient;
1417
pub use block_blob_client::BlockBlobClient;
18+
pub use page_blob_client::PageBlobClient;
1519

1620
pub use crate::generated::clients::{
17-
BlobClientOptions, BlobContainerClientOptions, BlobServiceClientOptions, BlockBlobClientOptions,
21+
AppendBlobClientOptions, BlobClientOptions, BlobContainerClientOptions,
22+
BlobServiceClientOptions, BlockBlobClientOptions, PageBlobClientOptions,
1823
};
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
use crate::{
5+
generated::clients::PageBlobClient as GeneratedPageBlobClient,
6+
models::{
7+
PageBlobClientClearPagesOptions, PageBlobClientClearPagesResult,
8+
PageBlobClientCreateOptions, PageBlobClientCreateResult, PageBlobClientResizeOptions,
9+
PageBlobClientResizeResult, PageBlobClientUploadPagesOptions,
10+
PageBlobClientUploadPagesResult,
11+
},
12+
pipeline::StorageHeadersPolicy,
13+
BlobClientOptions, PageBlobClientOptions,
14+
};
15+
use azure_core::{
16+
credentials::TokenCredential,
17+
http::{
18+
policies::{BearerTokenCredentialPolicy, Policy},
19+
NoFormat, RequestContent, Response, Url,
20+
},
21+
Bytes, Result,
22+
};
23+
use std::sync::Arc;
24+
25+
/// A client to interact with a specific Azure storage Page blob, although that blob may not yet exist.
26+
pub struct PageBlobClient {
27+
pub(crate) endpoint: Url,
28+
pub(crate) client: GeneratedPageBlobClient,
29+
}
30+
31+
impl PageBlobClient {
32+
/// Creates a new PageBlobClient, using Entra ID authentication.
33+
///
34+
/// # Arguments
35+
///
36+
/// * `endpoint` - The full URL of the Azure storage account, for example `https://myaccount.blob.core.windows.net/`
37+
/// * `container_name` - The name of the container containing this Page blob.
38+
/// * `blob_name` - The name of the Page blob to interact with.
39+
/// * `credential` - An implementation of [`TokenCredential`] that can provide an Entra ID token to use when authenticating.
40+
/// * `options` - Optional configuration for the client.
41+
pub fn new(
42+
endpoint: &str,
43+
container_name: String,
44+
blob_name: String,
45+
credential: Arc<dyn TokenCredential>,
46+
options: Option<PageBlobClientOptions>,
47+
) -> Result<Self> {
48+
let mut options = options.unwrap_or_default();
49+
50+
let storage_headers_policy = Arc::new(StorageHeadersPolicy);
51+
options
52+
.client_options
53+
.per_call_policies
54+
.push(storage_headers_policy);
55+
56+
let oauth_token_policy = BearerTokenCredentialPolicy::new(
57+
credential.clone(),
58+
["https://storage.azure.com/.default"],
59+
);
60+
options
61+
.client_options
62+
.per_try_policies
63+
.push(Arc::new(oauth_token_policy) as Arc<dyn Policy>);
64+
65+
let client = GeneratedPageBlobClient::new(
66+
endpoint,
67+
credential.clone(),
68+
container_name.clone(),
69+
blob_name.clone(),
70+
Some(options),
71+
)?;
72+
Ok(Self {
73+
endpoint: endpoint.parse()?,
74+
client,
75+
})
76+
}
77+
78+
/// Gets the endpoint of the Storage account this client is connected to.
79+
pub fn endpoint(&self) -> &Url {
80+
&self.endpoint
81+
}
82+
83+
/// Gets the container name of the Storage account this client is connected to.
84+
pub fn container_name(&self) -> &str {
85+
&self.client.container_name
86+
}
87+
88+
/// Gets the blob name of the Storage account this client is connected to.
89+
pub fn blob_name(&self) -> &str {
90+
&self.client.blob_name
91+
}
92+
93+
/// Creates a new Page blob.
94+
///
95+
/// # Arguments
96+
///
97+
/// * `content_length` - The maximum size for the Page blob, up to 1TB. The page blob size must
98+
/// be aligned to a 512-byte boundary.
99+
/// * `options` - Optional parameters for the request. See [`PageBlobClientCreateOptionsExt`](crate::models::PageBlobClientCreateOptionsExt) for additional usage helpers.
100+
pub async fn create(
101+
&self,
102+
content_length: u64,
103+
options: Option<PageBlobClientCreateOptions<'_>>,
104+
) -> Result<Response<PageBlobClientCreateResult, NoFormat>> {
105+
self.client.create(content_length, options).await
106+
}
107+
108+
/// Clears a range of pages.
109+
///
110+
/// # Arguments
111+
///
112+
/// * `range` - The range of bytes to clear. See [`format_page_range()`](crate::format_page_range) for help with the expected String format.
113+
/// * `options` - Optional parameters for the request.
114+
pub async fn clear_page(
115+
&self,
116+
range: String,
117+
options: Option<PageBlobClientClearPagesOptions<'_>>,
118+
) -> Result<Response<PageBlobClientClearPagesResult, NoFormat>> {
119+
self.client.clear_pages(range, options).await
120+
}
121+
122+
/// Resizes a Page blob to the specified size. If the specified value is less than
123+
/// the current size of the blob, then all pages above the specified value are cleared.
124+
///
125+
/// # Arguments
126+
///
127+
/// * `size` - Size used to resize the blob. Maximum size for a page Blob is up to 1TB. The
128+
/// Page blob size must be aligned to a 512-byte boundary.
129+
/// * `options` - Optional parameters for the request.
130+
pub async fn resize(
131+
&self,
132+
size: u64,
133+
options: Option<PageBlobClientResizeOptions<'_>>,
134+
) -> Result<Response<PageBlobClientResizeResult, NoFormat>> {
135+
self.client.resize(size, options).await
136+
}
137+
138+
/// The Upload Pages operation writes a range of pages to a Page blob.
139+
///
140+
/// # Arguments
141+
///
142+
/// * `data` - The contents of the page.
143+
/// * `content_length` - Number of bytes to use for writing to a section of the blob. The
144+
/// content_length specified must be a modulus of 512.
145+
/// * `range` - The range of the bytes to write. See [`format_page_range()`](crate::format_page_range) for help with the expected String format.
146+
/// * `options` - Optional parameters for the request.
147+
pub async fn upload_page(
148+
&self,
149+
data: RequestContent<Bytes>,
150+
content_length: u64,
151+
range: String,
152+
options: Option<PageBlobClientUploadPagesOptions<'_>>,
153+
) -> Result<Response<PageBlobClientUploadPagesResult, NoFormat>> {
154+
self.client
155+
.upload_pages(data, content_length, range, options)
156+
.await
157+
}
158+
}

sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)