1#![allow(clippy::module_name_repetitions)]
3
4use std::convert::TryFrom;
5
6pub trait Status: std::fmt::Debug + std::fmt::Display + private::Sealed {
8 fn is_settled(&self) -> bool;
12
13 fn sentiment(&self) -> StatusSentiment;
21}
22
23#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum StatusSentiment {
26 Positive,
27 Neutral,
28 Negative,
29}
30
31impl StatusSentiment {
32 #[must_use]
34 pub fn is_positive(self) -> bool {
35 self == Self::Positive
36 }
37
38 #[must_use]
40 pub fn is_neutral(self) -> bool {
41 self == Self::Neutral
42 }
43
44 #[must_use]
46 pub fn is_negative(self) -> bool {
47 self == Self::Negative
48 }
49}
50
51#[derive(Clone, Copy, Debug, Eq, PartialEq, parse_display::Display, parse_display::FromStr)]
53#[display(style = "SNAKE_CASE")]
54pub enum ChangeSetStatus {
55 CreatePending,
56 CreateInProgress,
57 CreateComplete,
58 DeletePending,
59 DeleteInProgress,
60 DeleteComplete,
61 DeleteFailed,
62 Failed,
63}
64
65impl Status for ChangeSetStatus {
66 fn is_settled(&self) -> bool {
67 match self {
68 Self::CreatePending
69 | Self::CreateInProgress
70 | Self::DeletePending
71 | Self::DeleteInProgress => false,
72 Self::CreateComplete | Self::DeleteComplete | Self::DeleteFailed | Self::Failed => true,
73 }
74 }
75
76 fn sentiment(&self) -> StatusSentiment {
77 match self {
78 Self::CreateComplete | Self::DeleteComplete => StatusSentiment::Positive,
79 Self::CreatePending
80 | Self::CreateInProgress
81 | Self::DeletePending
82 | Self::DeleteInProgress => StatusSentiment::Neutral,
83 Self::DeleteFailed | Self::Failed => StatusSentiment::Negative,
84 }
85 }
86}
87
88#[derive(Clone, Copy, Debug, Eq, PartialEq, parse_display::Display, parse_display::FromStr)]
90#[display(style = "SNAKE_CASE")]
91pub enum StackStatus {
92 CreateInProgress,
93 CreateFailed,
94 CreateComplete,
95 RollbackInProgress,
96 RollbackFailed,
97 RollbackComplete,
98 DeleteInProgress,
99 DeleteFailed,
100 DeleteComplete,
101 UpdateInProgress,
102 UpdateCompleteCleanupInProgress,
103 UpdateComplete,
104 UpdateFailed,
105 UpdateRollbackInProgress,
106 UpdateRollbackFailed,
107 UpdateRollbackCompleteCleanupInProgress,
108 UpdateRollbackComplete,
109 ReviewInProgress,
110 ImportInProgress,
111 ImportComplete,
112 ImportRollbackInProgress,
113 ImportRollbackFailed,
114 ImportRollbackComplete,
115}
116
117impl Status for StackStatus {
118 fn is_settled(&self) -> bool {
119 match self {
120 Self::CreateInProgress
121 | Self::RollbackInProgress
122 | Self::DeleteInProgress
123 | Self::UpdateInProgress
124 | Self::UpdateCompleteCleanupInProgress
125 | Self::UpdateRollbackInProgress
126 | Self::UpdateRollbackCompleteCleanupInProgress
127 | Self::ReviewInProgress
128 | Self::ImportInProgress
129 | Self::ImportRollbackInProgress => false,
130 Self::CreateFailed
131 | Self::CreateComplete
132 | Self::RollbackFailed
133 | Self::RollbackComplete
134 | Self::DeleteFailed
135 | Self::DeleteComplete
136 | Self::UpdateComplete
137 | Self::UpdateFailed
138 | Self::UpdateRollbackFailed
139 | Self::UpdateRollbackComplete
140 | Self::ImportComplete
141 | Self::ImportRollbackFailed
142 | Self::ImportRollbackComplete => true,
143 }
144 }
145
146 fn sentiment(&self) -> StatusSentiment {
147 match self {
148 Self::CreateComplete
149 | Self::DeleteComplete
150 | Self::UpdateComplete
151 | Self::ImportComplete => StatusSentiment::Positive,
152 Self::CreateInProgress
153 | Self::DeleteInProgress
154 | Self::UpdateInProgress
155 | Self::UpdateCompleteCleanupInProgress
156 | Self::ReviewInProgress
157 | Self::ImportInProgress => StatusSentiment::Neutral,
158 Self::CreateFailed
159 | Self::RollbackInProgress
160 | Self::RollbackFailed
161 | Self::RollbackComplete
162 | Self::DeleteFailed
163 | Self::UpdateFailed
164 | Self::UpdateRollbackInProgress
165 | Self::UpdateRollbackFailed
166 | Self::UpdateRollbackCompleteCleanupInProgress
167 | Self::UpdateRollbackComplete
168 | Self::ImportRollbackInProgress
169 | Self::ImportRollbackFailed
170 | Self::ImportRollbackComplete => StatusSentiment::Negative,
171 }
172 }
173}
174
175#[derive(Clone, Copy, Debug, Eq, PartialEq, parse_display::Display, parse_display::FromStr)]
180#[display(style = "SNAKE_CASE")]
181pub enum BlockedStackStatus {
182 CreateFailed,
183 RollbackComplete,
184 RollbackFailed,
185 DeleteFailed,
186 UpdateFailed,
187 UpdateRollbackFailed,
188}
189
190impl TryFrom<StackStatus> for BlockedStackStatus {
191 type Error = StackStatus;
192
193 fn try_from(status: StackStatus) -> Result<Self, Self::Error> {
194 match status {
195 StackStatus::CreateFailed => Ok(Self::CreateFailed),
196 StackStatus::RollbackComplete => Ok(Self::RollbackComplete),
197 StackStatus::RollbackFailed => Ok(Self::RollbackFailed),
198 StackStatus::DeleteFailed => Ok(Self::DeleteFailed),
199 StackStatus::UpdateFailed => Ok(Self::UpdateFailed),
200 StackStatus::UpdateRollbackFailed => Ok(Self::UpdateRollbackFailed),
201 StackStatus::CreateInProgress
202 | StackStatus::CreateComplete
203 | StackStatus::DeleteComplete
204 | StackStatus::DeleteInProgress
205 | StackStatus::ReviewInProgress
206 | StackStatus::RollbackInProgress
207 | StackStatus::UpdateInProgress
208 | StackStatus::UpdateCompleteCleanupInProgress
209 | StackStatus::UpdateComplete
210 | StackStatus::UpdateRollbackInProgress
211 | StackStatus::UpdateRollbackCompleteCleanupInProgress
212 | StackStatus::UpdateRollbackComplete
213 | StackStatus::ImportInProgress
214 | StackStatus::ImportComplete
215 | StackStatus::ImportRollbackInProgress
216 | StackStatus::ImportRollbackFailed
217 | StackStatus::ImportRollbackComplete => Err(status),
218 }
219 }
220}
221
222#[derive(Clone, Copy, Debug, Eq, PartialEq, parse_display::Display, parse_display::FromStr)]
224#[display(style = "SNAKE_CASE")]
225pub enum ResourceStatus {
226 CreateInProgress,
227 CreateFailed,
228 CreateComplete,
229 DeleteInProgress,
230 DeleteFailed,
231 DeleteComplete,
232 DeleteSkipped,
233 UpdateInProgress,
234 UpdateFailed,
235 UpdateComplete,
236 ImportFailed,
237 ImportComplete,
238 ImportInProgress,
239 ImportRollbackInProgress,
240 ImportRollbackFailed,
241 ImportRollbackComplete,
242}
243
244impl Status for ResourceStatus {
245 fn is_settled(&self) -> bool {
246 match self {
247 Self::CreateInProgress
248 | Self::DeleteInProgress
249 | Self::UpdateInProgress
250 | Self::ImportInProgress
251 | Self::ImportRollbackInProgress => false,
252 Self::CreateFailed
253 | Self::CreateComplete
254 | Self::DeleteFailed
255 | Self::DeleteComplete
256 | Self::DeleteSkipped
257 | Self::UpdateFailed
258 | Self::UpdateComplete
259 | Self::ImportFailed
260 | Self::ImportComplete
261 | Self::ImportRollbackFailed
262 | Self::ImportRollbackComplete => true,
263 }
264 }
265
266 fn sentiment(&self) -> StatusSentiment {
267 match self {
268 Self::CreateComplete
269 | Self::DeleteComplete
270 | Self::UpdateComplete
271 | Self::ImportComplete => StatusSentiment::Positive,
272 Self::CreateInProgress
273 | Self::DeleteInProgress
274 | Self::DeleteSkipped
275 | Self::UpdateInProgress
276 | Self::ImportInProgress => StatusSentiment::Neutral,
277 Self::CreateFailed
278 | Self::DeleteFailed
279 | Self::UpdateFailed
280 | Self::ImportFailed
281 | Self::ImportRollbackInProgress
282 | Self::ImportRollbackFailed
283 | Self::ImportRollbackComplete => StatusSentiment::Negative,
284 }
285 }
286}
287
288mod private {
289 pub trait Sealed {}
291
292 impl Sealed for super::ChangeSetStatus {}
293 impl Sealed for super::StackStatus {}
294 impl Sealed for super::ResourceStatus {}
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300
301 #[test]
302 fn stack_status() {
303 assert_eq!(
305 format!("{}", StackStatus::UpdateRollbackCompleteCleanupInProgress).as_str(),
306 "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS"
307 );
308 assert_eq!(
309 "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS".parse(),
310 Ok(StackStatus::UpdateRollbackCompleteCleanupInProgress)
311 );
312 assert!("oh no".parse::<StackStatus>().is_err());
313 }
314
315 #[test]
316 fn resource_status() {
317 assert_eq!(
319 format!("{}", ResourceStatus::ImportRollbackInProgress).as_str(),
320 "IMPORT_ROLLBACK_IN_PROGRESS"
321 );
322 assert_eq!(
323 "IMPORT_ROLLBACK_IN_PROGRESS".parse(),
324 Ok(ResourceStatus::ImportRollbackInProgress)
325 );
326 assert!("oh no".parse::<ResourceStatus>().is_err());
327 }
328}