opendal/services/gcs/
config.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::fmt::Debug;
19use std::fmt::Formatter;
20
21use serde::Deserialize;
22use serde::Serialize;
23
24/// [Google Cloud Storage](https://cloud.google.com/storage) services support.
25#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
26#[serde(default)]
27#[non_exhaustive]
28pub struct GcsConfig {
29    /// root URI, all operations happens under `root`
30    pub root: Option<String>,
31    /// bucket name
32    #[serde(
33        alias = "google_bucket",
34        alias = "google_bucket_name",
35        alias = "bucket_name"
36    )]
37    pub bucket: String,
38    /// endpoint URI of GCS service,
39    /// default is `https://storage.googleapis.com`
40    pub endpoint: Option<String>,
41    /// Scope for gcs.
42    pub scope: Option<String>,
43    /// Service Account for gcs.
44    #[serde(
45        alias = "google_service_account",
46        alias = "google_service_account_path",
47        alias = "service_account_path"
48    )]
49    pub service_account: Option<String>,
50    /// Credentials string for GCS service OAuth2 authentication.
51    #[serde(alias = "google_service_account_key", alias = "service_account_key")]
52    pub credential: Option<String>,
53    /// Local path to credentials file for GCS service OAuth2 authentication.
54    #[serde(alias = "google_application_credentials")]
55    pub credential_path: Option<String>,
56    /// The predefined acl for GCS.
57    pub predefined_acl: Option<String>,
58    /// The default storage class used by gcs.
59    pub default_storage_class: Option<String>,
60    /// Allow opendal to send requests without signing when credentials are not
61    /// loaded.
62    #[serde(alias = "google_skip_signature", alias = "skip_signature")]
63    pub allow_anonymous: bool,
64    /// Disable attempting to load credentials from the GCE metadata server when
65    /// running within Google Cloud.
66    pub disable_vm_metadata: bool,
67    /// Disable loading configuration from the environment.
68    pub disable_config_load: bool,
69    /// A Google Cloud OAuth2 token.
70    ///
71    /// Takes precedence over `credential` and `credential_path`.
72    pub token: Option<String>,
73}
74
75impl Debug for GcsConfig {
76    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77        f.debug_struct("GcsConfig")
78            .field("root", &self.root)
79            .field("bucket", &self.bucket)
80            .field("endpoint", &self.endpoint)
81            .field("scope", &self.scope)
82            .finish_non_exhaustive()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_bucket_aliases() {
92        // Test google_bucket alias
93        let config_json = r#"{"google_bucket": "test-bucket"}"#;
94        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
95        assert_eq!("test-bucket", config.bucket);
96
97        // Test google_bucket_name alias
98        let config_json = r#"{"google_bucket_name": "test-bucket-name"}"#;
99        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
100        assert_eq!("test-bucket-name", config.bucket);
101
102        // Test bucket_name alias
103        let config_json = r#"{"bucket_name": "test-bucket-alias"}"#;
104        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
105        assert_eq!("test-bucket-alias", config.bucket);
106    }
107
108    #[test]
109    fn test_service_account_aliases() {
110        // Test google_service_account alias
111        let config_json = r#"{"google_service_account": "/path/to/sa.json"}"#;
112        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
113        assert_eq!(Some("/path/to/sa.json".to_string()), config.service_account);
114
115        // Test google_service_account_path alias
116        let config_json = r#"{"google_service_account_path": "/path/to/sa2.json"}"#;
117        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
118        assert_eq!(
119            Some("/path/to/sa2.json".to_string()),
120            config.service_account
121        );
122
123        // Test service_account_path alias
124        let config_json = r#"{"service_account_path": "/path/to/sa3.json"}"#;
125        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
126        assert_eq!(
127            Some("/path/to/sa3.json".to_string()),
128            config.service_account
129        );
130    }
131
132    #[test]
133    fn test_credential_aliases() {
134        // Test google_service_account_key alias
135        let config_json = r#"{"google_service_account_key": "key-content"}"#;
136        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
137        assert_eq!(Some("key-content".to_string()), config.credential);
138
139        // Test service_account_key alias
140        let config_json = r#"{"service_account_key": "key-content-2"}"#;
141        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
142        assert_eq!(Some("key-content-2".to_string()), config.credential);
143    }
144
145    #[test]
146    fn test_credential_path_aliases() {
147        // Test google_application_credentials alias
148        let config_json = r#"{"google_application_credentials": "/path/to/app.json"}"#;
149        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
150        assert_eq!(
151            Some("/path/to/app.json".to_string()),
152            config.credential_path
153        );
154    }
155
156    #[test]
157    fn test_allow_anonymous_aliases() {
158        // Test google_skip_signature alias
159        let config_json = r#"{"google_skip_signature": true}"#;
160        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
161        assert!(config.allow_anonymous);
162
163        // Test skip_signature alias
164        let config_json = r#"{"skip_signature": true}"#;
165        let config: GcsConfig = serde_json::from_str(config_json).unwrap();
166        assert!(config.allow_anonymous);
167    }
168}