opendal_service_gcs/
config.rs1use std::fmt::Debug;
19
20use serde::Deserialize;
21use serde::Serialize;
22
23use super::backend::GcsBuilder;
24
25#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
27#[serde(default)]
28#[non_exhaustive]
29pub struct GcsConfig {
30 pub root: Option<String>,
35 #[serde(
40 alias = "google_bucket",
41 alias = "google_bucket_name",
42 alias = "bucket_name"
43 )]
44 pub bucket: String,
45 pub endpoint: Option<String>,
51 pub scope: Option<String>,
55 #[serde(
59 alias = "google_service_account",
60 alias = "google_service_account_path",
61 alias = "service_account_path"
62 )]
63 pub service_account: Option<String>,
64 #[serde(alias = "google_service_account_key", alias = "service_account_key")]
68 pub credential: Option<String>,
69 #[serde(alias = "google_application_credentials")]
73 pub credential_path: Option<String>,
74 pub predefined_acl: Option<String>,
78 pub default_storage_class: Option<String>,
82 #[serde(alias = "google_skip_signature")]
86 pub skip_signature: bool,
87 #[deprecated(
92 since = "0.57.0",
93 note = "Please use `skip_signature` instead of `allow_anonymous`"
94 )]
95 pub allow_anonymous: bool,
96 pub disable_vm_metadata: bool,
101 pub disable_config_load: bool,
105 pub token: Option<String>,
111}
112
113impl Debug for GcsConfig {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 f.debug_struct("GcsConfig")
116 .field("root", &self.root)
117 .field("bucket", &self.bucket)
118 .field("endpoint", &self.endpoint)
119 .field("scope", &self.scope)
120 .finish_non_exhaustive()
121 }
122}
123
124impl opendal_core::Configurator for GcsConfig {
125 type Builder = GcsBuilder;
126
127 fn from_uri(uri: &opendal_core::OperatorUri) -> opendal_core::Result<Self> {
128 let mut map = uri.options().clone();
129
130 if let Some(name) = uri.name() {
131 map.insert("bucket".to_string(), name.to_string());
132 }
133
134 if let Some(root) = uri.root() {
135 map.insert("root".to_string(), root.to_string());
136 }
137
138 Self::from_iter(map)
139 }
140
141 fn into_builder(self) -> Self::Builder {
142 GcsBuilder {
143 config: self,
144 credential_provider_chain: None,
145 }
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use opendal_core::{Configurator, OperatorUri};
153
154 #[test]
155 fn test_bucket_aliases() {
156 let config_json = r#"{"google_bucket": "test-bucket"}"#;
157 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
158 assert_eq!("test-bucket", config.bucket);
159
160 let config_json = r#"{"google_bucket_name": "test-bucket-name"}"#;
161 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
162 assert_eq!("test-bucket-name", config.bucket);
163
164 let config_json = r#"{"bucket_name": "test-bucket-alias"}"#;
165 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
166 assert_eq!("test-bucket-alias", config.bucket);
167 }
168
169 #[test]
170 fn test_service_account_aliases() {
171 let config_json = r#"{"google_service_account": "/path/to/sa.json"}"#;
172 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
173 assert_eq!(Some("/path/to/sa.json".to_string()), config.service_account);
174
175 let config_json = r#"{"google_service_account_path": "/path/to/sa2.json"}"#;
176 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
177 assert_eq!(
178 Some("/path/to/sa2.json".to_string()),
179 config.service_account
180 );
181
182 let config_json = r#"{"service_account_path": "/path/to/sa3.json"}"#;
183 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
184 assert_eq!(
185 Some("/path/to/sa3.json".to_string()),
186 config.service_account
187 );
188 }
189
190 #[test]
191 fn test_credential_aliases() {
192 let config_json = r#"{"google_service_account_key": "key-content"}"#;
193 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
194 assert_eq!(Some("key-content".to_string()), config.credential);
195
196 let config_json = r#"{"service_account_key": "key-content-2"}"#;
197 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
198 assert_eq!(Some("key-content-2".to_string()), config.credential);
199 }
200
201 #[test]
202 fn test_credential_path_aliases() {
203 let config_json = r#"{"google_application_credentials": "/path/to/app.json"}"#;
204 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
205 assert_eq!(
206 Some("/path/to/app.json".to_string()),
207 config.credential_path
208 );
209 }
210
211 #[test]
212 fn test_skip_signature_aliases() {
213 let config_json = r#"{"google_skip_signature": true}"#;
214 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
215 assert!(config.skip_signature);
216
217 let config_json = r#"{"skip_signature": true}"#;
218 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
219 assert!(config.skip_signature);
220
221 let config_json = r#"{"allow_anonymous": true}"#;
222 let config: GcsConfig = serde_json::from_str(config_json).unwrap();
223 #[allow(deprecated)]
224 {
225 assert!(config.allow_anonymous);
226 }
227 }
228
229 #[test]
230 fn from_uri_extracts_bucket_and_root() {
231 let uri = OperatorUri::new(
232 "gcs://example-bucket/path/to/root",
233 Vec::<(String, String)>::new(),
234 )
235 .unwrap();
236 let cfg = GcsConfig::from_uri(&uri).unwrap();
237 assert_eq!(cfg.bucket, "example-bucket");
238 assert_eq!(cfg.root.as_deref(), Some("path/to/root"));
239 }
240}