From 71ee0aaab0bb217367e94f6829f1e8373ebb6f1b Mon Sep 17 00:00:00 2001 From: Jochen Maes Date: Fri, 27 Oct 2023 07:08:18 +0200 Subject: [PATCH] improves workings Signed-off-by: Jochen Maes --- .drone.yml | 44 +++++++++++++ Cargo.lock | 20 +++--- Cargo.toml | 2 +- src/gatherers/environment.rs | 31 ++++++---- src/gatherers/ip.rs | 116 ++++++----------------------------- src/gatherers/mod.rs | 2 +- src/main.rs | 114 ++++++++++++++++------------------ src/types/fact.rs | 24 +++----- src/types/mod.rs | 2 +- src/util/command.rs | 20 +++--- src/util/mod.rs | 2 +- 11 files changed, 168 insertions(+), 209 deletions(-) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..dc4ce94 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,44 @@ +--- +kind: pipeline +type: docker +name: "Mouse release" + +platform: + arch: amd64 + +trigger: + event: + - tag + +volumes: + - name: dockersock + host: + path: /var/run/docker.sock + - name: artifacts + temp: {} + +steps: + - name: build amd64 + image: rust:1.73 + commands: + - rustup target add x86_64-unknown-linux-musl + - rustup target add aarch64-unknown-linux-musl + - cargo build --target x86_64-unknown-linux-musl --bins -r + - cargo build --target aarch64-unknown-linux-musl --bins -r + - cp target/x86_64-unknown-linux-musl/release/mouse /artifcats/mouse-amd64 + - cp target/aarch64-unknown-linux-musl/release/mouse /artifcats/mouse-arm64 + volumes: + - name: artifacts + path: /artifcats/ + + - name: create gitea release + image: plugins/gitea-release + settings: + api_key: + from_secret: gitea_api_key + base_url: https://gitea.sejo-it.be + checksum: sha265 + files: /artifacts/* + volumes: + - name: artifacts + path: /artifcats/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index f1092b4..f0298c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,9 +52,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -62,9 +62,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -74,9 +74,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -86,9 +86,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -125,9 +125,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" diff --git a/Cargo.toml b/Cargo.toml index 8b1ba31..5526f7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "4.4.6", features = ["derive"] } +clap = { version = "4.4.7", features = ["derive"] } csv = "1.3.0" serde = { version = "1.0.189", features = ["std", "derive"] } serde_json = "1.0.107" diff --git a/src/gatherers/environment.rs b/src/gatherers/environment.rs index 08f2cc0..3f47e63 100644 --- a/src/gatherers/environment.rs +++ b/src/gatherers/environment.rs @@ -1,23 +1,28 @@ -use crate::types::fact::{FactData, Fact}; +use crate::types::fact::Fact; +use serde::{Deserialize, Serialize}; +use serde_json::Value; use std::env; pub struct EnvironmentData {} +impl EnvironmentData {} -impl EnvironmentData { +#[derive(Serialize, Deserialize)] +pub struct EnvironmentValue { + key: String, + value: String, + time_set: u128, } impl Fact for EnvironmentData { - fn gather(&self) -> Vec{ - let mut vfd: Vec = vec![]; - let time_set = self.get_epoch_ms(); + fn gather(&self) -> String { + let mut outmap: Vec = vec![]; for (key, value) in env::vars() { - let fd = FactData{ - name: String::from("env_") + &key, - value: value, - time_set: time_set - }; - vfd.push(fd); + let entry = json!({ + "key": &key, + "value": value, + }); + outmap.append(&mut vec![entry]); } - return vfd; + serde_json::to_string(&outmap).unwrap() } -} \ No newline at end of file +} diff --git a/src/gatherers/ip.rs b/src/gatherers/ip.rs index 2a2438a..53fc461 100644 --- a/src/gatherers/ip.rs +++ b/src/gatherers/ip.rs @@ -1,107 +1,29 @@ -use crate::{types::fact::{Fact, FactData}, util::command::get_result_as_string}; +use crate::{types::fact::Fact, util::command::get_result_as_string}; use serde::{Deserialize, Serialize}; +use serde_json::Value; +#[derive(Serialize, Deserialize)] pub struct IPData {} - impl IPData {} -#[derive(Serialize, Deserialize)] -struct IpAddrInfo { - family: String, - local: String, - prefixlen: i32, - broadcast: Option, - scope: String, - dynamic: Option, - noprefixroute: Option, - label: Option, - valid_life_time: i64, - preferred_life_time: i64, -} - -#[derive(Serialize, Deserialize)] -struct IpAddr { - ifindex: i32, - ifname: String, - flags: Vec, - mtu: i32, - qdisc: String, - operstate: String, - group: String, - txqlen: i32, - link_type: String, - address: Option, - broadcast: Option, - addr_info: Vec, -} - impl Fact for IPData { - fn gather(&self) -> Vec { - let mut vfd: Vec = vec![]; - let time_set = self.get_epoch_ms(); - let ips: Vec = 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 { - 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; + fn gather(&self) -> String { + let res = get_result_as_string("ip", vec!["-j", "addr"]); + let jsonres: Value = serde_json::from_str(res.as_str()).unwrap(); + let out = json!({ "ip_addr": jsonres }); + out.to_string() } } +pub struct IPRouteData {} +impl IPRouteData {} -#[derive(Serialize, Deserialize)] -struct IpRoute { - dst: String, - gateway: Option, - dev: String, - protocol: Option, - metric: Option, - flags: Vec, - scope: String, - prefsrc: String, - -} - -impl Fact for IpRoute { - fn gather(&self) -> Vec { - let mut vfd: Vec = vec![]; - let time_set = self.get_epoch_ms(); - - let routes: Vec = serde_json::from_str(get_result_as_string("ip", vec!["-j", "route"]).as_str()).unwrap(); - - return vfd; +impl Fact for IPRouteData { + fn gather(&self) -> String { + let res = get_result_as_string("ip", vec!["-j", "route"]); + let jsonres: Value = serde_json::from_str(res.as_str()).unwrap(); + let out = json!({ + "ip_route": jsonres + }); + out.to_string() } -} \ No newline at end of file +} diff --git a/src/gatherers/mod.rs b/src/gatherers/mod.rs index a6ae982..b75ed35 100644 --- a/src/gatherers/mod.rs +++ b/src/gatherers/mod.rs @@ -1,2 +1,2 @@ pub mod environment; -pub mod ip; \ No newline at end of file +pub mod ip; diff --git a/src/main.rs b/src/main.rs index f6eba3b..4d7f188 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,16 @@ -mod types; mod gatherers; +mod types; mod util; -use std::collections::HashSet; -use crate::types::fact::{Fact, FactData}; -use crate::gatherers::environment::EnvironmentData; -use crate::gatherers::ip::IPData; -use clap::Parser; -use csv::Writer; +#[macro_use] +extern crate serde_json; +use crate::gatherers::environment::EnvironmentData; +use crate::gatherers::ip::{IPData, IPRouteData}; +use crate::types::fact::Fact; +use clap::Parser; +use serde_json::Value; +use std::collections::{HashMap, HashSet}; #[derive(Parser)] #[clap(author, version, about, long_about = None)] @@ -17,69 +19,61 @@ struct Args { #[arg(short, long)] gatherer: Option>, /// Output format, yaml, json are supported - #[arg(short, long, default_value="yaml")] + #[arg(short, long, default_value = "yaml")] output: String, } -fn gather_all() -> Vec{ - let mut data: Vec = vec![]; - data.append(&mut gather(&EnvironmentData{})); - data.append(&mut gather(&IPData{})); - return data; -} - -fn gather_list(gatherers: HashSet) -> Vec { - let mut data: Vec = vec![]; +fn gather_list(gatherers: HashSet, output: &str) -> String { + let mut outmap: HashMap = HashMap::new(); for g in gatherers { match g.as_str() { - "all" => for d in gather_all(){ - data.push(d); - }, - "env" => for d in gather(&EnvironmentData{}) { - data.push(d); - }, - "ip" => for d in gather(&IPData{}) { - data.push(d); + "env" => { + outmap.insert( + "environment".to_string(), + serde_json::from_str(&EnvironmentData {}.gather()).unwrap(), + ); + } + "ipaddr" => { + outmap.insert( + "ipaddr".to_string(), + serde_json::from_str(&IPData {}.gather()).unwrap(), + ); + } + "iproute" => { + outmap.insert( + "iproute".to_string(), + serde_json::from_str(&IPRouteData {}.gather()).unwrap(), + ); + } + x => { + println!("unknown gatherer: {x}"); } - _ => for d in gather_all() { - data.push(d); - } }; } - return data; -} -fn gather (t: &dyn Fact) -> Vec { - return t.gather(); + match output { + "json" => serde_json::to_string(&outmap).unwrap(), + "yaml" => serde_yaml::to_string(&outmap).unwrap(), + x => format!("Unknown output format {x}"), + } } fn main() { let args = Args::parse(); - let mut data:Vec = vec![]; - - if args.gatherer.is_none() { - data.append(&mut gather_all()); - } else { - // sanitize the gatherer list - let ugatherers: HashSet = match &args.gatherer { - Some(x) => x.into_iter().map(|name| name).cloned().collect::>(), - None => HashSet::::new(), - }; - data.append(&mut gather_list(ugatherers)); - } - match args.output.as_str() { - "json" => { - let serialized_json = serde_json::to_string(&data).unwrap(); - println!("{}", serialized_json); - }, - "csv" => { - let mut writer = Writer::from_writer(vec![]); - for fd in data { - writer.serialize(fd).unwrap(); - } - println!("{}", String::from_utf8(writer.into_inner().unwrap()).unwrap()); - } - &_ => { - let serialized_yaml = serde_yaml::to_string(&data).unwrap(); - println!("{}", serialized_yaml); - }, + let output_format = match args.output.as_str() { + "json" => "json", + "yaml" => "yaml", + _ => "yaml", }; + let all: HashSet = HashSet::from([ + "env".to_string(), + "ipaddr".to_string(), + "iproute".to_string(), + ]); + let data_output: String = match args.gatherer { + None => gather_list(all, output_format), + Some(x) => { + let gatherers: HashSet = x.into_iter().collect::>(); + gather_list(gatherers, output_format) + } + }; + println!("{}", data_output); } diff --git a/src/types/fact.rs b/src/types/fact.rs index 87007b0..7ed078b 100644 --- a/src/types/fact.rs +++ b/src/types/fact.rs @@ -1,20 +1,12 @@ -use std::time::{UNIX_EPOCH, SystemTime}; -use serde::{Serialize, Deserialize}; +use std::time::{SystemTime, UNIX_EPOCH}; -#[derive(Serialize, Deserialize)] -pub struct FactData { - pub name: String, - pub value: String, - pub time_set: u128, -} - -pub trait Fact : Send + Sync { - fn gather(&self) -> Vec; +pub trait Fact: Send + Sync { + fn gather(&self) -> String; fn get_epoch_ms(&self) -> u128 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis() + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() } -} \ No newline at end of file +} diff --git a/src/types/mod.rs b/src/types/mod.rs index eeaf59b..c93a213 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1 +1 @@ -pub mod fact; \ No newline at end of file +pub mod fact; diff --git a/src/util/command.rs b/src/util/command.rs index 6b5fc88..c444b16 100644 --- a/src/util/command.rs +++ b/src/util/command.rs @@ -10,33 +10,35 @@ fn get_output_from_command(cmd: &str, args: Vec<&str>) -> Output { 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() - } + 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() - } + Err(e) => e.to_string(), + }; } -pub fn get_result_as_string(cmd: &str, args:Vec<&str>) -> 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) + _ => get_stderr_as_string(output), } } #[cfg(test)] mod tests { - use crate::util::command::{get_result_as_string}; + 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",])) + assert_eq!( + "ls: cannot access '/dev/mouse': No such file or directory", + get_result_as_string("ls", vec!["/dev/mouse",]) + ) } } diff --git a/src/util/mod.rs b/src/util/mod.rs index ab8b7ed..9fe7961 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1 +1 @@ -pub mod command; \ No newline at end of file +pub mod command;