Skip to content

Commit 1e847c9

Browse files
authored
support find blobs by tags operation (#439)
1 parent ec9cc59 commit 1e847c9

File tree

5 files changed

+173
-0
lines changed

5 files changed

+173
-0
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use crate::account::responses::ListBlobsByTagsResponse;
2+
use crate::core::prelude::*;
3+
use azure_core::headers::add_optional_header;
4+
use azure_core::prelude::*;
5+
use std::convert::TryInto;
6+
7+
#[derive(Debug, Clone)]
8+
pub struct FindBlobsByTagsBuilder<'a> {
9+
client: &'a StorageClient,
10+
expression: String,
11+
lease_id: Option<&'a str>,
12+
next_marker: Option<NextMarker>,
13+
max_results: Option<MaxResults>,
14+
client_request_id: Option<ClientRequestId<'a>>,
15+
timeout: Option<Timeout>,
16+
}
17+
18+
impl<'a> FindBlobsByTagsBuilder<'a> {
19+
pub(crate) fn new(client: &'a StorageClient) -> Self {
20+
Self {
21+
client,
22+
expression: "".to_string(),
23+
lease_id: None,
24+
next_marker: None,
25+
max_results: None,
26+
client_request_id: None,
27+
timeout: None,
28+
}
29+
}
30+
31+
setters! {
32+
expression: String => expression,
33+
next_marker: NextMarker => Some(next_marker),
34+
max_results: MaxResults => Some(max_results),
35+
client_request_id: ClientRequestId<'a> => Some(client_request_id),
36+
timeout: Timeout => Some(timeout),
37+
}
38+
39+
pub async fn execute(
40+
&self,
41+
) -> Result<ListBlobsByTagsResponse, Box<dyn std::error::Error + Send + Sync>> {
42+
let mut url = self
43+
.client
44+
.storage_account_client()
45+
.blob_storage_url()
46+
.to_owned();
47+
48+
self.timeout.append_to_url_query(&mut url);
49+
url.query_pairs_mut().append_pair("comp", "blobs");
50+
url.query_pairs_mut().append_pair("where", &self.expression);
51+
52+
trace!("url == {:?}", url);
53+
54+
let (request, _url) = self.client.prepare_request(
55+
url.as_str(),
56+
&http::Method::GET,
57+
&|mut request| {
58+
request = add_optional_header(&self.client_request_id, request);
59+
request
60+
},
61+
None,
62+
)?;
63+
64+
let response = self
65+
.client
66+
.http_client()
67+
.execute_request_check_status(request, http::StatusCode::OK)
68+
.await?;
69+
70+
debug!("response.headers() == {:#?}", response.headers());
71+
72+
Ok((&response).try_into()?)
73+
}
74+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
mod find_blobs_by_tags_builder;
12
mod get_account_information_builder;
3+
pub use self::find_blobs_by_tags_builder::FindBlobsByTagsBuilder;
24
pub use self::get_account_information_builder::GetAccountInformationBuilder;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use crate::xml::read_xml;
2+
use azure_core::headers::{date_from_headers, request_id_from_headers};
3+
use azure_core::prelude::NextMarker;
4+
use azure_core::RequestId;
5+
use bytes::Bytes;
6+
use chrono::{DateTime, Utc};
7+
use std::convert::TryFrom;
8+
9+
#[derive(Debug, Clone, PartialEq)]
10+
pub struct ListBlobsByTagsResponse {
11+
pub max_results: Option<u32>,
12+
pub delimiter: Option<String>,
13+
pub next_marker: Option<NextMarker>,
14+
pub r#where: Option<String>,
15+
pub blobs: Blobs,
16+
pub request_id: RequestId,
17+
pub date: DateTime<Utc>,
18+
}
19+
20+
#[derive(Debug, Clone, PartialEq, Deserialize)]
21+
#[serde(rename_all = "PascalCase")]
22+
struct ListBlobsByTagsResponseInternal {
23+
pub max_results: Option<u32>,
24+
pub delimiter: Option<String>,
25+
pub next_marker: Option<String>,
26+
pub r#where: Option<String>,
27+
pub blobs: Blobs,
28+
}
29+
30+
#[derive(Debug, Clone, PartialEq, Deserialize)]
31+
#[serde(rename_all = "PascalCase")]
32+
pub struct Blobs {
33+
#[serde(rename = "Blob", default = "Vec::new")]
34+
pub blobs: Vec<Blob>,
35+
}
36+
37+
#[derive(Debug, Clone, PartialEq, Deserialize)]
38+
#[serde(rename_all = "PascalCase")]
39+
pub struct Blob {
40+
pub name: String,
41+
pub container_name: String,
42+
pub tag_value: String,
43+
}
44+
45+
impl TryFrom<&http::Response<Bytes>> for ListBlobsByTagsResponse {
46+
type Error = crate::Error;
47+
48+
fn try_from(response: &http::Response<Bytes>) -> Result<Self, Self::Error> {
49+
let body = response.body();
50+
51+
trace!("body == {:?}", body);
52+
let list_blobs_response_internal: ListBlobsByTagsResponseInternal = read_xml(body)?;
53+
54+
Ok(Self {
55+
request_id: request_id_from_headers(response.headers())?,
56+
date: date_from_headers(response.headers())?,
57+
max_results: list_blobs_response_internal.max_results,
58+
delimiter: list_blobs_response_internal.delimiter,
59+
r#where: list_blobs_response_internal.r#where,
60+
blobs: list_blobs_response_internal.blobs,
61+
next_marker: NextMarker::from_possibly_empty_string(
62+
list_blobs_response_internal.next_marker,
63+
),
64+
})
65+
}
66+
}
67+
68+
#[cfg(test)]
69+
mod tests {
70+
use super::*;
71+
72+
#[test]
73+
fn deserde_azure() {
74+
const S: &'static str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
75+
<EnumerationResults ServiceEndpoint=\"https://hsdgeventstoredev.blob.core.windows.net/\">
76+
<Where>tag1='value1'</Where>
77+
<Blobs>
78+
<Blob>
79+
<Name>test1</Name>
80+
<ContainerName>container1</ContainerName>
81+
<TagValue>value1</TagValue>
82+
</Blob>
83+
</Blobs>
84+
<NextMarker/>
85+
</EnumerationResults>";
86+
87+
let bytes = Bytes::from(S);
88+
let _list_blobs_response_internal: ListBlobsByTagsResponseInternal =
89+
read_xml(&bytes).unwrap();
90+
}
91+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
mod get_account_information_response;
2+
mod list_blobs_by_tags_response;
23
pub use get_account_information_response::GetAccountInformationResponse;
4+
pub use list_blobs_by_tags_response::ListBlobsByTagsResponse;

sdk/storage/src/core/clients/storage_client.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ impl StorageClient {
8484
crate::account::requests::GetAccountInformationBuilder::new(self)
8585
}
8686

87+
pub fn find_blobs_by_tags(&self) -> crate::account::requests::FindBlobsByTagsBuilder {
88+
crate::account::requests::FindBlobsByTagsBuilder::new(self)
89+
}
90+
8791
#[cfg(feature = "blob")]
8892
pub fn list_containers(&self) -> crate::container::requests::ListContainersBuilder {
8993
crate::container::requests::ListContainersBuilder::new(self)

0 commit comments

Comments
 (0)