Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Storage] Initial v11 codegen output #2287

Draft
wants to merge 7 commits into
base: vincenttran/remaining_mvp_functionality
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[toolchain]
channel = "1.80.0"
components = [
"rustc",
"rustfmt",
Expand Down
110 changes: 69 additions & 41 deletions sdk/storage/azure_storage_blob/src/clients/blob_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
// Licensed under the MIT License.

use crate::{
clients::GeneratedBlobClient,
clients::{BlockBlobClient, GeneratedBlobClient},
models::{
BlobBlobClientDownloadOptions, BlobBlobClientGetPropertiesOptions,
BlobBlockBlobClientCommitBlockListOptions, BlobBlockBlobClientStageBlockOptions,
BlobBlockBlobClientUploadOptions, BlobProperties, BlockLookupList,
BlobClientDownloadOptions, BlobClientDownloadResult, BlobClientGetPropertiesOptions,
BlobClientGetPropertiesResult, BlockBlobClientCommitBlockListOptions,
BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockOptions,
BlockBlobClientStageBlockResult, BlockBlobClientUploadOptions, BlockBlobClientUploadResult,
BlockLookupList,
},
pipeline::StorageHeadersPolicy,
BlobClientOptions,
Expand All @@ -21,6 +23,7 @@ pub struct BlobClient {
endpoint: Url,
container_name: String,
blob_name: String,
credential: Arc<dyn TokenCredential>,
client: GeneratedBlobClient,
}

Expand Down Expand Up @@ -49,11 +52,19 @@ impl BlobClient {
.per_try_policies
.push(Arc::new(oauth_token_policy) as Arc<dyn Policy>);

let client = GeneratedBlobClient::new(endpoint, credential, Some(options))?;
let client = GeneratedBlobClient::new(
endpoint,
credential.clone(),
"2025-05-05".to_string(),
container_name.clone(),
blob_name.clone(),
Some(options),
)?;
Comment on lines +55 to +62
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we that we don't have an accessor BlobClient and this literally the generated client that will perform the REST operations, I think this makes some fields redundant on our handwritten clients.

Generated BlobClient struct:

pub struct BlobClient {
    pub(crate) blob: String,
    pub(crate) container_name: String,
    pub(crate) endpoint: Url,
    pub(crate) pipeline: Pipeline,
    pub(crate) version: String,
}

We can now omit blob_name, container_name, endpoint from the handwritten client layer and instead do self.client.<field>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omit from struct, add getters (that will go 1 layer down into gen client)

Ok(Self {
endpoint: endpoint.parse()?,
container_name,
blob_name,
credential,
client,
})
}
Expand All @@ -70,29 +81,23 @@ impl BlobClient {
&self.blob_name
}

pub fn credential(&self) -> Arc<dyn TokenCredential> {
self.credential.clone()
}

pub async fn get_blob_properties(
&self,
options: Option<BlobBlobClientGetPropertiesOptions<'_>>,
) -> Result<BlobProperties> {
let response = self
.client
.get_blob_blob_client(self.container_name.clone(), self.blob_name.clone())
.get_properties(options)
.await?;

let blob_properties: BlobProperties = response.headers().get()?;
Ok(blob_properties)
options: Option<BlobClientGetPropertiesOptions<'_>>,
) -> Result<Response<BlobClientGetPropertiesResult>> {
let response = self.client.get_properties(options).await?;
Ok(response)
}

pub async fn download_blob(
&self,
options: Option<BlobBlobClientDownloadOptions<'_>>,
) -> Result<Response> {
let response = self
.client
.get_blob_blob_client(self.container_name.clone(), self.blob_name.clone())
.download(options)
.await?;
options: Option<BlobClientDownloadOptions<'_>>,
) -> Result<Response<BlobClientDownloadResult>> {
let response = self.client.download(options).await?;
Ok(response)
}

Expand All @@ -101,48 +106,71 @@ impl BlobClient {
&self,
data: RequestContent<Bytes>,
overwrite: bool,
content_length: i64,
options: Option<BlobBlockBlobClientUploadOptions<'_>>,
) -> Result<Response<()>> {
content_length: u64,
options: Option<BlockBlobClientUploadOptions<'_>>,
) -> Result<Response<BlockBlobClientUploadResult>> {
let mut options = options.unwrap_or_default();

// Check if they want overwrite, by default overwrite=False
if !overwrite {
options.if_none_match = Some(String::from("*"));
}

let response = self
.client
.get_blob_block_blob_client(self.container_name.clone(), self.blob_name.clone())
// Currently there is no way to alter what options you pass to the BlockBlobClient we spin up on-demand
// We could inherit the ClientOptions from the current BlobClient to resolve the recording issue
let block_blob_client = BlockBlobClient::new(
self.endpoint().as_str(),
self.credential(),
"2025-05-05".to_string(),
self.container_name().to_string(),
self.blob_name().to_string(),
None,
)?;

let response = block_blob_client
.upload(data, content_length, Some(options))
.await?;
println!("Resp inside of upload_blob API: {:?}", response);
Ok(response)
}

pub async fn commit_block_list(
&self,
blocks: RequestContent<BlockLookupList>,
options: Option<BlobBlockBlobClientCommitBlockListOptions<'_>>,
) -> Result<Response<()>> {
let response = self
.client
.get_blob_block_blob_client(self.container_name.clone(), self.blob_name.clone())
.commit_block_list(blocks, options)
.await?;
options: Option<BlockBlobClientCommitBlockListOptions<'_>>,
) -> Result<Response<BlockBlobClientCommitBlockListResult>> {
// Currently there is no way to alter what options you pass to the BlockBlobClient we spin up on-demand
let block_blob_client = BlockBlobClient::new(
self.endpoint().as_str(),
self.credential(),
"2025-05-05".to_string(),
self.container_name().to_string(),
self.blob_name().to_string(),
None,
)?;
let response = block_blob_client.commit_block_list(blocks, options).await?;
Ok(response)
}

pub async fn stage_block(
&self,
block_id: &str,
content_length: i64,
content_length: u64,
body: RequestContent<Bytes>,
options: Option<BlobBlockBlobClientStageBlockOptions<'_>>,
) -> Result<Response<()>> {
options: Option<BlockBlobClientStageBlockOptions<'_>>,
) -> Result<Response<BlockBlobClientStageBlockResult>> {
let block_id = base64::encode(block_id);
let response = self
.client
.get_blob_block_blob_client(self.container_name.clone(), self.blob_name.clone())
// Currently there is no way to alter what options you pass to the BlockBlobClient we spin up on-demand
let block_blob_client = BlockBlobClient::new(
self.endpoint().as_str(),
self.credential(),
"2025-05-05".to_string(),
self.container_name().to_string(),
self.blob_name().to_string(),
None,
)?;

let response = block_blob_client
.stage_block(&block_id, content_length, body, options)
.await?;
Ok(response)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

use crate::clients::GeneratedBlobClient;
use crate::clients::GeneratedBlobContainerClient;
use crate::models::{
BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions,
BlobContainerClientGetPropertiesOptions, ContainerProperties,
BlobContainerClientCreateOptions, BlobContainerClientCreateResult,
BlobContainerClientDeleteOptions, BlobContainerClientDeleteResult,
BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult,
};
use crate::pipeline::StorageHeadersPolicy;
use crate::BlobClientOptions;
use crate::BlobContainerClientOptions;
use azure_core::{
credentials::TokenCredential, BearerTokenCredentialPolicy, Policy, Response, Result, Url,
};
Expand All @@ -16,15 +17,15 @@ use std::sync::Arc;
pub struct BlobContainerClient {
endpoint: Url,
container_name: String,
client: GeneratedBlobClient,
client: GeneratedBlobContainerClient,
}

impl BlobContainerClient {
pub fn new(
endpoint: &str,
container_name: String,
credential: Arc<dyn TokenCredential>,
options: Option<BlobClientOptions>,
options: Option<BlobContainerClientOptions>,
) -> Result<Self> {
let mut options = options.unwrap_or_default();

Expand All @@ -43,7 +44,12 @@ impl BlobContainerClient {
.per_try_policies
.push(Arc::new(oauth_token_policy) as Arc<dyn Policy>);

let client = GeneratedBlobClient::new(endpoint, credential, Some(options))?;
let client = GeneratedBlobContainerClient::new(
endpoint,
credential,
container_name.clone(),
Some(options),
)?;

Ok(Self {
endpoint: endpoint.parse()?,
Expand All @@ -63,38 +69,25 @@ impl BlobContainerClient {
pub async fn create_container(
&self,
options: Option<BlobContainerClientCreateOptions<'_>>,
) -> Result<Response<()>> {
let response = self
.client
.get_blob_container_client(self.container_name.clone())
.create(options)
.await?;
) -> Result<Response<BlobContainerClientCreateResult>> {
let response = self.client.create(options).await?;
Ok(response)
}

pub async fn delete_container(
&self,
options: Option<BlobContainerClientDeleteOptions<'_>>,
) -> Result<Response<()>> {
let response = self
.client
.get_blob_container_client(self.container_name.clone())
.delete(options)
.await?;
) -> Result<Response<BlobContainerClientDeleteResult>> {
let response = self.client.delete(options).await?;
Ok(response)
}

pub async fn get_container_properties(
&self,
options: Option<BlobContainerClientGetPropertiesOptions<'_>>,
) -> Result<ContainerProperties> {
let response = self
.client
.get_blob_container_client(self.container_name.clone())
.get_properties(options)
.await?;
) -> Result<Response<BlobContainerClientGetPropertiesResult>> {
let response = self.client.get_properties(options).await?;

let container_properties: ContainerProperties = response.headers().get()?;
Ok(container_properties)
Ok(response)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// Licensed under the MIT License.

use crate::{
clients::GeneratedBlobClient,
clients::GeneratedBlobServiceClient,
models::{BlobServiceClientGetPropertiesOptions, StorageServiceProperties},
pipeline::StorageHeadersPolicy,
BlobClientOptions,
BlobServiceClientOptions,
};
use azure_core::{
credentials::TokenCredential, BearerTokenCredentialPolicy, Policy, Response, Result, Url,
Expand All @@ -14,14 +14,14 @@ use std::sync::Arc;

pub struct BlobServiceClient {
endpoint: Url,
client: GeneratedBlobClient,
client: GeneratedBlobServiceClient,
}

impl BlobServiceClient {
pub fn new(
endpoint: &str,
credential: Arc<dyn TokenCredential>,
options: Option<BlobClientOptions>,
options: Option<BlobServiceClientOptions>,
) -> Result<Self> {
let mut options = options.unwrap_or_default();

Expand All @@ -40,7 +40,7 @@ impl BlobServiceClient {
.per_try_policies
.push(Arc::new(oauth_token_policy) as Arc<dyn Policy>);

let client = GeneratedBlobClient::new(endpoint, credential, Some(options))?;
let client = GeneratedBlobServiceClient::new(endpoint, credential, Some(options))?;

Ok(Self {
endpoint: endpoint.parse()?,
Expand All @@ -56,11 +56,7 @@ impl BlobServiceClient {
&self,
options: Option<BlobServiceClientGetPropertiesOptions<'_>>,
) -> Result<Response<StorageServiceProperties>> {
let response = self
.client
.get_blob_service_client()
.get_properties(options)
.await?;
let response = self.client.get_properties(options).await?;
Ok(response)
}
}
Loading