1use crate::{Region, RegionError};
2use regex::Regex;
3use std::sync::LazyLock;
4use url::Url;
5
6static REGION_HOST_REGEX: LazyLock<Regex> = LazyLock::new(|| {
8 Regex::new(r"^(?:https://){0,1}([^\.]+)\.([^\.]+)\.viturhosted\.net/?$").expect("Invalid regex")
9});
10
11static DOMAIN_NAME: &str = "viturhosted.net";
13
14pub trait ServiceDiscovery {
16 fn name(&self) -> &'static str;
17 fn fqdn(region: Region) -> String;
18 fn endpoint(region: Region) -> Result<Url, RegionError>;
19}
20
21pub struct ZeroKmsServiceDiscovery;
23
24impl ServiceDiscovery for ZeroKmsServiceDiscovery {
25 fn name(&self) -> &'static str {
26 "zerokms"
27 }
28
29 fn fqdn(region: Region) -> String {
32 format!("{}.viturhosted.net", region.identifier())
33 }
34
35 fn endpoint(region: Region) -> Result<Url, RegionError> {
38 Url::parse(&format!("https://{}.{DOMAIN_NAME}/", region.identifier())).map_err(|e| {
39 RegionError::InvalidRegion(format!(
40 "Invalid service URL for ZeroKMS in region {}: {}",
41 region.identifier(),
42 e
43 ))
44 })
45 }
46}
47
48impl ZeroKmsServiceDiscovery {
49 pub fn region_from_host_fqdn(host_fqdn: &str) -> Result<Region, RegionError> {
53 REGION_HOST_REGEX
54 .captures(host_fqdn)
55 .ok_or_else(|| RegionError::InvalidHostFqdn(host_fqdn.to_string()))
56 .and_then(|caps| {
57 let region = caps.get(1).unwrap().as_str().to_string();
58 let provider = caps.get(2).unwrap().as_str().to_string();
59 Region::new(&format!("{}.{}", region, provider))
60 })
61 }
62}
63
64pub struct CtsServiceDiscovery;
66
67impl ServiceDiscovery for CtsServiceDiscovery {
68 fn name(&self) -> &'static str {
69 "cts"
70 }
71
72 fn fqdn(region: Region) -> String {
73 format!("{}.auth.{DOMAIN_NAME}", region.identifier())
74 }
75
76 fn endpoint(region: Region) -> Result<Url, RegionError> {
77 if matches!(region, Region::Aws(crate::AwsRegion::ApSoutheast2)) {
78 return Url::parse(&format!(
79 "https://{}.auth.{DOMAIN_NAME}/",
80 region.identifier()
81 ))
82 .map_err(|e| {
83 RegionError::InvalidRegion(format!(
84 "Invalid service URL for ZeroKMS in region {}: {}",
85 region.identifier(),
86 e
87 ))
88 });
89 }
90 Err(RegionError::InvalidRegion(format!(
91 "Region {} is not supported by the CTS service",
92 region.identifier()
93 )))
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_region_from_host_fqdn() -> anyhow::Result<()> {
103 let host_fqdn = "us-west-1.aws.viturhosted.net";
104 let region = ZeroKmsServiceDiscovery::region_from_host_fqdn(host_fqdn)?;
105 assert_eq!(region.identifier(), "us-west-1.aws");
106
107 Ok(())
108 }
109
110 #[test]
111 fn test_region_from_host_endpoint() -> anyhow::Result<()> {
112 let host_fqdn = "https://us-west-1.aws.viturhosted.net";
113 let region = ZeroKmsServiceDiscovery::region_from_host_fqdn(host_fqdn)?;
114 assert_eq!(region.identifier(), "us-west-1.aws");
115 Ok(())
116 }
117
118 #[test]
119 fn test_region_from_host_endpoint_with_trailing_slash() -> anyhow::Result<()> {
120 let host_fqdn = "https://us-west-1.aws.viturhosted.net/";
121 let region = ZeroKmsServiceDiscovery::region_from_host_fqdn(host_fqdn)?;
122 assert_eq!(region.identifier(), "us-west-1.aws");
123 Ok(())
124 }
125}