zlayer_types/api/
system.rs1use serde::{Deserialize, Serialize};
10use utoipa::ToSchema;
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
14pub struct DiskUsageCategory {
15 pub name: String,
18 pub total_bytes: u64,
20 pub reclaimable_bytes: u64,
23 pub item_count: u64,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, ToSchema)]
29pub struct SystemDiskUsage {
30 pub categories: Vec<DiskUsageCategory>,
31 pub total_bytes: u64,
33 pub total_reclaimable_bytes: u64,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, ToSchema)]
39pub struct SystemPruneReport {
40 pub stopped_containers: Vec<String>,
43 pub dead_deployments: Vec<String>,
44 pub deleted_images: Vec<String>,
45 pub deleted_volumes: Vec<String>,
46 pub deleted_networks: Vec<String>,
47 pub reclaimed_layers: Vec<String>,
48 pub reclaimed_blobs: Vec<String>,
49 pub reclaimed_bundles: Vec<String>,
50 pub space_reclaimed_bytes: u64,
52}
53
54impl SystemPruneReport {
55 #[must_use]
57 pub fn total_items(&self) -> usize {
58 self.stopped_containers.len()
59 + self.dead_deployments.len()
60 + self.deleted_images.len()
61 + self.deleted_volumes.len()
62 + self.deleted_networks.len()
63 + self.reclaimed_layers.len()
64 + self.reclaimed_blobs.len()
65 + self.reclaimed_bundles.len()
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_system_disk_usage_roundtrip() {
75 let usage = SystemDiskUsage {
76 categories: vec![
77 DiskUsageCategory {
78 name: "images".to_string(),
79 total_bytes: 10_000,
80 reclaimable_bytes: 2_500,
81 item_count: 7,
82 },
83 DiskUsageCategory {
84 name: "layers".to_string(),
85 total_bytes: 40_000,
86 reclaimable_bytes: 5_000,
87 item_count: 23,
88 },
89 ],
90 total_bytes: 50_000,
91 total_reclaimable_bytes: 7_500,
92 };
93
94 let json = serde_json::to_string(&usage).unwrap();
95 assert!(json.contains("\"images\""));
96 assert!(json.contains("\"total_bytes\":50000"));
97 assert!(json.contains("\"total_reclaimable_bytes\":7500"));
98
99 let back: SystemDiskUsage = serde_json::from_str(&json).unwrap();
100 assert_eq!(back, usage);
101 }
102
103 #[test]
104 fn test_system_disk_usage_default() {
105 let usage = SystemDiskUsage::default();
106 assert!(usage.categories.is_empty());
107 assert_eq!(usage.total_bytes, 0);
108 assert_eq!(usage.total_reclaimable_bytes, 0);
109 }
110
111 #[test]
112 fn test_system_prune_report_roundtrip() {
113 let report = SystemPruneReport {
114 stopped_containers: vec!["c1".to_string(), "c2".to_string()],
115 dead_deployments: vec!["dep-old".to_string()],
116 deleted_images: vec!["nginx:latest".to_string()],
117 deleted_volumes: vec!["vol-a".to_string()],
118 deleted_networks: vec![],
119 reclaimed_layers: vec!["sha256:aaa".to_string(), "sha256:bbb".to_string()],
120 reclaimed_blobs: vec!["sha256:ccc".to_string()],
121 reclaimed_bundles: vec!["bundle-1".to_string()],
122 space_reclaimed_bytes: 123_456,
123 };
124
125 let json = serde_json::to_string(&report).unwrap();
126 let back: SystemPruneReport = serde_json::from_str(&json).unwrap();
127 assert_eq!(back, report);
128 assert!(json.contains("\"space_reclaimed_bytes\":123456"));
129 }
130
131 #[test]
132 fn test_system_prune_report_total_items() {
133 let report = SystemPruneReport {
134 stopped_containers: vec!["c1".to_string(), "c2".to_string()],
135 dead_deployments: vec!["dep-old".to_string()],
136 deleted_images: vec!["nginx:latest".to_string()],
137 deleted_volumes: vec!["vol-a".to_string()],
138 deleted_networks: vec!["net-1".to_string()],
139 reclaimed_layers: vec!["sha256:aaa".to_string(), "sha256:bbb".to_string()],
140 reclaimed_blobs: vec!["sha256:ccc".to_string()],
141 reclaimed_bundles: vec!["bundle-1".to_string()],
142 space_reclaimed_bytes: 0,
143 };
144 assert_eq!(report.total_items(), 10);
146 }
147
148 #[test]
149 fn test_system_prune_report_default_empty() {
150 let report = SystemPruneReport::default();
151 assert_eq!(report.total_items(), 0);
152 assert_eq!(report.space_reclaimed_bytes, 0);
153 }
154}