From 968922478e421cef7c05dd44e26a9df93dc938b7 Mon Sep 17 00:00:00 2001 From: David Boucher Date: Thu, 27 Mar 2025 15:20:39 +0100 Subject: [PATCH] wip(generic-snmp): with a better json structure. Not functional --- experimental/Cargo.toml | 2 +- experimental/examples/new-cpu.json | 16 +- experimental/examples/new-cpu.json.example | 31 ++ experimental/examples/new-disk.json | 24 +- experimental/examples/new-disk.json.example | 46 ++ experimental/examples/new-mem.json | 19 +- experimental/examples/new-mem.json.example | 36 ++ experimental/src/generic/mod.rs | 555 ++++++++++---------- experimental/src/main.rs | 96 +++- 9 files changed, 481 insertions(+), 344 deletions(-) create mode 100644 experimental/examples/new-cpu.json.example create mode 100644 experimental/examples/new-disk.json.example create mode 100644 experimental/examples/new-mem.json.example diff --git a/experimental/Cargo.toml b/experimental/Cargo.toml index ff37123c2..9b10efd7a 100644 --- a/experimental/Cargo.toml +++ b/experimental/Cargo.toml @@ -18,7 +18,7 @@ rasn = "0.24.0" rasn-snmp = "0.24.0" rasn-smi = "0.24.0" log = "0.4.25" -clap = { version = "4.5.29", features = ["derive"] } +lexopt = "0.3.0" serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.138" lalrpop-util = { version = "0.22.1", features = ["lexer"] } diff --git a/experimental/examples/new-cpu.json b/experimental/examples/new-cpu.json index badb30e4b..8c28d518b 100644 --- a/experimental/examples/new-cpu.json +++ b/experimental/examples/new-cpu.json @@ -4,7 +4,7 @@ { "name": "cpu", "oid": "1.3.6.1.2.1.25.3.3.1.2", - "query": "Walk", // par défaut walk + "query": "Walk" } ] }, @@ -13,18 +13,18 @@ { "name": "core.cpu.usage.percent", "value": "{cpu}", - "uom": "%", // optional - "min": 0, // optional - "max": 100 // optional + "uom": "%", + "min": 0, + "max": 100 } ], "aggregations": [ { "name": "avg.cpu.usage.percent", - "value": "Average({cpu})", // si agregation, pas de prefix - "uom": "%", // optional - "min": 0, // optional - "max": 100 // optional + "value": "Average({cpu})", + "uom": "%", + "min": 0, + "max": 100 } ] } diff --git a/experimental/examples/new-cpu.json.example b/experimental/examples/new-cpu.json.example new file mode 100644 index 000000000..badb30e4b --- /dev/null +++ b/experimental/examples/new-cpu.json.example @@ -0,0 +1,31 @@ +{ + "collect": { + "snmp": [ + { + "name": "cpu", + "oid": "1.3.6.1.2.1.25.3.3.1.2", + "query": "Walk", // par défaut walk + } + ] + }, + "compute": { + "metrics": [ + { + "name": "core.cpu.usage.percent", + "value": "{cpu}", + "uom": "%", // optional + "min": 0, // optional + "max": 100 // optional + } + ], + "aggregations": [ + { + "name": "avg.cpu.usage.percent", + "value": "Average({cpu})", // si agregation, pas de prefix + "uom": "%", // optional + "min": 0, // optional + "max": 100 // optional + } + ] + } +} diff --git a/experimental/examples/new-disk.json b/experimental/examples/new-disk.json index fbc85a794..98056f355 100644 --- a/experimental/examples/new-disk.json +++ b/experimental/examples/new-disk.json @@ -4,7 +4,7 @@ { "name": "disk", "oid": "1.3.6.1.2.1.25.2.3.1", - "query": "Walk", // par défaut walk + "query": "Walk", "labels": { ".3": "label", ".4": "allocationUnits", @@ -17,28 +17,28 @@ "compute": { "metrics": [ { - "prefix": "{disk.label}", // par défaut "{idx}" + "prefix": "{disk.label}", "name": "disk.usage.percent", "value": "100 * {disk.used} / {disk.size}", - "uom": "%", // optional - "min": 0, // optional - "max": 100, // optional + "uom": "%", + "min": 0, + "max": 100 }, { "name": "disk.usage.bytes", "value": "{disk.used} * {disk.allocationUnits}", - "uom": "B", // optional - "min": 0, // optional - "max_expr": "{disk.size} * {disk.allocationUnits}" // optional + "uom": "B", + "min": 0, + "max_expr": "{disk.size} * {disk.allocationUnits}" } ], "aggregations": [ { "name": "avg.disk.usage.percent", - "value": "Average({metrics.disk.usage.percent})", // si agregation, pas de prefix - "uom": "%", // optional - "min": 0, // optional - "max": 100 // optional + "value": "Average({metrics.disk.usage.percent})", + "uom": "%", + "min": 0, + "max": 100 } ] } diff --git a/experimental/examples/new-disk.json.example b/experimental/examples/new-disk.json.example new file mode 100644 index 000000000..fbc85a794 --- /dev/null +++ b/experimental/examples/new-disk.json.example @@ -0,0 +1,46 @@ +{ + "collect": { + "snmp": [ + { + "name": "disk", + "oid": "1.3.6.1.2.1.25.2.3.1", + "query": "Walk", // par défaut walk + "labels": { + ".3": "label", + ".4": "allocationUnits", + ".5": "size", + ".6": "used" + } + } + ] + }, + "compute": { + "metrics": [ + { + "prefix": "{disk.label}", // par défaut "{idx}" + "name": "disk.usage.percent", + "value": "100 * {disk.used} / {disk.size}", + "uom": "%", // optional + "min": 0, // optional + "max": 100, // optional + }, + { + "name": "disk.usage.bytes", + "value": "{disk.used} * {disk.allocationUnits}", + "uom": "B", // optional + "min": 0, // optional + "max_expr": "{disk.size} * {disk.allocationUnits}" // optional + } + ], + "aggregations": [ + { + "name": "avg.disk.usage.percent", + "value": "Average({metrics.disk.usage.percent})", // si agregation, pas de prefix + "uom": "%", // optional + "min": 0, // optional + "max": 100 // optional + } + ] + } +} + diff --git a/experimental/examples/new-mem.json b/experimental/examples/new-mem.json index feb981b17..2cbdc2e17 100644 --- a/experimental/examples/new-mem.json +++ b/experimental/examples/new-mem.json @@ -4,12 +4,12 @@ { "name": "total", "oid": "1.3.6.1.4.1.2021.4.6.0", - "query": "Get", // par défaut walk + "query": "Get" }, { "name": "free", "oid": "1.3.6.1.4.1.2021.4.11.0", - "query": "Get", // par défaut walk + "query": "Get" } ] }, @@ -18,16 +18,17 @@ { "name": "core.mem.usage.percent", "value": "100 * (1 - {free}/{cpu})", - "uom": "%", // optional - "min": 0, // optional - "max": 100 // optional + "uom": "%", + "min": 0, + "max": 100, + "threshold-suffix": "mem" }, { "name": "avg.cpu.usage.percent", - "value": "Average({cpu})", // si agregation, pas de prefix - "uom": "%", // optional - "min": 0, // optional - "max": 100 // optional + "value": "Average({cpu})", + "uom": "%", + "min": 0, + "max": 100 } ] } diff --git a/experimental/examples/new-mem.json.example b/experimental/examples/new-mem.json.example new file mode 100644 index 000000000..abf2c24d4 --- /dev/null +++ b/experimental/examples/new-mem.json.example @@ -0,0 +1,36 @@ +{ + "collect": { + "snmp": [ + { + "name": "total", + "oid": "1.3.6.1.4.1.2021.4.6.0", + "query": "Get", // par défaut walk + }, + { + "name": "free", + "oid": "1.3.6.1.4.1.2021.4.11.0", + "query": "Get", // par défaut walk + } + ] + }, + "compute": { + "metrics": [ + { + "name": "core.mem.usage.percent", + "value": "100 * (1 - {free}/{cpu})", + "uom": "%", // optional + "min": 0, // optional + "max": 100, // optional + "threshold-suffix": "mem", // optional (example: --warning-mem=78 --critical-mem=90) + }, + { + "name": "avg.cpu.usage.percent", + "value": "Average({cpu})", // si agregation, pas de prefix + "uom": "%", // optional + "min": 0, // optional + "max": 100 // optional + } + ] + } +} + diff --git a/experimental/src/generic/mod.rs b/experimental/src/generic/mod.rs index 6fd25685f..742d09b01 100644 --- a/experimental/src/generic/mod.rs +++ b/experimental/src/generic/mod.rs @@ -23,15 +23,6 @@ impl Status { } } -struct Metric<'b> { - name: String, - value: f32, - warning: &'b Option, - critical: &'b Option, - status: Status, - agregated: bool, -} - fn worst(a: Status, b: Status) -> Status { let a_int = match a { Status::Ok => 0, @@ -52,60 +43,42 @@ fn worst(a: Status, b: Status) -> Status { } } -#[derive(Deserialize, Debug, Clone, Copy)] -enum Operation { - None, - Average, -} - #[derive(Deserialize, Debug)] enum QueryType { Walk, } #[derive(Deserialize, Debug)] -struct EntryOperation { +struct Metric { name: String, - op: Operation, + value: String, + uom: Option, + min: Option, + max: Option, } #[derive(Deserialize, Debug)] -struct EntryQuery { +pub struct Compute { + metrics: Vec, + aggregations: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct Snmp { name: String, oid: String, query: QueryType, } #[derive(Deserialize, Debug)] -enum Entry { - Agregation(EntryOperation), - Query(EntryQuery), -} - -#[derive(Deserialize, Debug)] -struct Data { - uom: String, - min: Option, - max: Option, -} - -#[derive(Deserialize, Debug)] -struct OutputTable { - header: String, - text: Vec, -} - -#[derive(Deserialize, Debug)] -struct Leaf { - name: String, - output: OutputTable, - entries: Vec, - data: Option, +pub struct Collect { + snmp: Vec, } #[derive(Deserialize, Debug)] pub struct Command { - leaf: Leaf, + collect: Collect, + compute: Compute, } pub struct CmdResult { @@ -136,66 +109,66 @@ fn compute_status(value: f32, warn: &Option, crit: &Option) -> S Status::Ok } -fn build_metrics<'a>( - values: &Vec<(String, f32)>, - ag: &Option<(&str, usize, f32)>, - ext: &'a CommandExt, -) -> (Vec>, Status) { - let mut metrics: Vec = Vec::new(); - let mut status = Status::Ok; - match ag { - Some(a) => { - // The agregation is located in first place - if a.1 == 0 { - let w = &ext.warning_agregation; - let c = &ext.critical_agregation; - let current_status = - compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation); - metrics.push(Metric { - name: a.0.to_string(), - value: a.2, - warning: w, - critical: c, - status: current_status, - agregated: true, - }); - status = worst(current_status, status); - } - } - None => (), - } - values.iter().enumerate().for_each(|(i, v)| { - let current_status = compute_status(v.1, &ext.warning_core, &ext.critical_core); - metrics.push(Metric { - name: values[i].0.clone(), - value: v.1, - warning: &ext.warning_core, - critical: &ext.critical_core, - status: current_status, - agregated: false, - }); - status = worst(current_status, status); - }); - match ag { - Some(a) => { - if a.1 > 0 { - let current_status = - compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation); - metrics.push(Metric { - name: a.0.to_string(), - value: a.2, - warning: &ext.warning_agregation, - critical: &ext.critical_agregation, - status: current_status, - agregated: true, - }); - status = worst(current_status, status); - } - } - None => (), - } - (metrics, status) -} +//fn build_metrics<'a>( +// values: &Vec<(String, f32)>, +// ag: &Option<(&str, usize, f32)>, +// ext: &'a CommandExt, +//) -> (Vec>, Status) { +// let mut metrics: Vec = Vec::new(); +// let mut status = Status::Ok; +// match ag { +// Some(a) => { +// // The agregation is located in first place +// if a.1 == 0 { +// let w = &ext.warning_agregation; +// let c = &ext.critical_agregation; +// let current_status = +// compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation); +// metrics.push(Metric { +// name: a.0.to_string(), +// value: a.2, +// warning: w, +// critical: c, +// status: current_status, +// agregated: true, +// }); +// status = worst(current_status, status); +// } +// } +// None => (), +// } +// values.iter().enumerate().for_each(|(i, v)| { +// let current_status = compute_status(v.1, &ext.warning_core, &ext.critical_core); +// metrics.push(Metric { +// name: values[i].0.clone(), +// value: v.1, +// warning: &ext.warning_core, +// critical: &ext.critical_core, +// status: current_status, +// agregated: false, +// }); +// status = worst(current_status, status); +// }); +// match ag { +// Some(a) => { +// if a.1 > 0 { +// let current_status = +// compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation); +// metrics.push(Metric { +// name: a.0.to_string(), +// value: a.2, +// warning: &ext.warning_agregation, +// critical: &ext.critical_agregation, +// status: current_status, +// agregated: true, +// }); +// status = worst(current_status, status); +// } +// } +// None => (), +// } +// (metrics, status) +//} impl Command { pub fn execute( @@ -205,193 +178,197 @@ impl Command { community: &str, ext: &CommandExt, ) -> CmdResult { - let mut agregation = ("", 0, Operation::None); - let mut res: Option<(&str, SnmpResult)> = None; - for (idx, entry) in self.leaf.entries.iter().enumerate() { - match entry { - Entry::Agregation(op) => { - agregation = (&op.name, idx, op.op); - } - Entry::Query(query) => match query.query { - QueryType::Walk => { - res = Some(( - &query.name, - r_snmp_bulk_walk(target, version, community, &query.oid), - )); - } - }, - } - } - match res { - Some(r) => { - let mut values: Vec<(String, f32)> = Vec::new(); - let mut idx = 0; - r.1.variables.iter().for_each(|v| { - let label = r.0.replace("{idx}", &idx.to_string()); - values.push((label, v.value.parse().unwrap())); - idx += 1; - }); - let count = values.len(); - let ag = match agregation.2 { - Operation::Average => { - let sum: f32 = values.iter().map(|(_, v)| v).sum(); - let avg = sum / values.len() as f32; - Some((agregation.0, agregation.1, avg)) - } - _ => None, - }; - let (metrics, status) = build_metrics(&values, &ag, &ext); - let output = self.build_output(count, status, &metrics, &ag, &ext); - return CmdResult { status, output }; - } - None => { - return CmdResult { - status: Status::Unknown, - output: "No result".to_string(), - }; - } +// let mut agregation = ("", 0, Operation::None); +// let mut res: Option<(&str, SnmpResult)> = None; +// for (idx, entry) in self.leaf.entries.iter().enumerate() { +// match entry { +// Entry::Agregation(op) => { +// agregation = (&op.name, idx, op.op); +// } +// Entry::Query(query) => match query.query { +// QueryType::Walk => { +// res = Some(( +// &query.name, +// r_snmp_bulk_walk(target, version, community, &query.oid), +// )); +// } +// }, +// } +// } +// match res { +// Some(r) => { +// let mut values: Vec<(String, f32)> = Vec::new(); +// let mut idx = 0; +// r.1.variables.iter().for_each(|v| { +// let label = r.0.replace("{idx}", &idx.to_string()); +// values.push((label, v.value.parse().unwrap())); +// idx += 1; +// }); +// let count = values.len(); +// let ag = match agregation.2 { +// Operation::Average => { +// let sum: f32 = values.iter().map(|(_, v)| v).sum(); +// let avg = sum / values.len() as f32; +// Some((agregation.0, agregation.1, avg)) +// } +// _ => None, +// }; +// let (metrics, status) = build_metrics(&values, &ag, &ext); +// let output = self.build_output(count, status, &metrics, &ag, &ext); +// return CmdResult { status, output }; +// } +// None => { +// return CmdResult { +// status: Status::Unknown, +// output: "No result".to_string(), +// }; +// } +// } + CmdResult { + status: Status::Unknown, + output: "No result".to_string(), } } - fn build_output( - &self, - count: usize, - status: Status, - metrics: &Vec, - ag: &Option<(&str, usize, f32)>, - ext: &CommandExt, - ) -> String { - let no_threshold = ext.warning_core.is_none() - && ext.critical_core.is_none() - && ext.warning_agregation.is_none() - && ext.critical_agregation.is_none(); - let write_details = - no_threshold || (ext.warning_core.is_some() || ext.critical_core.is_some()); - let write_agregation_details = - no_threshold || (ext.warning_agregation.is_some() || ext.critical_agregation.is_some()); - let mut output_text = "".to_string(); - let mut begun = false; - if &self.leaf.output.header != "" { - output_text = self.leaf.output.header.replace("{status}", status.as_str()); - } - for line in &self.leaf.output.text { - if line.contains("idx") { - if write_details { - // We have to iterate on metrics - let mut output_vec = (Vec::new(), Vec::new(), Vec::new()); - let mut idx = 0; - for m in metrics.iter() { - if !m.agregated { - let text = line - .replace("{idx}", idx.to_string().as_str()) - .replace("{name}", m.name.as_str()) - .replace("{value}", format!("{:.2}", m.value).as_str()) - .replace("{count}", count.to_string().as_str()); - match m.status { - Status::Ok => { - output_vec.0.push(text); - } - Status::Warning => { - output_vec.1.push(text); - } - Status::Critical => { - output_vec.2.push(text); - } - Status::Unknown => (), - } - idx += 1; - } - } - if !output_vec.2.is_empty() { - if begun { - output_text += " - "; - } else { - begun = true; - } - output_text += output_vec.2.join(" - ").as_str(); - } - if !output_vec.1.is_empty() { - if begun { - output_text += " - "; - } else { - begun = true; - } - output_text += output_vec.1.join(" - ").as_str(); - } - if !output_vec.0.is_empty() { - if begun { - output_text += " - "; - } - output_text += output_vec.0.join(" - ").as_str(); - } - } - } else { - if write_agregation_details { - match ag { - Some(a) => { - output_text += line - .replace( - format!("{{{}}}", a.0).as_str(), - format!("{:.2}", a.2).as_str(), - ) - .replace("{count}", count.to_string().as_str()) - .as_str(); - begun = true; - } - None => output_text += line, - }; - } - } - } - - let mut perfdata = " |".to_string(); - match &self.leaf.data { - Some(d) => { - metrics.iter().for_each(|m| { - perfdata += format!( - " '{}'={}{};{};{};{};{}", - m.name, - m.value, - d.uom, - match m.warning { - Some(m) => m.to_string(), - None => "".to_string(), - }, - match m.critical { - Some(m) => m.to_string(), - None => "".to_string(), - }, - match d.min { - Some(m) => m.to_string(), - None => "".to_string(), - }, - match d.max { - Some(m) => m.to_string(), - None => "".to_string(), - }, - ) - .as_str(); - }); - } - None => { - metrics.iter().for_each(|m| { - perfdata += format!( - " '{}'={};{};{}", - m.name, - m.value, - match m.warning { - Some(v) => v.to_string(), - None => "".to_string(), - }, - match m.critical { - Some(v) => v.to_string(), - None => "".to_string(), - } - ) - .as_str(); - }); - } - }; - output_text + &perfdata - } +// fn build_output( +// &self, +// count: usize, +// status: Status, +// metrics: &Vec, +// ag: &Option<(&str, usize, f32)>, +// ext: &CommandExt, +// ) -> String { +// let no_threshold = ext.warning_core.is_none() +// && ext.critical_core.is_none() +// && ext.warning_agregation.is_none() +// && ext.critical_agregation.is_none(); +// let write_details = +// no_threshold || (ext.warning_core.is_some() || ext.critical_core.is_some()); +// let write_agregation_details = +// no_threshold || (ext.warning_agregation.is_some() || ext.critical_agregation.is_some()); +// let mut output_text = "".to_string(); +// let mut begun = false; +// if &self.leaf.output.header != "" { +// output_text = self.leaf.output.header.replace("{status}", status.as_str()); +// } +// for line in &self.leaf.output.text { +// if line.contains("idx") { +// if write_details { +// // We have to iterate on metrics +// let mut output_vec = (Vec::new(), Vec::new(), Vec::new()); +// let mut idx = 0; +// for m in metrics.iter() { +// if !m.agregated { +// let text = line +// .replace("{idx}", idx.to_string().as_str()) +// .replace("{name}", m.name.as_str()) +// .replace("{value}", format!("{:.2}", m.value).as_str()) +// .replace("{count}", count.to_string().as_str()); +// match m.status { +// Status::Ok => { +// output_vec.0.push(text); +// } +// Status::Warning => { +// output_vec.1.push(text); +// } +// Status::Critical => { +// output_vec.2.push(text); +// } +// Status::Unknown => (), +// } +// idx += 1; +// } +// } +// if !output_vec.2.is_empty() { +// if begun { +// output_text += " - "; +// } else { +// begun = true; +// } +// output_text += output_vec.2.join(" - ").as_str(); +// } +// if !output_vec.1.is_empty() { +// if begun { +// output_text += " - "; +// } else { +// begun = true; +// } +// output_text += output_vec.1.join(" - ").as_str(); +// } +// if !output_vec.0.is_empty() { +// if begun { +// output_text += " - "; +// } +// output_text += output_vec.0.join(" - ").as_str(); +// } +// } +// } else { +// if write_agregation_details { +// match ag { +// Some(a) => { +// output_text += line +// .replace( +// format!("{{{}}}", a.0).as_str(), +// format!("{:.2}", a.2).as_str(), +// ) +// .replace("{count}", count.to_string().as_str()) +// .as_str(); +// begun = true; +// } +// None => output_text += line, +// }; +// } +// } +// } +// +// let mut perfdata = " |".to_string(); +// match &self.leaf.data { +// Some(d) => { +// metrics.iter().for_each(|m| { +// perfdata += format!( +// " '{}'={}{};{};{};{};{}", +// m.name, +// m.value, +// d.uom, +// match m.warning { +// Some(m) => m.to_string(), +// None => "".to_string(), +// }, +// match m.critical { +// Some(m) => m.to_string(), +// None => "".to_string(), +// }, +// match d.min { +// Some(m) => m.to_string(), +// None => "".to_string(), +// }, +// match d.max { +// Some(m) => m.to_string(), +// None => "".to_string(), +// }, +// ) +// .as_str(); +// }); +// } +// None => { +// metrics.iter().for_each(|m| { +// perfdata += format!( +// " '{}'={};{};{}", +// m.name, +// m.value, +// match m.warning { +// Some(v) => v.to_string(), +// None => "".to_string(), +// }, +// match m.critical { +// Some(v) => v.to_string(), +// None => "".to_string(), +// } +// ) +// .as_str(); +// }); +// } +// }; +// output_text + &perfdata +// } } diff --git a/experimental/src/main.rs b/experimental/src/main.rs index a7cef5994..4336ee435 100644 --- a/experimental/src/main.rs +++ b/experimental/src/main.rs @@ -1,4 +1,4 @@ -extern crate clap; +extern crate lexopt; extern crate lalrpop_util; extern crate log; extern crate rasn; @@ -11,8 +11,8 @@ extern crate serde_json; mod generic; mod lib; -use clap::Parser; use generic::{Command, CommandExt}; +use std::ffi::{OsString, OsStr}; use lalrpop_util::lalrpop_mod; use lib::r_snmp_get; use serde_json::Result; @@ -20,35 +20,35 @@ use std::fs; lalrpop_mod!(grammar); -#[derive(Parser, Debug)] -#[command(version, about)] +#[derive(Debug)] +//#[command(version, about)] struct Cli { /// Hostname to operate on - #[arg(long, short = 'H', default_value = "localhost")] + //#[arg(long, short = 'H', default_value = "localhost")] hostname: String, - #[arg(long, short, default_value_t = 161)] + //#[arg(long, short, default_value_t = 161)] port: u16, - #[arg(long, short = 'v', default_value = "2c")] + //#[arg(long, short = 'v', default_value = "2c")] snmp_version: String, - #[arg(long, short, default_value = "public")] + //#[arg(long, short, default_value = "public")] community: String, - #[arg(long, short)] + //#[arg(long, short)] json_conf: String, - #[arg(long, short)] + //#[arg(long, short)] warning_core: Option, - #[arg(long, short = 'C')] + //#[arg(long, short = 'C')] critical_core: Option, - #[arg(long, short = 'a')] + //#[arg(long, short = 'a')] warning_agregation: Option, - #[arg(long, short = 'b')] + //#[arg(long, short = 'b')] critical_agregation: Option, } @@ -67,19 +67,65 @@ fn json_to_command(file_name: &str) -> Result { } fn main() { - let cli = Cli::parse(); - let url = format!("{}:{}", cli.hostname, cli.port); - let cmd = json_to_command(&cli.json_conf); + use lexopt::prelude::*; + let mut parser = lexopt::Parser::from_env(); + let mut hostname = "localhost".to_string(); + let mut port = 161; + let mut json = None; + loop { + let arg = parser.next(); + match arg { + Ok(arg) => { + println!("{:?} ok", arg); + match arg { + Some(arg) => { + match arg { + Short('H') | Long("hostname") => { + hostname = parser.value().unwrap().into_string().unwrap(); + }, + Short('p') | Long("port") => { + port = parser.value().unwrap().parse::().unwrap(); + println!("port: {}", port); + }, + Short('j') | Long("json") => { + json = Some(parser.value().unwrap().into_string().unwrap()); + println!("json: {:?}", json); + }, + _ => { + println!("other"); + } + } + }, + None => { + break; + } + } + }, + Err(err) => { + println!("err: {:?}", err); + std::process::exit(3); + } + } + } + let url = format!("{}:{}", hostname, port); + + if json.is_none() { + println!("json is empty"); + std::process::exit(3); + } + + let json = json.unwrap(); + let cmd = json_to_command(&json); let cmd = cmd.unwrap(); - let ext = CommandExt { - warning_core: cli.warning_core, - critical_core: cli.critical_core, - warning_agregation: cli.warning_agregation, - critical_agregation: cli.critical_agregation, - }; - let result = cmd.execute(&url, &cli.snmp_version, &cli.community, &ext); - println!("{}", result.output); - std::process::exit(result.status as i32); + //let ext = CommandExt { + // warning_core: cli.warning_core, + // critical_core: cli.critical_core, + // warning_agregation: cli.warning_agregation, + // critical_agregation: cli.critical_agregation, + //}; + //let result = cmd.execute(&url, &cli.snmp_version, &cli.community, &ext); + //println!("{}", result.output); + //std::process::exit(result.status as i32); } mod Test {