adds util

Signed-off-by: Jochen Maes <jochen@sejo-it.be>
This commit is contained in:
Jochen Maes 2023-10-21 08:39:19 +02:00
parent 5f58c86436
commit 55fc77b728
5 changed files with 175 additions and 10 deletions

View File

@ -1,6 +1,4 @@
use std::process::Command;
use crate::types::fact::{Fact, FactData};
use crate::{types::fact::{Fact, FactData}, util::command::get_result_as_string};
use serde::{Deserialize, Serialize};
pub struct IPData {}
@ -41,13 +39,7 @@ impl Fact for IPData {
fn gather(&self) -> Vec<FactData> {
let mut vfd: Vec<FactData> = vec![];
let time_set = self.get_epoch_ms();
let output = Command::new("ip")
.arg("-j")
.arg("addr")
.output()
.expect("Failed to execute ip");
let stdout = String::from_utf8(output.stdout).unwrap();
let ips: Vec<IpAddr> = serde_json::from_str(stdout.as_str()).unwrap();
let ips: Vec<IpAddr> = serde_json::from_str(get_result_as_string("ip", vec!["-j", "addr"]).as_str()).unwrap();
for ip in ips {
if ip.ifname != "lo" {
for addr_info in ip.addr_info {
@ -89,3 +81,27 @@ impl Fact for IPData {
return vfd;
}
}
#[derive(Serialize, Deserialize)]
struct IpRoute {
dst: String,
gateway: Option<String>,
dev: String,
protocol: Option<String>,
metric: Option<i32>,
flags: Vec<String>,
scope: String,
prefsrc: String,
}
impl Fact for IpRoute {
fn gather(&self) -> Vec<FactData> {
let mut vfd: Vec<FactData> = vec![];
let time_set = self.get_epoch_ms();
let routes: Vec<IpRoute> = serde_json::from_str(get_result_as_string("ip", vec!["-j", "route"]).as_str()).unwrap();
return vfd;
}
}

105
src/gatherers/system.rs Normal file
View File

@ -0,0 +1,105 @@
use std::process::Command;
use crate::types::fact::{Fact, FactData};
use serde::{Deserialize, Serialize};
pub struct SystemData {}
impl SystemData {}
#[derive(Serialize, Deserialize)]
struct UnameData{
kernel_name: String,
node_name: String,
kernel_release: String,
kernel_version: String,
machine: String,
processor: String,
hardware_platform: String,
operating_system: String,
}
#[derive(Serialize, Deserialize)]
struct IpAddrInfo {
family: String,
local: String,
prefixlen: i32,
broadcast: Option<String>,
scope: String,
dynamic: Option<bool>,
noprefixroute: Option<bool>,
label: Option<String>,
valid_life_time: i64,
preferred_life_time: i64,
}
#[derive(Serialize, Deserialize)]
struct IpAddr {
ifindex: i32,
ifname: String,
flags: Vec<String>,
mtu: i32,
qdisc: String,
operstate: String,
group: String,
txqlen: i32,
link_type: String,
address: Option<String>,
broadcast: Option<String>,
addr_info: Vec<IpAddrInfo>,
}
impl Fact for SystemData {
fn gather(&self) -> Vec<FactData> {
let mut vfd: Vec<FactData> = vec![];
let time_set = self.get_epoch_ms();
let output = Command::new("ip")
.arg("-j")
.arg("addr")
.output()
.expect("Failed to execute ip");
let stdout = String::from_utf8(output.stdout).unwrap();
let ips: Vec<IpAddr> = serde_json::from_str(stdout.as_str()).unwrap();
for ip in ips {
if ip.ifname != "lo" {
for addr_info in ip.addr_info {
let fd = FactData {
name: format!("ip_addr_{}_{}_addr", ip.ifname, addr_info.family),
value: addr_info.local,
time_set: time_set,
};
vfd.push(fd);
vfd.push(FactData {
name: format!("ip_addr_{}_{}_prefixlen", ip.ifname, addr_info.family),
value: addr_info.prefixlen.to_string(),
time_set: time_set,
});
if addr_info.label.is_some() {
vfd.push(FactData {
name: format!("ip_addr_{}_{}_label", ip.ifname, addr_info.family),
value: addr_info.label.unwrap(),
time_set: time_set,
});
}
if addr_info.broadcast.is_some() {
vfd.push(FactData {
name: format!("ip_addr_{}_{}_broadcast", ip.ifname, addr_info.family),
value: addr_info.broadcast.unwrap(),
time_set: time_set,
});
}
if ip.address.is_some() {
vfd.push(FactData {
name: format!("ip_addr_{}_macaddr", ip.ifname),
value: ip.address.clone().unwrap(),
time_set: time_set,
})
}
}
}
}
return vfd;
}
}

View File

@ -1,5 +1,6 @@
mod types;
mod gatherers;
mod util;
use std::collections::HashSet;
use crate::types::fact::{Fact, FactData};

42
src/util/command.rs Normal file
View File

@ -0,0 +1,42 @@
use std::process::{Command, Output};
fn get_output_from_command(cmd: &str, args: Vec<&str>) -> Output {
return Command::new(&cmd)
.args(args)
.output()
.expect(format!("Failed to execute command: {}", &cmd).as_str());
}
fn get_stdout_as_string(output: Output) -> String {
return match String::from_utf8(output.stdout) {
Ok(x) => x.strip_suffix("\n").unwrap().to_string(),
Err(e) => e.to_string()
}
}
fn get_stderr_as_string(output: Output) -> String {
return match String::from_utf8(output.stderr) {
Ok(x) => x.strip_suffix("\n").unwrap().to_string(),
Err(e) => e.to_string()
}
}
pub fn get_result_as_string(cmd: &str, args:Vec<&str>) -> String {
let output = get_output_from_command(cmd, args);
match output.status.code() {
Some(0) => get_stdout_as_string(output),
_ => get_stderr_as_string(output)
}
}
#[cfg(test)]
mod tests {
use crate::util::command::{get_result_as_string};
#[test]
fn test_get_output_from_command() {
assert_eq!("Linux", get_result_as_string("uname", vec![]));
assert_eq!("ls: cannot access '/dev/mouse': No such file or directory",
get_result_as_string("ls", vec!["/dev/mouse",]))
}
}

1
src/util/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod command;