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 { config: self }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use opendal_core::Configurator;
126 use opendal_core::OperatorUri;
127
128 #[test]
129 fn test_container_name_aliases() {
130 let json = r#"{"container": "test-container"}"#;
131 let config: AzblobConfig = serde_json::from_str(json).unwrap();
132 assert_eq!(config.container, "test-container");
133
134 let json = r#"{"azure_container_name": "test-container"}"#;
135 let config: AzblobConfig = serde_json::from_str(json).unwrap();
136 assert_eq!(config.container, "test-container");
137
138 let json = r#"{"container_name": "test-container"}"#;
139 let config: AzblobConfig = serde_json::from_str(json).unwrap();
140 assert_eq!(config.container, "test-container");
141 }
142
143 #[test]
144 fn test_account_name_aliases() {
145 let json = r#"{"container": "test", "account_name": "testaccount"}"#;
146 let config: AzblobConfig = serde_json::from_str(json).unwrap();
147 assert_eq!(config.account_name, Some("testaccount".to_string()));
148
149 let json = r#"{"container": "test", "azure_storage_account_name": "testaccount-azure"}"#;
150 let config: AzblobConfig = serde_json::from_str(json).unwrap();
151 assert_eq!(config.account_name, Some("testaccount-azure".to_string()));
152 }
153
154 #[test]
155 fn test_account_key_aliases() {
156 let json = r#"{"container": "test", "account_key": "dGVzdGtleQ=="}"#;
157 let config: AzblobConfig = serde_json::from_str(json).unwrap();
158 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
159
160 let json = r#"{"container": "test", "azure_storage_account_key": "dGVzdGtleQ=="}"#;
161 let config: AzblobConfig = serde_json::from_str(json).unwrap();
162 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
163
164 let json = r#"{"container": "test", "azure_storage_access_key": "dGVzdGtleQ=="}"#;
165 let config: AzblobConfig = serde_json::from_str(json).unwrap();
166 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
167
168 let json = r#"{"container": "test", "azure_storage_master_key": "dGVzdGtleQ=="}"#;
169 let config: AzblobConfig = serde_json::from_str(json).unwrap();
170 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
171
172 let json = r#"{"container": "test", "access_key": "dGVzdGtleQ=="}"#;
173 let config: AzblobConfig = serde_json::from_str(json).unwrap();
174 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
175
176 let json = r#"{"container": "test", "master_key": "dGVzdGtleQ=="}"#;
177 let config: AzblobConfig = serde_json::from_str(json).unwrap();
178 assert_eq!(config.account_key, Some("dGVzdGtleQ==".to_string()));
179 }
180
181 #[test]
182 fn test_sas_token_aliases() {
183 let json = r#"{"container": "test", "sas_token": "test-token"}"#;
184 let config: AzblobConfig = serde_json::from_str(json).unwrap();
185 assert_eq!(config.sas_token, Some("test-token".to_string()));
186
187 let json = r#"{"container": "test", "azure_storage_sas_key": "test-token"}"#;
188 let config: AzblobConfig = serde_json::from_str(json).unwrap();
189 assert_eq!(config.sas_token, Some("test-token".to_string()));
190
191 let json = r#"{"container": "test", "azure_storage_sas_token": "test-token"}"#;
192 let config: AzblobConfig = serde_json::from_str(json).unwrap();
193 assert_eq!(config.sas_token, Some("test-token".to_string()));
194
195 let json = r#"{"container": "test", "sas_key": "test-token"}"#;
196 let config: AzblobConfig = serde_json::from_str(json).unwrap();
197 assert_eq!(config.sas_token, Some("test-token".to_string()));
198 }
199
200 #[test]
201 fn test_endpoint_aliases() {
202 let json = r#"{"container": "test", "endpoint": "https://test.blob.core.windows.net"}"#;
203 let config: AzblobConfig = serde_json::from_str(json).unwrap();
204 assert_eq!(
205 config.endpoint,
206 Some("https://test.blob.core.windows.net".to_string())
207 );
208
209 let json = r#"{"container": "test", "azure_storage_endpoint": "https://test.blob.core.windows.net"}"#;
210 let config: AzblobConfig = serde_json::from_str(json).unwrap();
211 assert_eq!(
212 config.endpoint,
213 Some("https://test.blob.core.windows.net".to_string())
214 );
215
216 let json =
217 r#"{"container": "test", "azure_endpoint": "https://test.blob.core.windows.net"}"#;
218 let config: AzblobConfig = serde_json::from_str(json).unwrap();
219 assert_eq!(
220 config.endpoint,
221 Some("https://test.blob.core.windows.net".to_string())
222 );
223 }
224
225 #[test]
226 fn from_uri_with_host_container() {
227 let uri = OperatorUri::new(
228 "azblob://my-container/path/to/root",
229 Vec::<(String, String)>::new(),
230 )
231 .unwrap();
232 let cfg = AzblobConfig::from_uri(&uri).unwrap();
233 assert_eq!(cfg.container, "my-container");
234 assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
235 }
236
237 #[test]
238 fn from_uri_with_path_container() {
239 let uri = OperatorUri::new(
240 "azblob://my-container/nested/root",
241 Vec::<(String, String)>::new(),
242 )
243 .unwrap();
244 let cfg = AzblobConfig::from_uri(&uri).unwrap();
245 assert_eq!(cfg.container, "my-container");
246 assert_eq!(cfg.root.as_deref(), Some("nested/root"));
247 }
248}