Skip to main content

iggy_cli/commands/binary_system/
snapshot.rs

1/* Licensed to the Apache Software Foundation (ASF) under one
2 * or more contributor license agreements.  See the NOTICE file
3 * distributed with this work for additional information
4 * regarding copyright ownership.  The ASF licenses this file
5 * to you under the Apache License, Version 2.0 (the
6 * "License"); you may not use this file except in compliance
7 * with the License.  You may obtain a copy of the License at
8 *
9 *   http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied.  See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18
19use 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}