iggy_cli/commands/binary_system/
snapshot.rs1use std::path::Path;
20
21use crate::commands::cli_command::{CliCommand, PRINT_TARGET};
22use anyhow::Context;
23use async_trait::async_trait;
24use comfy_table::Table;
25use iggy_common::Client;
26use iggy_common::{SnapshotCompression, SystemSnapshotType};
27use tokio::io::AsyncWriteExt;
28use tracing::{Level, event};
29
30pub struct GetSnapshotCmd {
31 compression: SnapshotCompression,
32 snapshot_types: Vec<SystemSnapshotType>,
33 out_dir: String,
34}
35
36impl GetSnapshotCmd {
37 pub fn new(
38 compression: Option<SnapshotCompression>,
39 snapshot_types: Option<Vec<SystemSnapshotType>>,
40 out_dir: Option<String>,
41 ) -> Self {
42 let default_types = vec![
43 SystemSnapshotType::FilesystemOverview,
44 SystemSnapshotType::ProcessList,
45 SystemSnapshotType::ResourceUsage,
46 SystemSnapshotType::ServerLogs,
47 ];
48 Self {
49 compression: compression.unwrap_or(SnapshotCompression::Deflated),
50 snapshot_types: snapshot_types.unwrap_or(default_types),
51 out_dir: out_dir.unwrap_or_else(|| ".".to_string()),
52 }
53 }
54}
55
56impl Default for GetSnapshotCmd {
57 fn default() -> Self {
58 Self::new(None, None, None)
59 }
60}
61
62#[async_trait]
63impl CliCommand for GetSnapshotCmd {
64 fn explain(&self) -> String {
65 "snapshot command".to_owned()
66 }
67
68 async fn execute_cmd(&mut self, client: &dyn Client) -> anyhow::Result<(), anyhow::Error> {
69 let snapshot_data = client
70 .snapshot(self.compression, self.snapshot_types.to_owned())
71 .await
72 .with_context(|| "Problem sending snapshot command".to_owned())?;
73 let file_path = Path::new(&self.out_dir).join(format!(
74 "snapshot_{}.zip",
75 chrono::Local::now().format("%Y%m%d_%H%M%S")
76 ));
77 let file_size = snapshot_data.0.len();
78
79 let mut file = tokio::fs::File::create(&file_path)
80 .await
81 .with_context(|| format!("Failed to create file at {file_path:?}"))?;
82
83 file.write_all(&snapshot_data.0)
84 .await
85 .with_context(|| "Failed to write snapshot data to file".to_owned())?;
86
87 let mut table = Table::new();
88 table.set_header(vec!["Property", "Value"]);
89 table.add_row(vec!["File Path", file_path.to_string_lossy().as_ref()]);
90 table.add_row(vec!["File Size (bytes)", &file_size.to_string()]);
91
92 event!(target: PRINT_TARGET, Level::INFO, "{table}");
93
94 Ok(())
95 }
96}