1use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
10#[serde(rename_all = "lowercase")]
11pub enum LifecycleType {
12 #[default]
14 Delete,
15 Compress,
17}
18
19#[repr(u8)]
21#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
22#[serde(rename_all = "lowercase")]
23pub enum LifecycleMode {
24 Enabled,
26 Disabled,
28 #[serde(rename = "dry_run")]
30 DryRun,
31}
32
33impl Default for LifecycleMode {
34 fn default() -> Self {
35 Self::Enabled
36 }
37}
38
39#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
41pub struct LifecycleSettings {
42 #[serde(rename = "type")]
44 pub lifecycle_type: LifecycleType,
45 pub bucket: String,
47 #[serde(default)]
50 pub entries: Vec<String>,
51 pub older_than: String,
53 #[serde(default = "default_lifecycle_interval")]
55 pub interval: String,
56 #[serde(default)]
58 pub when: Option<Value>,
59 #[serde(default)]
61 pub mode: LifecycleMode,
62}
63
64impl Default for LifecycleSettings {
65 fn default() -> Self {
66 Self {
67 lifecycle_type: LifecycleType::default(),
68 bucket: String::default(),
69 entries: Vec::default(),
70 older_than: String::default(),
71 interval: default_lifecycle_interval(),
72 when: Option::default(),
73 mode: LifecycleMode::default(),
74 }
75 }
76}
77
78fn default_lifecycle_interval() -> String {
79 "3600s".to_string()
80}
81
82#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
84pub struct LifecycleInfo {
85 pub name: String,
87 pub is_provisioned: bool,
89 pub is_running: bool,
91 #[serde(default, rename = "type")]
93 pub lifecycle_type: LifecycleType,
94 #[serde(default)]
96 pub mode: LifecycleMode,
97 #[serde(default)]
99 pub last_run: Option<DateTime<Utc>>,
100}
101
102#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
104pub struct LifecycleModePayload {
105 pub mode: LifecycleMode,
106}
107
108#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
110pub struct LifecycleList {
111 pub lifecycles: Vec<LifecycleInfo>,
113}
114
115#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
117pub struct FullLifecycleInfo {
118 pub info: LifecycleInfo,
120 pub settings: LifecycleSettings,
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn lifecycle_mode_default_is_enabled() {
130 assert_eq!(LifecycleMode::default(), LifecycleMode::Enabled);
131 }
132
133 #[test]
134 fn lifecycle_mode_serde_roundtrip() {
135 assert_eq!(
136 serde_json::to_string(&LifecycleMode::Enabled).unwrap(),
137 "\"enabled\""
138 );
139 assert_eq!(
140 serde_json::to_string(&LifecycleMode::Disabled).unwrap(),
141 "\"disabled\""
142 );
143 assert_eq!(
144 serde_json::to_string(&LifecycleMode::DryRun).unwrap(),
145 "\"dry_run\""
146 );
147
148 assert_eq!(
149 serde_json::from_str::<LifecycleMode>("\"enabled\"").unwrap(),
150 LifecycleMode::Enabled
151 );
152 assert_eq!(
153 serde_json::from_str::<LifecycleMode>("\"disabled\"").unwrap(),
154 LifecycleMode::Disabled
155 );
156 assert_eq!(
157 serde_json::from_str::<LifecycleMode>("\"dry_run\"").unwrap(),
158 LifecycleMode::DryRun
159 );
160 }
161
162 #[test]
163 fn lifecycle_settings_mode_defaults_on_missing() {
164 let settings: LifecycleSettings = serde_json::from_str(
165 r#"{
166 "type": "delete",
167 "bucket": "bucket-1",
168 "entries": ["entry-1"],
169 "older_than": "1d",
170 "interval": "1h"
171 }"#,
172 )
173 .unwrap();
174
175 assert_eq!(settings.mode, LifecycleMode::Enabled);
176 }
177
178 #[test]
179 fn lifecycle_settings_type_is_required() {
180 let err = serde_json::from_str::<LifecycleSettings>(
181 r#"{
182 "bucket": "bucket-1",
183 "older_than": "1d"
184 }"#,
185 )
186 .unwrap_err();
187
188 assert!(err.to_string().contains("missing field `type`"));
189 }
190
191 #[test]
192 fn lifecycle_settings_default_interval_is_3600s() {
193 let settings = LifecycleSettings::default();
194 assert_eq!(settings.interval, "3600s");
195 }
196
197 #[test]
198 fn lifecycle_info_mode_defaults_on_missing() {
199 let info: LifecycleInfo = serde_json::from_str(
200 r#"{
201 "name": "test",
202 "is_provisioned": false,
203 "is_running": true
204 }"#,
205 )
206 .unwrap();
207
208 assert_eq!(info.lifecycle_type, LifecycleType::Delete);
209 assert_eq!(info.mode, LifecycleMode::Enabled);
210 assert_eq!(info.last_run, None);
211 }
212
213 #[test]
214 fn lifecycle_mode_payload_serde_roundtrip() {
215 let payload = LifecycleModePayload {
216 mode: LifecycleMode::Disabled,
217 };
218
219 let serialized = serde_json::to_string(&payload).unwrap();
220 assert_eq!(serialized, r#"{"mode":"disabled"}"#);
221
222 let deserialized: LifecycleModePayload = serde_json::from_str(&serialized).unwrap();
223 assert_eq!(deserialized, payload);
224 }
225}