Skip to main content

iceberg/io/storage/config/
azdls.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
18//! Azure Data Lake Storage configuration.
19//!
20//! This module provides configuration constants and types for Azure Data Lake Storage.
21
22use serde::{Deserialize, Serialize};
23use typed_builder::TypedBuilder;
24
25use super::StorageConfig;
26use crate::Result;
27
28/// A connection string.
29///
30/// Note, this string is parsed first, and any other passed adls.* properties
31/// will override values from the connection string.
32pub const ADLS_CONNECTION_STRING: &str = "adls.connection-string";
33/// The account that you want to connect to.
34pub const ADLS_ACCOUNT_NAME: &str = "adls.account-name";
35/// The key to authentication against the account.
36pub const ADLS_ACCOUNT_KEY: &str = "adls.account-key";
37/// The shared access signature.
38pub const ADLS_SAS_TOKEN: &str = "adls.sas-token";
39/// The tenant-id.
40pub const ADLS_TENANT_ID: &str = "adls.tenant-id";
41/// The client-id.
42pub const ADLS_CLIENT_ID: &str = "adls.client-id";
43/// The client-secret.
44pub const ADLS_CLIENT_SECRET: &str = "adls.client-secret";
45/// The authority host of the service principal.
46/// - required for client_credentials authentication
47/// - default value: `https://login.microsoftonline.com`
48pub const ADLS_AUTHORITY_HOST: &str = "adls.authority-host";
49
50/// Azure Data Lake Storage configuration.
51///
52/// This struct contains all the configuration options for connecting to Azure Data Lake Storage.
53/// Use the builder pattern via `AzdlsConfig::builder()` to construct instances.
54#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, TypedBuilder)]
55pub struct AzdlsConfig {
56    /// Connection string.
57    #[builder(default, setter(strip_option, into))]
58    pub connection_string: Option<String>,
59    /// Account name.
60    #[builder(default, setter(strip_option, into))]
61    pub account_name: Option<String>,
62    /// Account key.
63    #[builder(default, setter(strip_option, into))]
64    pub account_key: Option<String>,
65    /// SAS token.
66    #[builder(default, setter(strip_option, into))]
67    pub sas_token: Option<String>,
68    /// Tenant ID.
69    #[builder(default, setter(strip_option, into))]
70    pub tenant_id: Option<String>,
71    /// Client ID.
72    #[builder(default, setter(strip_option, into))]
73    pub client_id: Option<String>,
74    /// Client secret.
75    #[builder(default, setter(strip_option, into))]
76    pub client_secret: Option<String>,
77    /// Authority host.
78    #[builder(default, setter(strip_option, into))]
79    pub authority_host: Option<String>,
80    /// Endpoint URL.
81    #[builder(default, setter(strip_option, into))]
82    pub endpoint: Option<String>,
83    /// Filesystem name.
84    #[builder(default, setter(into))]
85    pub filesystem: String,
86}
87
88impl TryFrom<&StorageConfig> for AzdlsConfig {
89    type Error = crate::Error;
90
91    fn try_from(config: &StorageConfig) -> Result<Self> {
92        let props = config.props();
93
94        let mut cfg = AzdlsConfig::default();
95
96        if let Some(connection_string) = props.get(ADLS_CONNECTION_STRING) {
97            cfg.connection_string = Some(connection_string.clone());
98        }
99        if let Some(account_name) = props.get(ADLS_ACCOUNT_NAME) {
100            cfg.account_name = Some(account_name.clone());
101        }
102        if let Some(account_key) = props.get(ADLS_ACCOUNT_KEY) {
103            cfg.account_key = Some(account_key.clone());
104        }
105        if let Some(sas_token) = props.get(ADLS_SAS_TOKEN) {
106            cfg.sas_token = Some(sas_token.clone());
107        }
108        if let Some(tenant_id) = props.get(ADLS_TENANT_ID) {
109            cfg.tenant_id = Some(tenant_id.clone());
110        }
111        if let Some(client_id) = props.get(ADLS_CLIENT_ID) {
112            cfg.client_id = Some(client_id.clone());
113        }
114        if let Some(client_secret) = props.get(ADLS_CLIENT_SECRET) {
115            cfg.client_secret = Some(client_secret.clone());
116        }
117        if let Some(authority_host) = props.get(ADLS_AUTHORITY_HOST) {
118            cfg.authority_host = Some(authority_host.clone());
119        }
120
121        Ok(cfg)
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128
129    #[test]
130    fn test_azdls_config_builder() {
131        let config = AzdlsConfig::builder()
132            .account_name("myaccount")
133            .account_key("my-account-key")
134            .build();
135
136        assert_eq!(config.account_name.as_deref(), Some("myaccount"));
137        assert_eq!(config.account_key.as_deref(), Some("my-account-key"));
138    }
139
140    #[test]
141    fn test_azdls_config_from_storage_config() {
142        let storage_config = StorageConfig::new()
143            .with_prop(ADLS_ACCOUNT_NAME, "myaccount")
144            .with_prop(ADLS_ACCOUNT_KEY, "my-account-key");
145
146        let azdls_config = AzdlsConfig::try_from(&storage_config).unwrap();
147
148        assert_eq!(azdls_config.account_name.as_deref(), Some("myaccount"));
149        assert_eq!(azdls_config.account_key.as_deref(), Some("my-account-key"));
150    }
151
152    #[test]
153    fn test_azdls_config_with_sas_token() {
154        let storage_config = StorageConfig::new()
155            .with_prop(ADLS_ACCOUNT_NAME, "myaccount")
156            .with_prop(ADLS_SAS_TOKEN, "my-sas-token");
157
158        let azdls_config = AzdlsConfig::try_from(&storage_config).unwrap();
159
160        assert_eq!(azdls_config.account_name.as_deref(), Some("myaccount"));
161        assert_eq!(azdls_config.sas_token.as_deref(), Some("my-sas-token"));
162    }
163
164    #[test]
165    fn test_azdls_config_with_client_credentials() {
166        let storage_config = StorageConfig::new()
167            .with_prop(ADLS_ACCOUNT_NAME, "myaccount")
168            .with_prop(ADLS_TENANT_ID, "my-tenant")
169            .with_prop(ADLS_CLIENT_ID, "my-client")
170            .with_prop(ADLS_CLIENT_SECRET, "my-secret");
171
172        let azdls_config = AzdlsConfig::try_from(&storage_config).unwrap();
173
174        assert_eq!(azdls_config.account_name.as_deref(), Some("myaccount"));
175        assert_eq!(azdls_config.tenant_id.as_deref(), Some("my-tenant"));
176        assert_eq!(azdls_config.client_id.as_deref(), Some("my-client"));
177        assert_eq!(azdls_config.client_secret.as_deref(), Some("my-secret"));
178    }
179}