switchboard_container_utils/
utils.rs

1use crate::ContainerResult;
2use regex::Regex;
3use std::time::{SystemTime, UNIX_EPOCH};
4use switchboard_common::FunctionResult;
5
6pub fn unix_timestamp() -> u64 {
7    let now = SystemTime::now();
8    if let Ok(since_the_epoch) = now.duration_since(UNIX_EPOCH) {
9        since_the_epoch.as_secs()
10    } else {
11        0
12    }
13}
14
15pub fn truncate_string(input: &str, max_length: usize) -> String {
16    if input.len() > max_length {
17        let truncated = &input[..max_length - 3]; // Subtract 3 to account for the added "..."
18        format!("{}...", truncated)
19    } else {
20        input.to_string()
21    }
22}
23
24pub fn format_bytes(bytes: f64) -> String {
25    const KB: f64 = 1024.0;
26    const MB: f64 = KB * KB;
27    const GB: f64 = MB * KB;
28    const TB: f64 = GB * KB;
29
30    if bytes < KB {
31        format!("{} B", bytes)
32    } else if bytes < MB {
33        format!("{:.2} KB", bytes / KB)
34    } else if bytes < GB {
35        format!("{:.2} MB", bytes / MB)
36    } else if bytes < TB {
37        format!("{:.2} GB", bytes / GB)
38    } else {
39        format!("{:.2} TB", bytes / TB)
40    }
41}
42
43static PREFIX: &str =
44    "-----------------------------------------------------------------------------------------------------------------------";
45static GLOG_1: &str = "Gramine detected the following insecure configurations:";
46static GLOG_2: &str =
47    "- sys.insecure__allow_eventfd = true         (host-based eventfd is enabled)";
48static GLOG_3: &str =
49    "- sgx.allowed_files = [ ... ]                (some files are passed through from untrusted host without verification)";
50static GLOG_4: &str =
51    "Gramine will continue application execution, but this configuration must not be used in production!";
52static SILENCED_SUBSTRS: [&str; 5] = [PREFIX, GLOG_1, GLOG_2, GLOG_3, GLOG_4];
53
54pub fn parse_gramine_logs(logs: &str) -> String {
55    // let mut result = logs;
56    // for &substring in SILENCED_SUBSTRS.iter() {
57    //     result = result.replace(substring, "");
58    // }
59    // result
60
61    let pattern = SILENCED_SUBSTRS
62        .iter()
63        .map(|&s| regex::escape(s))
64        .collect::<Vec<_>>()
65        .join("|");
66
67    let re = Regex::new(&pattern).unwrap();
68    re.replace_all(logs, "").to_string()
69}
70
71pub fn find_fn_result(logs: &str) -> ContainerResult<FunctionResult> {
72    if logs.is_empty() {
73        return Err(switchboard_common::SbError::FunctionResultParseError);
74    }
75    // {
76    // let logs: Vec<String> = logs
77    // .split('\n')
78    // .map(|s| s.to_string())
79    // .filter(|s| !s.starts_with("FN_OUT"))
80    // .collect();
81    // println!("[DOCKER] {:#?}", logs);
82    // }
83    let last_line = logs.trim_end().split('\n').last().unwrap();
84
85    // let last_word: String = last_line
86    //     .chars()
87    //     .filter(|c| c.is_ascii_hexdigit() || c.is_alphabetic())
88    //     .collect();
89    FunctionResult::decode(last_line)
90        .map_err(|_| switchboard_common::SbError::FunctionResultParseError)
91}
92
93/// Find all lines in the logs that start with "FN_OUT: "
94pub fn find_all_fn_out_lines(text: &str) -> Vec<&str> {
95    let re = regex::Regex::new(r"(?m)^FN_OUT: [0-9a-fA-F]+.*").unwrap();
96    re.captures_iter(text)
97        .map(|cap| cap.get(0).map_or("", |m| m.as_str()))
98        .collect()
99}