Skip to content

Commit 15b7d27

Browse files
[Storage] azure_storage_blob release prep (+ delete() for BlobClient) (#2431)
1 parent c97ce1b commit 15b7d27

File tree

7 files changed

+235
-12
lines changed

7 files changed

+235
-12
lines changed

sdk/storage/.dict.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ immutabilitypolicy
1919
uncommittedblobs
2020
policyid
2121
ruleid
22+
westus

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_d3c80a557c",
4+
"Tag": "rust/azure_storage_blob_c02de844b6",
55
"TagPrefix": "rust/azure_storage_blob"
66
}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
# 0.1.0 (2024-07)
1+
# Release History
22

3-
- initial TODO
3+
## 0.1.0 (2025-04-08)
4+
5+
### Features Added
6+
7+
* Initial supported release.
Lines changed: 143 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,144 @@
1-
# sdk/storage/azure_storage_blob
1+
# Azure Storage Blob client library for Rust
22

3-
TODO TODO TODO
3+
Azure Blob storage is Microsoft's object storage solution for the cloud. Blob storage is optimized for storing massive amounts of unstructured data, such as text or binary data.
4+
5+
[Source code] | [Package (crates.io)] | [API reference documentation] | [REST API documentation] | [Product documentation]
6+
7+
## Getting started
8+
9+
### Install the package
10+
11+
Install the Azure Storage Blob client library for Rust with [cargo]:
12+
13+
```sh
14+
cargo add azure_storage_blob
15+
```
16+
17+
### Prerequisites
18+
19+
* You must have an [Azure subscription] and an [Azure storage account] to use this package.
20+
21+
22+
23+
### Create a storage account
24+
If you wish to create a new storage account, you can use the
25+
[Azure Portal], [Azure PowerShell], or [Azure CLI]:
26+
```bash
27+
# Create a new resource group to hold the storage account -
28+
# if using an existing resource group, skip this step
29+
az group create --name my-resource-group --location westus2
30+
31+
# Create the storage account
32+
az storage account create -n my-storage-account-name -g my-resource-group
33+
```
34+
35+
#### Authenticate the client
36+
37+
In order to interact with the Azure Blob Storage service, you'll need to create an instance of a client, `BlobClient`, `BlobContainerClient`, or `BlobServiceClient`. The [Azure Identity] library makes it easy to add Microsoft Entra ID support for authenticating Azure SDK clients with their corresponding Azure services:
38+
```rust
39+
use azure_storage_blob::BlobClient;
40+
use azure_identity::DefaultAzureCredential;
41+
42+
// Create a BlobClient that will authenticate through Microsoft Entra ID
43+
let credential = DefaultAzureCredential::new()?;
44+
let blob_client = BlobClient::new(
45+
"https://<storage_account_name>.blob.core.windows.net/", // endpoint
46+
"container_name".to_string(), // container name
47+
"blob_name".to_string(), // blob name
48+
credential, // credential
49+
Some(BlobClientOptions::default()), // BlobClient options
50+
)?;
51+
```
52+
53+
#### Permissions
54+
You may need to specify RBAC roles to access Blob Storage via Microsoft Entra ID. Please see [Assign an Azure role for access to blob data] for more details.
55+
56+
## Examples
57+
58+
### Create `BlobClient`
59+
```rust
60+
use azure_storage_blob::BlobClient;
61+
use azure_identity::DefaultAzureCredential;
62+
63+
// Create a BlobClient that will authenticate through Microsoft Entra ID
64+
let credential = DefaultAzureCredential::new()?;
65+
let blob_client = BlobClient::new(
66+
"https://<storage_account_name>.blob.core.windows.net/", // endpoint
67+
"container_name".to_string(), // container name
68+
"blob_name".to_string(), // blob name
69+
credential, // credential
70+
Some(BlobClientOptions::default()), // BlobClient options
71+
)?;
72+
```
73+
### Upload Blob
74+
```rust
75+
use azure_storage_blob::BlobClient;
76+
use azure_identity::DefaultAzureCredential;
77+
78+
let credential = DefaultAzureCredential::new()?;
79+
let blob_client = BlobClient::new(
80+
"https://<storage_account_name>.blob.core.windows.net/",
81+
"container_name".to_string(),
82+
"blob_name".to_string(),
83+
credential,
84+
Some(BlobClientOptions::default()),
85+
)?;
86+
87+
blob_client
88+
.upload(
89+
RequestContent::from(data.to_vec()), // data
90+
false, // overwrite
91+
u64::try_from(data.len())?, // content length
92+
None, // upload options
93+
)
94+
.await?;
95+
```
96+
97+
### Get Blob Properties
98+
```rust
99+
use azure_storage_blob::BlobClient;
100+
use azure_identity::DefaultAzureCredential;
101+
102+
let credential = DefaultAzureCredential::new()?;
103+
let blob_client = BlobClient::new(
104+
"https://<storage_account_name>.blob.core.windows.net/",
105+
"container_name".to_string(),
106+
"blob_name".to_string(),
107+
credential,
108+
Some(BlobClientOptions::default()),
109+
)?;
110+
let blob_properties = blob_client.get_properties(
111+
None // get properties options
112+
)
113+
.await?;
114+
```
115+
116+
117+
## Next steps
118+
119+
### Provide feedback
120+
121+
If you encounter bugs or have suggestions, [open an issue](https://github.com/Azure/azure-sdk-for-rust/issues).
122+
123+
## Contributing
124+
125+
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [https://cla.microsoft.com](https://cla.microsoft.com).
126+
127+
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You'll only need to do this once across all repos using our CLA.
128+
129+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
130+
131+
<!-- LINKS -->
132+
[Azure subscription]: https://azure.microsoft.com/free/
133+
[Azure storage account]: https://learn.microsoft.com/azure/storage/common/storage-account-overview
134+
[Azure Portal]: https://learn.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal
135+
[Azure PowerShell]: https://learn.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell
136+
[Azure CLI]: https://learn.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli
137+
[cargo]: https://dev-doc.rust-lang.org/stable/cargo/commands/cargo.html
138+
[Azure Identity]: https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/identity/azure_identity
139+
[API reference documentation]: https://docs.rs/crate/azure_storage_blob/latest
140+
[Package (crates.io)]: https://crates.io/crates/azure_storage_blob
141+
[Source code]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/storage/azure-storage-blob
142+
[REST API documentation]: https://learn.microsoft.com/rest/api/storageservices/blob-service-rest-api
143+
[Product documentation]: https://learn.microsoft.com/azure/storage/blobs/storage-blobs-overview
144+
[Assign an Azure role for access to blob data]: https://learn.microsoft.com/azure/storage/blobs/assign-azure-role-data-access?tabs=portal

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use crate::{
1010
},
1111
models::{BlockList, BlockListType, BlockLookupList},
1212
pipeline::StorageHeadersPolicy,
13-
BlobClientDownloadOptions, BlobClientGetPropertiesOptions, BlobClientOptions,
14-
BlockBlobClientCommitBlockListOptions, BlockBlobClientGetBlockListOptions,
13+
BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions,
14+
BlobClientOptions, BlockBlobClientCommitBlockListOptions, BlockBlobClientGetBlockListOptions,
1515
BlockBlobClientStageBlockOptions, BlockBlobClientUploadOptions,
1616
};
1717
use azure_core::{
@@ -149,6 +149,19 @@ impl BlobClient {
149149
Ok(response)
150150
}
151151

152+
/// Deletes the blob.
153+
///
154+
/// # Arguments
155+
///
156+
/// * `options` - Optional configuration for the request.
157+
pub async fn delete(
158+
&self,
159+
options: Option<BlobClientDeleteOptions<'_>>,
160+
) -> Result<Response<()>> {
161+
let response = self.client.delete(options).await?;
162+
Ok(response)
163+
}
164+
152165
/// Writes to a blob based on blocks specified by the list of IDs and content that make up the blob.
153166
///
154167
/// # Arguments

sdk/storage/azure_storage_blob/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ pub use crate::generated::clients::{
1414
BlobClientOptions, BlobContainerClientOptions, BlobServiceClientOptions,
1515
};
1616
pub use crate::generated::models::{
17-
BlobClientDownloadOptions, BlobClientGetPropertiesOptions, BlobContainerClientCreateOptions,
18-
BlobContainerClientDeleteOptions, BlobContainerClientGetPropertiesOptions,
19-
BlobServiceClientGetPropertiesOptions, BlockBlobClientCommitBlockListOptions,
20-
BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions,
21-
BlockBlobClientUploadOptions,
17+
BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions,
18+
BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions,
19+
BlobContainerClientGetPropertiesOptions, BlobServiceClientGetPropertiesOptions,
20+
BlockBlobClientCommitBlockListOptions, BlockBlobClientGetBlockListOptions,
21+
BlockBlobClientStageBlockOptions, BlockBlobClientUploadOptions,
2222
};
2323

2424
pub mod models {

sdk/storage/azure_storage_blob/tests/blob_client.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,70 @@ async fn test_upload_blob(ctx: TestContext) -> Result<(), Box<dyn Error>> {
189189
Ok(())
190190
}
191191

192+
#[recorded::test]
193+
async fn test_delete_blob(ctx: TestContext) -> Result<(), Box<dyn Error>> {
194+
// Recording Setup
195+
196+
let recording = ctx.recording();
197+
let (options, endpoint) = recorded_test_setup(recording);
198+
let container_name = recording
199+
.random_string::<17>(Some("container"))
200+
.to_ascii_lowercase();
201+
let blob_name = recording
202+
.random_string::<12>(Some("blob"))
203+
.to_ascii_lowercase();
204+
205+
let container_client_options = BlobContainerClientOptions {
206+
client_options: options.clone(),
207+
..Default::default()
208+
};
209+
// Act
210+
let container_client = BlobContainerClient::new(
211+
&endpoint,
212+
container_name.clone(),
213+
recording.credential(),
214+
Some(container_client_options),
215+
)?;
216+
container_client.create_container(None).await?;
217+
218+
let blob_client_options = BlobClientOptions {
219+
client_options: options.clone(),
220+
..Default::default()
221+
};
222+
let blob_client = BlobClient::new(
223+
&endpoint,
224+
container_name,
225+
blob_name,
226+
recording.credential(),
227+
Some(blob_client_options),
228+
)?;
229+
230+
let data = b"hello rusty world";
231+
232+
blob_client
233+
.upload(
234+
RequestContent::from(data.to_vec()),
235+
false,
236+
u64::try_from(data.len())?,
237+
None,
238+
)
239+
.await?;
240+
241+
// Existence Check
242+
blob_client.get_properties(None).await?;
243+
244+
blob_client.delete(None).await?;
245+
246+
let response = blob_client.download(None).await;
247+
248+
// Assert
249+
let error = response.unwrap_err().http_status();
250+
assert_eq!(StatusCode::NotFound, error.unwrap());
251+
252+
container_client.delete_container(None).await?;
253+
Ok(())
254+
}
255+
192256
#[recorded::test]
193257
async fn test_download_blob(ctx: TestContext) -> Result<(), Box<dyn Error>> {
194258
// Recording Setup

0 commit comments

Comments
 (0)