statehub_api/v0/state/
impls.rs1use std::cmp;
7use std::iter;
8
9use super::*;
10
11impl fmt::Display for State {
12 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13 if f.alternate() {
14 f.debug_struct("State")
15 .field("name", &self.name.0)
16 .field("aws", &self.locations.aws)
17 .field("azure", &self.locations.azure)
18 .finish()
19 } else {
20 self.name.fmt(f)
21 }
22 }
23}
24
25impl From<String> for StateName {
26 fn from(name: String) -> Self {
27 Self(name)
28 }
29}
30
31impl From<&str> for StateName {
32 fn from(text: &str) -> Self {
33 text.to_string().into()
34 }
35}
36
37impl fmt::Display for StateName {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 self.0.fmt(f)
40 }
41}
42
43impl str::FromStr for StateName {
44 type Err = Infallible;
45
46 fn from_str(text: &str) -> Result<Self, Self::Err> {
47 Ok(text.into())
48 }
49}
50
51impl AsRef<str> for StateName {
52 fn as_ref(&self) -> &str {
53 self.0.as_ref()
54 }
55}
56
57impl ops::Deref for StateName {
58 type Target = str;
59
60 fn deref(&self) -> &Self::Target {
61 self.0.deref()
62 }
63}
64
65impl PartialEq<&str> for StateName {
66 fn eq(&self, other: &&str) -> bool {
67 self.0.eq(other)
68 }
69}
70
71impl State {
72 pub fn is_available_in(&self, location: &Location) -> bool {
73 self.locations.contains(location)
74 }
75
76 pub fn is_ready(&self) -> bool {
77 self.condition == Condition::Green
78 }
79
80 pub fn all_locations(&self) -> Vec<Location> {
81 let aws = self.locations.aws.iter().map(|aws| aws.region.into());
82 let azure = self.locations.azure.iter().map(|azure| azure.region.into());
83 aws.chain(azure).collect()
84 }
85
86 pub fn collect_volumes(&self) -> HashMap<String, HashMap<Location, &VolumeLocation>> {
87 let aws = self.locations.aws.iter().flat_map(|location| {
88 location
89 .volumes
90 .iter()
91 .map(move |volume| (volume, location.region.into()))
92 });
93 let azure = self.locations.azure.iter().flat_map(|location| {
94 location
95 .volumes
96 .iter()
97 .map(move |volume| (volume, location.region.into()))
98 });
99
100 let mut volumes = HashMap::<_, HashMap<_, _>>::new();
101 for (volume, location) in aws.chain(azure) {
102 volumes
103 .entry(volume.name.clone())
104 .or_default()
105 .insert(location, volume);
106 }
107 volumes
108 }
109
110 pub fn count_volumes(&self) -> usize {
111 let aws = self
112 .locations
113 .aws
114 .iter()
115 .map(|aws| aws.volumes.len())
116 .max()
117 .unwrap_or_default();
118 let azure = self
119 .locations
120 .azure
121 .iter()
122 .map(|azure| azure.volumes.len())
123 .max()
124 .unwrap_or_default();
125 cmp::max(aws, azure)
126 }
127}
128
129impl StateLocationStatus {
130 pub fn as_str(&self) -> &'static str {
131 match self {
132 Self::Ok => "ok",
133 Self::Provisioning => "provisioning",
134 Self::Recovering => "recovering",
135 Self::Deleting => "deleting",
136 Self::Error => "error",
137 }
138 }
139
140 pub fn is_deleting(&self) -> bool {
141 *self == Self::Deleting
142 }
143
144 pub fn is_final(&self) -> bool {
145 match self {
146 Self::Ok => true,
147 Self::Provisioning => false,
148 Self::Recovering => false,
149 Self::Deleting => false,
150 Self::Error => true,
151 }
152 }
153}
154
155impl Default for VolumeBindingMode {
156 fn default() -> Self {
157 Self::WaitForFirstConsumer
158 }
159}
160
161impl From<AwsRegion> for CreateStateLocationAwsDto {
162 fn from(region: AwsRegion) -> Self {
163 Self { region }
164 }
165}
166
167impl From<AzureRegion> for CreateStateLocationAzureDto {
168 fn from(region: AzureRegion) -> Self {
169 Self { region }
170 }
171}
172
173impl iter::FromIterator<Location> for CreateStateLocationsDto {
174 fn from_iter<T>(iter: T) -> Self
175 where
176 T: IntoIterator<Item = Location>,
177 {
178 iter.into_iter().fold(Self::default(), |mut dto, location| {
179 match location {
180 Location::Aws(region) => dto.aws.push(region.into()),
181 Location::Azure(region) => dto.azure.push(region.into()),
182 }
184 dto
185 })
186 }
187}
188
189impl StateLocations {
190 pub fn contains(&self, location: &Location) -> bool {
191 match location {
192 Location::Aws(region) => self.aws.iter().any(|aws| aws.region == *region),
193 Location::Azure(region) => self.azure.iter().any(|azure| azure.region == *region),
194 }
195 }
196}
197
198impl Default for Condition {
199 fn default() -> Self {
200 Self::Green
201 }
202}
203
204impl Default for ProvisioningStatus {
205 fn default() -> Self {
206 Self::Ready
207 }
208}
209
210impl StorageClass {
211 pub fn new_if_not_default(
212 state: &str,
213 storage_class: Option<String>,
214 fs_type: Option<VolumeFileSystem>,
215 ) -> Option<Self> {
216 if storage_class.is_none() && fs_type.is_none() {
217 return None;
218 }
219
220 let name = storage_class.unwrap_or_else(|| state.to_string());
221 let fs_type = fs_type.unwrap_or_default().to_string();
222
223 let storage_class = Self {
224 name,
225 fs_type,
226 ..Self::default()
227 };
228
229 Some(storage_class)
230 }
231}