Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 68 additions & 29 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,39 @@ use clap::{App, Arg, crate_version};
mod cpu;
mod memory;
mod gcc;
mod security;

// TODO: rename this
struct PlatformData {
struct SingleCollector {
tag: &'static str,
func: fn(&mut Collector) -> Result<CollectorValue, CollectorErr>,
}

struct GroupCollector {
tag: &'static str,
func: fn(&mut Collector) -> Result<Vec<(String, CollectorValue)>, CollectorErr>,
}

enum Tag {
Single(SingleCollector),
Group(GroupCollector),
}

// TODO: This also needed a better name than "platform"
const PLATFORM: &'static [PlatformData] = &[
PlatformData {tag: "cpu.cores", func: cpu::get_cores},
PlatformData {tag: "mem.total", func: memory::get_mem_total},
PlatformData {tag: "mem.used", func: memory::get_mem_used},
PlatformData {tag: "mem.free", func: memory::get_mem_free},
PlatformData {tag: "mem.shared", func: memory::get_mem_shared},
PlatformData {tag: "mem.buff/cache", func: memory::get_mem_buff_and_cache},
PlatformData {tag: "mem.available", func: memory::get_mem_available},
PlatformData {tag: "swap.total", func: memory::get_swap_total},
PlatformData {tag: "swap.used", func: memory::get_swap_used},
PlatformData {tag: "swap.free", func: memory::get_swap_free},
PlatformData {tag: "gcc.version", func: gcc::version},
PlatformData {tag: "gcc.flags", func: gcc::flags},
const PLATFORM: &'static [Tag] = &[
Tag::Single(SingleCollector {tag: "cpu.cores", func: cpu::get_cores}),
Tag::Single(SingleCollector {tag: "mem.total", func: memory::get_mem_total}),
Tag::Single(SingleCollector {tag: "mem.used", func: memory::get_mem_used}),
Tag::Single(SingleCollector {tag: "mem.free", func: memory::get_mem_free}),
Tag::Single(SingleCollector {tag: "mem.shared", func: memory::get_mem_shared}),
Tag::Single(SingleCollector {tag: "mem.buff/cache", func: memory::get_mem_buff_and_cache}),
Tag::Single(SingleCollector {tag: "mem.available", func: memory::get_mem_available}),
Tag::Single(SingleCollector {tag: "swap.total", func: memory::get_swap_total}),
Tag::Single(SingleCollector {tag: "swap.used", func: memory::get_swap_used}),
Tag::Single(SingleCollector {tag: "swap.free", func: memory::get_swap_free}),
Tag::Single(SingleCollector {tag: "gcc.version", func: gcc::version}),
Tag::Single(SingleCollector {tag: "gcc.flags", func: gcc::flags}),
Tag::Group(GroupCollector {tag: "security.vulnerability", func: security::get_vulnerabilities}),
];

fn main() {
Expand Down Expand Up @@ -61,22 +73,49 @@ fn main() {
// Iterate through each tag:func pair
// Call the function, and insert the data from the collecting function
for pd in PLATFORM {
let f = pd.func;

let data = f(&mut col);

if let Ok(d) = data {
col.add_data(String::from(pd.tag), d)
}
else if matches.is_present("allow-failures") {
// TODO: Use a CollectorError type here and use that to record the error.
col.add_data(String::from(pd.tag), CollectorValue::Text(String::from("(null)")));
}
else {
// Propogate the panic upwards and stop the collection.
// TODO: Maybe be a little nicer about this.
data.unwrap();
match pd {
Tag::Single(pd) => {
let f = pd.func;

let data = f(&mut col);

if let Ok(d) = data {
col.add_data(String::from(pd.tag), d)
}
else if matches.is_present("allow-failures") {
// TODO: Use a CollectorError type here and use that to record the error.
col.add_data(String::from(pd.tag), CollectorValue::Text(String::from("(null)")));
}
else {
// Propogate the panic upwards and stop the collection.
// TODO: Maybe be a little nicer about this.
data.unwrap();
}
}
// TODO: This and the above are basically the same but with minor deviations
// can probably be rewritten to share logic a bit better
Tag::Group(pd) => {
let f = pd.func;

let data = f(&mut col);

if let Ok(tg) = data {
for (tag, d) in tg {
col.add_data(format!("{}.{}", pd.tag, tag), d)
}
}
else if matches.is_present("allow-failures") {
// TODO: Use a CollectorError type here and use that to record the error.
col.add_data(String::from(pd.tag), CollectorValue::Text(String::from("(null)")));
}
else {
// Propogate the panic upwards and stop the collection.
// TODO: Maybe be a little nicer about this.
data.unwrap();
}
}
}

}

match matches.value_of("output") {
Expand Down
26 changes: 26 additions & 0 deletions src/security.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 IBM Corp.
use crate::collector::*;

static BASE_DIR: &str = "/sys/devices/system/cpu/vulnerabilities/";

pub fn get_vulnerabilities(_col: &mut Collector) -> Result<Vec<(String, CollectorValue)>, CollectorErr> {
let mut ret = Vec::new();

// TODO: perhaps report missing directory (older kernels?) better here
let paths = std::fs::read_dir(BASE_DIR)?;

for p in paths {
// TODO: perhaps skip over errors here in allow-failures mode?
let p = p?;

let out = _col.run_command(format!("cat {}", p.path().display()).as_str());

let tag = String::from(p.file_name().to_str().unwrap());
let value = CollectorValue::Text(String::from_utf8(out.stdout).unwrap().trim().to_string());

ret.push((tag, value));
}

Ok(ret)
}