Skip to main content

template_model/
regions.rs

1pub const DEFAULT_REGION: &str = "us-east-1";
2pub const DEFAULT_PARTITION: &str = "aws";
3pub const DEFAULT_URL_SUFFIX: &str = "amazonaws.com";
4
5const CN_REGIONS: &[&str] = &["cn-north-1", "cn-northwest-1"];
6const GOV_REGIONS: &[&str] = &["us-gov-east-1", "us-gov-west-1"];
7
8pub const AVAILABILITY_ZONES: &[(&str, &[&str])] = &[
9    ("af-south-1", &["af-south-1a", "af-south-1b", "af-south-1c"]),
10    ("ap-east-1", &["ap-east-1a", "ap-east-1b", "ap-east-1c"]),
11    ("ap-east-2", &["ap-east-2a", "ap-east-2b", "ap-east-2c"]),
12    ("ap-northeast-1", &["ap-northeast-1a", "ap-northeast-1b", "ap-northeast-1c", "ap-northeast-1d"]),
13    ("ap-northeast-2", &["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c", "ap-northeast-2d"]),
14    ("ap-northeast-3", &["ap-northeast-3a", "ap-northeast-3b", "ap-northeast-3c"]),
15    ("ap-south-1", &["ap-south-1a", "ap-south-1b", "ap-south-1c"]),
16    ("ap-south-2", &["ap-south-2a", "ap-south-2b", "ap-south-2c"]),
17    ("ap-southeast-1", &["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]),
18    ("ap-southeast-2", &["ap-southeast-2a", "ap-southeast-2b", "ap-southeast-2c"]),
19    ("ap-southeast-3", &["ap-southeast-3a", "ap-southeast-3b", "ap-southeast-3c"]),
20    ("ap-southeast-4", &["ap-southeast-4a", "ap-southeast-4b", "ap-southeast-4c"]),
21    ("ap-southeast-5", &["ap-southeast-5a", "ap-southeast-5b", "ap-southeast-5c"]),
22    ("ap-southeast-6", &["ap-southeast-6a", "ap-southeast-6b", "ap-southeast-6c"]),
23    ("ap-southeast-7", &["ap-southeast-7a", "ap-southeast-7b", "ap-southeast-7c"]),
24    ("ca-central-1", &["ca-central-1a", "ca-central-1b", "ca-central-1c", "ca-central-1d"]),
25    ("ca-west-1", &["ca-west-1a", "ca-west-1b", "ca-west-1c"]),
26    ("cn-north-1", &["cn-north-1a", "cn-north-1b", "cn-north-1c"]),
27    ("cn-northwest-1", &["cn-northwest-1a", "cn-northwest-1b", "cn-northwest-1c"]),
28    ("eu-central-1", &["eu-central-1a", "eu-central-1b", "eu-central-1c"]),
29    ("eu-central-2", &["eu-central-2a", "eu-central-2b", "eu-central-2c"]),
30    ("eu-isoe-west-1", &["eu-isoe-west-1a", "eu-isoe-west-1b", "eu-isoe-west-1c"]),
31    ("eu-north-1", &["eu-north-1a", "eu-north-1b", "eu-north-1c"]),
32    ("eu-south-1", &["eu-south-1a", "eu-south-1b", "eu-south-1c"]),
33    ("eu-south-2", &["eu-south-2a", "eu-south-2b", "eu-south-2c"]),
34    ("eu-west-1", &["eu-west-1a", "eu-west-1b", "eu-west-1c"]),
35    ("eu-west-2", &["eu-west-2a", "eu-west-2b", "eu-west-2c"]),
36    ("eu-west-3", &["eu-west-3a", "eu-west-3b", "eu-west-3c"]),
37    ("eusc-de-east-1", &["eusc-de-east-1a", "eusc-de-east-1b", "eusc-de-east-1c"]),
38    ("il-central-1", &["il-central-1a", "il-central-1b", "il-central-1c"]),
39    ("me-central-1", &["me-central-1a", "me-central-1b", "me-central-1c"]),
40    ("me-south-1", &["me-south-1a", "me-south-1b", "me-south-1c"]),
41    ("mx-central-1", &["mx-central-1a", "mx-central-1b", "mx-central-1c"]),
42    ("sa-east-1", &["sa-east-1a", "sa-east-1b", "sa-east-1c"]),
43    ("us-east-1", &["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e", "us-east-1f"]),
44    ("us-east-2", &["us-east-2a", "us-east-2b", "us-east-2c"]),
45    ("us-gov-east-1", &["us-gov-east-1a", "us-gov-east-1b", "us-gov-east-1c"]),
46    ("us-gov-west-1", &["us-gov-west-1a", "us-gov-west-1b", "us-gov-west-1c"]),
47    ("us-iso-east-1", &["us-iso-east-1a", "us-iso-east-1b", "us-iso-east-1c"]),
48    ("us-iso-west-1", &["us-iso-west-1a", "us-iso-west-1b", "us-iso-west-1c"]),
49    ("us-isob-east-1", &["us-isob-east-1a", "us-isob-east-1b", "us-isob-east-1c"]),
50    ("us-isof-east-1", &["us-isof-east-1a", "us-isof-east-1b", "us-isof-east-1c"]),
51    ("us-isof-south-1", &["us-isof-south-1a", "us-isof-south-1b", "us-isof-south-1c"]),
52    ("us-west-1", &["us-west-1a", "us-west-1c"]),
53    ("us-west-2", &["us-west-2a", "us-west-2b", "us-west-2c", "us-west-2d"]),
54];
55
56const AWS_REGION_NAMES: [&str; AVAILABILITY_ZONES.len()] = {
57    let mut names = [""; AVAILABILITY_ZONES.len()];
58    let mut i = 0;
59    while i < AVAILABILITY_ZONES.len() {
60        names[i] = AVAILABILITY_ZONES[i].0;
61        i += 1;
62    }
63    names
64};
65
66pub const AWS_REGIONS: &[&str] = &AWS_REGION_NAMES;
67
68pub fn is_known_region(region: &str) -> bool {
69    AWS_REGIONS.contains(&region)
70}
71
72pub fn availability_zones_for_region(region: &str) -> Option<&'static [&'static str]> {
73    AVAILABILITY_ZONES.iter().find(|(name, _)| *name == region).map(|(_, zones)| *zones)
74}
75
76pub fn partition_for_region(region: &str) -> &'static str {
77    if CN_REGIONS.contains(&region) {
78        "aws-cn"
79    } else if GOV_REGIONS.contains(&region) {
80        "aws-us-gov"
81    } else {
82        DEFAULT_PARTITION
83    }
84}
85
86pub fn url_suffix_for_region(region: &str) -> &'static str {
87    if CN_REGIONS.contains(&region) { "amazonaws.com.cn" } else { DEFAULT_URL_SUFFIX }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn partition_for_standard_regions() {
96        assert_eq!(partition_for_region("us-east-1"), "aws");
97        assert_eq!(partition_for_region("eu-west-1"), "aws");
98        assert_eq!(partition_for_region("ap-southeast-1"), "aws");
99    }
100
101    #[test]
102    fn partition_for_china_regions() {
103        assert_eq!(partition_for_region("cn-north-1"), "aws-cn");
104        assert_eq!(partition_for_region("cn-northwest-1"), "aws-cn");
105    }
106
107    #[test]
108    fn partition_for_govcloud_regions() {
109        assert_eq!(partition_for_region("us-gov-east-1"), "aws-us-gov");
110        assert_eq!(partition_for_region("us-gov-west-1"), "aws-us-gov");
111    }
112
113    #[test]
114    fn url_suffix_for_standard_regions() {
115        assert_eq!(url_suffix_for_region("us-east-1"), "amazonaws.com");
116        assert_eq!(url_suffix_for_region("eu-west-1"), "amazonaws.com");
117        assert_eq!(url_suffix_for_region("us-gov-west-1"), "amazonaws.com");
118    }
119
120    #[test]
121    fn url_suffix_for_china_regions() {
122        assert_eq!(url_suffix_for_region("cn-north-1"), "amazonaws.com.cn");
123        assert_eq!(url_suffix_for_region("cn-northwest-1"), "amazonaws.com.cn");
124    }
125
126    #[test]
127    fn aws_regions_derives_from_availability_zones() {
128        assert_eq!(AWS_REGIONS.len(), AVAILABILITY_ZONES.len());
129        for ((region, _), name) in AVAILABILITY_ZONES.iter().zip(AWS_REGIONS.iter()) {
130            assert_eq!(region, name, "AWS_REGIONS must mirror AVAILABILITY_ZONES region names in order");
131        }
132    }
133
134    #[test]
135    fn availability_zones_table_is_sorted_and_unique() {
136        for pair in AVAILABILITY_ZONES.windows(2) {
137            assert!(
138                pair[0].0 < pair[1].0,
139                "AVAILABILITY_ZONES must be sorted by region: {} !< {}",
140                pair[0].0,
141                pair[1].0
142            );
143        }
144    }
145
146    #[test]
147    fn availability_zones_lookup_matches_region() {
148        assert_eq!(
149            availability_zones_for_region("us-east-1"),
150            Some(["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e", "us-east-1f"].as_slice())
151        );
152        assert_eq!(availability_zones_for_region("us-west-1"), Some(["us-west-1a", "us-west-1c"].as_slice()));
153        assert_eq!(availability_zones_for_region("mars-north-1"), None);
154    }
155
156    #[test]
157    fn is_known_region_covers_gov_cn_and_rejects_unknown() {
158        assert!(is_known_region("us-east-1"));
159        assert!(is_known_region("us-gov-west-1"));
160        assert!(is_known_region("cn-north-1"));
161        assert!(is_known_region("ap-east-2"));
162        assert!(!is_known_region("mars-north-1"));
163    }
164}