opendal/services/azdls/
config.rs1use std::fmt::Debug;
19
20use serde::Deserialize;
21use serde::Serialize;
22
23use super::AZDLS_SCHEME;
24use super::backend::AzdlsBuilder;
25
26#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
28pub struct AzdlsConfig {
29 pub root: Option<String>,
31 pub filesystem: String,
33 pub endpoint: Option<String>,
35 pub account_name: Option<String>,
37 pub account_key: Option<String>,
40 pub client_secret: Option<String>,
44 pub tenant_id: Option<String>,
48 pub client_id: Option<String>,
52 pub sas_token: Option<String>,
56 pub authority_host: Option<String>,
61}
62
63impl Debug for AzdlsConfig {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 f.debug_struct("AzdlsConfig")
66 .field("root", &self.root)
67 .field("filesystem", &self.filesystem)
68 .field("endpoint", &self.endpoint)
69 .finish_non_exhaustive()
70 }
71}
72
73impl crate::Configurator for AzdlsConfig {
74 type Builder = AzdlsBuilder;
75
76 fn from_uri(uri: &crate::types::OperatorUri) -> crate::Result<Self> {
77 let authority = uri.authority().ok_or_else(|| {
78 crate::Error::new(crate::ErrorKind::ConfigInvalid, "uri authority is required")
79 .with_context("service", AZDLS_SCHEME)
80 })?;
81
82 let mut map = uri.options().clone();
83 map.insert("endpoint".to_string(), format!("https://{authority}"));
84
85 if let Some(host) = uri.name() {
86 if let Some(account) = host.split('.').next() {
87 if !account.is_empty() {
88 map.entry("account_name".to_string())
89 .or_insert_with(|| account.to_string());
90 }
91 }
92 }
93
94 if let Some(root) = uri.root() {
95 if let Some((filesystem, rest)) = root.split_once('/') {
96 if filesystem.is_empty() {
97 return Err(crate::Error::new(
98 crate::ErrorKind::ConfigInvalid,
99 "filesystem is required in uri path",
100 )
101 .with_context("service", AZDLS_SCHEME));
102 }
103 map.insert("filesystem".to_string(), filesystem.to_string());
104 if !rest.is_empty() {
105 map.insert("root".to_string(), rest.to_string());
106 }
107 } else if !root.is_empty() {
108 map.insert("filesystem".to_string(), root.to_string());
109 }
110 }
111
112 if !map.contains_key("filesystem") {
113 return Err(crate::Error::new(
114 crate::ErrorKind::ConfigInvalid,
115 "filesystem is required",
116 )
117 .with_context("service", AZDLS_SCHEME));
118 }
119
120 Self::from_iter(map)
121 }
122
123 #[allow(deprecated)]
124 fn into_builder(self) -> Self::Builder {
125 AzdlsBuilder {
126 config: self,
127 http_client: None,
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use crate::Configurator;
136 use crate::types::OperatorUri;
137
138 #[test]
139 fn from_uri_sets_endpoint_filesystem_root_and_account() {
140 let uri = OperatorUri::new(
141 "azdls://account.dfs.core.windows.net/fs/data/2024",
142 Vec::<(String, String)>::new(),
143 )
144 .unwrap();
145
146 let cfg = AzdlsConfig::from_uri(&uri).unwrap();
147 assert_eq!(
148 cfg.endpoint.as_deref(),
149 Some("https://account.dfs.core.windows.net")
150 );
151 assert_eq!(cfg.filesystem, "fs".to_string());
152 assert_eq!(cfg.root.as_deref(), Some("data/2024"));
153 assert_eq!(cfg.account_name.as_deref(), Some("account"));
154 }
155
156 #[test]
157 fn from_uri_accepts_filesystem_from_query() {
158 let uri = OperatorUri::new(
159 "azdls://account.dfs.core.windows.net",
160 vec![("filesystem".to_string(), "logs".to_string())],
161 )
162 .unwrap();
163
164 let cfg = AzdlsConfig::from_uri(&uri).unwrap();
165 assert_eq!(cfg.filesystem, "logs".to_string());
166 }
167}