opendal_service_azblob/
config.rs1use std::fmt::Debug;
19
20use serde::Deserialize;
21use serde::Serialize;
22
23use super::backend::AzblobBuilder;
24
25#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
27pub struct AzblobConfig {
28 pub root: Option<String>,
32
33 #[serde(alias = "azure_container_name", alias = "container_name")]
35 pub container: String,
36
37 #[serde(alias = "azure_storage_endpoint", alias = "azure_endpoint")]
44 pub endpoint: Option<String>,
45
46 #[serde(alias = "azure_storage_account_name")]
48 pub account_name: Option<String>,
49
50 #[serde(
52 alias = "azure_storage_account_key",
53 alias = "azure_storage_access_key",
54 alias = "azure_storage_master_key",
55 alias = "access_key",
56 alias = "master_key"
57 )]
58 pub account_key: Option<String>,
59
60 pub encryption_key: Option<String>,
62
63 pub encryption_key_sha256: Option<String>,
65
66 pub encryption_algorithm: Option<String>,
68
69 #[serde(
71 alias = "azure_storage_sas_key",
72 alias = "azure_storage_sas_token",
73 alias = "sas_key"
74 )]
75 pub sas_token: Option<String>,
76
77 #[deprecated(
79 since = "0.57.0",
80 note = "Azblob delete batch capability is enabled by default with Azure Blob's 256-operation batch limit. Use CapabilityOverrideLayer to override delete_max_size for specific endpoints."
81 )]
82 pub batch_max_operations: Option<usize>,
83
84 #[serde(default)]
86 pub skip_signature: bool,
87}
88
89impl Debug for AzblobConfig {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 f.debug_struct("AzblobConfig")
92 .field("root", &self.root)
93 .field("container", &self.container)
94 .field("endpoint", &self.endpoint)
95 .finish_non_exhaustive()
96 }
97}
98
99impl opendal_core::Configurator for AzblobConfig {
100 type Builder = AzblobBuilder;
101
102 fn from_uri(uri: &opendal_core::OperatorUri) -> opendal_core::Result<Self> {
103 let mut map = uri.options().clone();
104
105 if let Some(container) = uri.name() {
106 map.insert("container".to_string(), container.to_string());
107 }
108
109 if let Some(root) = uri.root() {
110 map.insert("root".to_string(), root.to_string());
111 }
112
113 Self::from_iter(map)
114 }
115
116 #[allow(deprecated)]
117 fn into_builder(self) -> Self::Builder {
118 AzblobBuilder {
119 config: self,
120 credential_providers: None,
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use opendal_core::Configurator;
129 use opendal_core::OperatorUri;
130
131 #[test]
132 fn test_container_name_aliases() {
133 let json = r#"{"container": "test-container"}"#;
134 let config: AzblobConfig = serde_json::from_str(json).unwrap();
135 assert_eq!(config.container, "test-container");
136
137 let json = r#"{"azure_container_name": "test-container"}"#;
138 let config: AzblobConfig = serde_json::from_str(json).unwrap();
139 assert_eq!(config.container, "test-container");
140
141 let json = r#"{"container_name": "test-container"}"#;
142 let config: AzblobConfig = serde_json::from_str(json).unwrap();
143 assert_eq!(config.container, "test-container");
144 }
145
146 #[test]
147 fn test_account_name_aliases() {
148 let json = r#"{"container": "test", "account_name": "testaccount"}"#;
149 let config: AzblobConfig = serde_json::from_str(json).unwrap();
150 assert_eq!(config.account_name, Some("testaccount".to_string()));
151
152 let json = r#"{"container": "test", "azure_storage_account_name": "testaccount-azure"}"#;
153 let config: AzblobConfig = serde_json::from_str(json).unwrap();
154 assert_eq!(config.account_name, Some("testaccount-azure".to_string()));
155 }
156
157 #[test]
158 fn test_account_key_aliases() {
159 let json = r#"{"container": "test", "account_key": "dGVzdGtleQ=="}"#;
160 let config: AzblobConfig = serde_json::from_str(json).unwrap();
161 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
162
163 let json = r#"{"container": "test", "azure_storage_account_key": "dGVzdGtleQ=="}"#;
164 let config: AzblobConfig = serde_json::from_str(json).unwrap();
165 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
166
167 let json = r#"{"container": "test", "azure_storage_access_key": "dGVzdGtleQ=="}"#;
168 let config: AzblobConfig = serde_json::from_str(json).unwrap();
169 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
170
171 let json = r#"{"container": "test", "azure_storage_master_key": "dGVzdGtleQ=="}"#;
172 let config: AzblobConfig = serde_json::from_str(json).unwrap();
173 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
174
175 let json = r#"{"container": "test", "access_key": "dGVzdGtleQ=="}"#;
176 let config: AzblobConfig = serde_json::from_str(json).unwrap();
177 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
178
179 let json = r#"{"container": "test", "master_key": "dGVzdGtleQ=="}"#;
180 let config: AzblobConfig = serde_json::from_str(json).unwrap();
181 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
182 }
183
184 #[test]
185 fn test_sas_token_aliases() {
186 let json = r#"{"container": "test", "sas_token": "test-token"}"#;
187 let config: AzblobConfig = serde_json::from_str(json).unwrap();
188 assert_eq!(config.sas_token, Some("test-token".to_string()));
189
190 let json = r#"{"container": "test", "azure_storage_sas_key": "test-token"}"#;
191 let config: AzblobConfig = serde_json::from_str(json).unwrap();
192 assert_eq!(config.sas_token, Some("test-token".to_string()));
193
194 let json = r#"{"container": "test", "azure_storage_sas_token": "test-token"}"#;
195 let config: AzblobConfig = serde_json::from_str(json).unwrap();
196 assert_eq!(config.sas_token, Some("test-token".to_string()));
197
198 let json = r#"{"container": "test", "sas_key": "test-token"}"#;
199 let config: AzblobConfig = serde_json::from_str(json).unwrap();
200 assert_eq!(config.sas_token, Some("test-token".to_string()));
201 }
202
203 #[test]
204 fn test_endpoint_aliases() {
205 let json = r#"{"container": "test", "endpoint": "https://test.blob.core.windows.net"}"#;
206 let config: AzblobConfig = serde_json::from_str(json).unwrap();
207 assert_eq!(
208 config.endpoint,
209 Some("https://test.blob.core.windows.net".to_string())
210 );
211
212 let json = r#"{"container": "test", "azure_storage_endpoint": "https://test.blob.core.windows.net"}"#;
213 let config: AzblobConfig = serde_json::from_str(json).unwrap();
214 assert_eq!(
215 config.endpoint,
216 Some("https://test.blob.core.windows.net".to_string())
217 );
218
219 let json =
220 r#"{"container": "test", "azure_endpoint": "https://test.blob.core.windows.net"}"#;
221 let config: AzblobConfig = serde_json::from_str(json).unwrap();
222 assert_eq!(
223 config.endpoint,
224 Some("https://test.blob.core.windows.net".to_string())
225 );
226 }
227
228 #[test]
229 fn from_uri_with_host_container() {
230 let uri = OperatorUri::new(
231 "azblob://my-container/path/to/root",
232 Vec::<(String, String)>::new(),
233 )
234 .unwrap();
235 let cfg = AzblobConfig::from_uri(&uri).unwrap();
236 assert_eq!(cfg.container, "my-container");
237 assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
238 }
239
240 #[test]
241 fn from_uri_with_path_container() {
242 let uri = OperatorUri::new(
243 "azblob://my-container/nested/root",
244 Vec::<(String, String)>::new(),
245 )
246 .unwrap();
247 let cfg = AzblobConfig::from_uri(&uri).unwrap();
248 assert_eq!(cfg.container, "my-container");
249 assert_eq!(cfg.root.as_deref(), Some("nested/root"));
250 }
251}