common_datasource/object_store/
oss.rs1use std::collections::HashMap;
16
17use object_store::ObjectStore;
18use object_store::services::Oss;
19use object_store::util::{with_instrument_layers, with_retry_layers};
20use snafu::ResultExt;
21
22use crate::error::{self, Result};
23
24const BUCKET: &str = "bucket";
25const ENDPOINT: &str = "endpoint";
26const ACCESS_KEY_ID: &str = "access_key_id";
27const ACCESS_KEY_SECRET: &str = "access_key_secret";
28const ROOT: &str = "root";
29const ALLOW_ANONYMOUS: &str = "allow_anonymous";
30const SKIP_SIGNATURE: &str = "skip_signature";
31
32pub fn is_supported_in_oss(key: &str) -> bool {
34 [
35 ROOT,
36 ALLOW_ANONYMOUS,
37 SKIP_SIGNATURE,
38 BUCKET,
39 ENDPOINT,
40 ACCESS_KEY_ID,
41 ACCESS_KEY_SECRET,
42 ]
43 .contains(&key)
44}
45
46pub fn build_oss_backend(
48 bucket: &str,
49 root: &str,
50 connection: &HashMap<String, String>,
51) -> Result<ObjectStore> {
52 let mut builder = Oss::default().bucket(bucket).root(root);
53
54 if let Some(endpoint) = connection.get(ENDPOINT) {
55 builder = builder.endpoint(endpoint);
56 }
57
58 if let Some(access_key_id) = connection.get(ACCESS_KEY_ID) {
59 builder = builder.access_key_id(access_key_id);
60 }
61
62 if let Some(access_key_secret) = connection.get(ACCESS_KEY_SECRET) {
63 builder = builder.access_key_secret(access_key_secret);
64 }
65
66 if let Some((key, value)) = connection
67 .get(SKIP_SIGNATURE)
68 .map(|value| (SKIP_SIGNATURE, value))
69 .or_else(|| {
70 connection
71 .get(ALLOW_ANONYMOUS)
72 .map(|value| (ALLOW_ANONYMOUS, value))
73 })
74 {
75 let skip_signature = value.as_str().parse::<bool>().map_err(|e| {
76 error::InvalidConnectionSnafu {
77 msg: format!("failed to parse the option {}={}, {}", key, value, e),
78 }
79 .build()
80 })?;
81 if skip_signature {
82 builder = builder.skip_signature();
83 }
84 }
85
86 let object_store = ObjectStore::new(builder).context(error::BuildBackendSnafu)?;
87 Ok(with_instrument_layers(
88 with_retry_layers(object_store),
89 true,
90 ))
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_is_supported_in_oss() {
99 assert!(is_supported_in_oss(ROOT));
100 assert!(is_supported_in_oss(ALLOW_ANONYMOUS));
101 assert!(is_supported_in_oss(SKIP_SIGNATURE));
102 assert!(is_supported_in_oss(BUCKET));
103 assert!(is_supported_in_oss(ENDPOINT));
104 assert!(is_supported_in_oss(ACCESS_KEY_ID));
105 assert!(is_supported_in_oss(ACCESS_KEY_SECRET));
106 assert!(!is_supported_in_oss("foo"));
107 assert!(!is_supported_in_oss("BAR"));
108 }
109
110 #[test]
111 fn test_build_oss_backend_all_fields_valid() {
112 let mut connection = HashMap::new();
113 connection.insert(
114 ENDPOINT.to_string(),
115 "http://oss-ap-southeast-1.aliyuncs.com".to_string(),
116 );
117 connection.insert(ACCESS_KEY_ID.to_string(), "key_id".to_string());
118 connection.insert(ACCESS_KEY_SECRET.to_string(), "key_secret".to_string());
119 connection.insert(ALLOW_ANONYMOUS.to_string(), "true".to_string());
120
121 let result = build_oss_backend("my-bucket", "my-root", &connection);
122 assert!(result.is_ok());
123 }
124}