atomr_persistence_azure/
config.rs1use std::env;
4
5use atomr_persistence::JournalError;
6
7pub const AZURITE_ACCOUNT: &str = "devstoreaccount1";
9pub const AZURITE_KEY: &str =
10 "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
11pub const AZURITE_ENDPOINT: &str = "http://127.0.0.1:10002/devstoreaccount1";
12
13#[derive(Debug, Clone)]
14pub struct AzureConfig {
15 pub account: String,
16 pub key: String,
17 pub endpoint: String,
18 pub journal_table: String,
19 pub snapshot_table: String,
20 pub auto_create_tables: bool,
21}
22
23impl AzureConfig {
24 pub fn new(account: impl Into<String>, key: impl Into<String>, endpoint: impl Into<String>) -> Self {
25 Self {
26 account: account.into(),
27 key: key.into(),
28 endpoint: endpoint.into(),
29 journal_table: "EventJournal".into(),
30 snapshot_table: "SnapshotStore".into(),
31 auto_create_tables: true,
32 }
33 }
34
35 pub fn azurite() -> Self {
37 Self::new(AZURITE_ACCOUNT, AZURITE_KEY, AZURITE_ENDPOINT)
38 }
39
40 pub fn from_connection_string(cs: &str) -> Result<Self, JournalError> {
43 let mut account = None;
44 let mut key = None;
45 let mut endpoint = None;
46 for part in cs.split(';').filter(|p| !p.is_empty()) {
47 let (k, v) =
48 part.split_once('=').ok_or_else(|| JournalError::backend("malformed connection string"))?;
49 match k.trim() {
50 "AccountName" => account = Some(v.to_string()),
51 "AccountKey" => key = Some(v.to_string()),
52 "TableEndpoint" => endpoint = Some(v.to_string()),
53 _ => {}
54 }
55 }
56 let account = account.ok_or_else(|| JournalError::backend("missing AccountName"))?;
57 let key = key.ok_or_else(|| JournalError::backend("missing AccountKey"))?;
58 let endpoint = endpoint.unwrap_or_else(|| format!("https://{account}.table.core.windows.net"));
59 Ok(Self::new(account, key, endpoint))
60 }
61
62 pub fn from_env() -> Self {
63 if let Ok(cs) = env::var("ATOMR_PERSISTENCE_AZURE_CONNECTION_STRING") {
64 if let Ok(cfg) = Self::from_connection_string(&cs) {
65 return cfg;
66 }
67 }
68 if let Ok(cs) = env::var("ATOMR_IT_AZURE_CONNECTION_STRING") {
69 if let Ok(cfg) = Self::from_connection_string(&cs) {
70 return cfg;
71 }
72 }
73 Self::azurite()
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn parses_connection_string() {
83 let cs = "AccountName=acc;AccountKey=key;TableEndpoint=https://acc.table.core.windows.net";
84 let cfg = AzureConfig::from_connection_string(cs).unwrap();
85 assert_eq!(cfg.account, "acc");
86 assert_eq!(cfg.key, "key");
87 assert_eq!(cfg.endpoint, "https://acc.table.core.windows.net");
88 }
89
90 #[test]
91 fn rejects_bad_connection_string() {
92 assert!(AzureConfig::from_connection_string("no-equals-here").is_err());
93 }
94
95 #[test]
96 fn azurite_defaults() {
97 let cfg = AzureConfig::azurite();
98 assert_eq!(cfg.account, AZURITE_ACCOUNT);
99 assert!(cfg.endpoint.starts_with("http://"));
100 }
101}