From b6f86848483d533562c0e00aadb483713ec6f25c Mon Sep 17 00:00:00 2001 From: David Boucher Date: Wed, 14 May 2025 09:01:52 +0200 Subject: [PATCH] fix(generic-snmp): error management improved, I think we can find better --- experimental/src/generic/error.rs | 31 ++++++++++--------------- experimental/src/generic/mod.rs | 22 +++++++++--------- experimental/src/main.rs | 38 ++++++++++++++----------------- 3 files changed, 40 insertions(+), 51 deletions(-) diff --git a/experimental/src/generic/error.rs b/experimental/src/generic/error.rs index 2dba73201..a5a48c881 100644 --- a/experimental/src/generic/error.rs +++ b/experimental/src/generic/error.rs @@ -1,7 +1,9 @@ +use serde_json::Error as JsonError; use snafu::prelude::*; -use std::{fs, io, path::PathBuf}; +use std::path::PathBuf; #[derive(Debug, Snafu)] +#[snafu(visibility(pub))] pub enum Error { #[snafu(display( "Threshold: This syntax is a shortcut of '0:{}', so {} must be greater than 0.", @@ -17,26 +19,17 @@ pub enum Error { ))] BadThresholdRange { start: f64, end: f64 }, - #[snafu(display("Threshold: Unable to read configuration from {}", path.display()))] - ReadConfiguration { source: io::Error, path: PathBuf }, - - #[snafu(display("Threshold: Threshold not of the form '[@]start:end'"))] + #[snafu(display("Threshold: The threshold syntax must follow '[@]start:end'"))] BadThreshold, - #[snafu(display("Unable to write result to {}", path.display()))] - WriteResult { source: io::Error, path: PathBuf }, + #[snafu(display("Json: Failed to parse JSON: {}", message))] + JsonParse { message: String }, + + #[snafu(display("Json: Unable to read the JSON file '{}'", path.display()))] + JsonRead { + source: std::io::Error, + path: PathBuf, + }, } pub type Result = std::result::Result; - -fn process_data() -> Result<()> { - let path = "config.toml"; - let configuration = fs::read_to_string(path).context(ReadConfigurationSnafu { path })?; - let path = unpack_config(&configuration); - fs::write(&path, b"My complex calculation").context(WriteResultSnafu { path })?; - Ok(()) -} - -fn unpack_config(data: &str) -> &str { - "/some/path/that/does/not/exist" -} diff --git a/experimental/src/generic/mod.rs b/experimental/src/generic/mod.rs index 45c9ba1d6..04392f2d5 100644 --- a/experimental/src/generic/mod.rs +++ b/experimental/src/generic/mod.rs @@ -176,7 +176,7 @@ impl Command { version: &str, community: &str, //ext: &CommandExt, - ) -> CmdResult { + ) -> Result { let mut to_get = Vec::new(); let mut get_name = Vec::new(); let mut collect = Vec::new(); @@ -251,7 +251,7 @@ impl Command { panic!("A label must be a string"); } }; - let status = compute_status(*item, &metric.warning, &metric.critical); + let status = compute_status(*item, &metric.warning, &metric.critical)?; let w = match metric.warning { Some(ref w) => Some(w.as_str()), None => None, @@ -267,7 +267,7 @@ impl Command { max: compute_threshold(i, &max), warning: w, critical: c, - status: status.unwrap(), + status, }; trace!("New metric '{}' with value {:?}", m.name, m.value); metrics.push(m); @@ -284,7 +284,7 @@ impl Command { res } }; - let status = compute_status(*s, &metric.warning, &metric.critical); + let status = compute_status(*s, &metric.warning, &metric.critical)?; let w = match metric.warning { Some(ref w) => Some(w.as_str()), None => None, @@ -300,7 +300,7 @@ impl Command { max: compute_threshold(0, &max), warning: w, critical: c, - status: status.unwrap(), + status, }; trace!("New metric '{}' with value {:?}", m.name, m.value); metrics.push(m); @@ -360,7 +360,7 @@ impl Command { res } }; - let status = compute_status(item, &metric.warning, &metric.critical); + let status = compute_status(item, &metric.warning, &metric.critical)?; let w = match metric.warning { Some(ref w) => Some(w.as_str()), None => None, @@ -376,7 +376,7 @@ impl Command { max, warning: w, critical: c, - status: status.unwrap(), + status, }; trace!("New metric '{}' with value {:?}", m.name, m.value); metrics.push(m); @@ -384,7 +384,7 @@ impl Command { } ExprResult::Number(s) => { let name = &metric.name; - let status = compute_status(s, &metric.warning, &metric.critical); + let status = compute_status(s, &metric.warning, &metric.critical)?; let w = match metric.warning { Some(ref w) => Some(w.as_str()), None => None, @@ -400,7 +400,7 @@ impl Command { max, warning: w, critical: c, - status: status.unwrap(), + status, }; trace!("New metric '{}' with value {:?}", m.name, m.value); metrics.push(m); @@ -412,9 +412,9 @@ impl Command { trace!("collect: {:#?}", collect); println!("metrics: {:#?}", metrics); - CmdResult { + Ok(CmdResult { status: Status::Unknown, output: "No result".to_string(), - } + }) } } diff --git a/experimental/src/main.rs b/experimental/src/main.rs index 8af0633b5..d1dd5678d 100644 --- a/experimental/src/main.rs +++ b/experimental/src/main.rs @@ -14,30 +14,32 @@ mod compute; mod generic; mod snmp; +use generic::error::*; use generic::Command; use lalrpop_util::lalrpop_mod; use lexopt::Arg; use log::{debug, trace}; -use serde_json::Result; +use snafu::ResultExt; use std::fs; lalrpop_mod!(grammar); -fn json_to_command(file_name: &str) -> Result { +fn json_to_command(file_name: &str) -> Result { // Transform content of the file into a string - let contents = match fs::read_to_string(file_name) { - Ok(ret) => ret, - Err(err) => { - println!("erreur: {}", err); - std::process::exit(3); - } - }; + let contents = fs::read_to_string(file_name).context(JsonReadSnafu { path: file_name })?; - let module: Result = serde_json::from_str(&contents.as_str()); - module + let content = contents.as_str(); + + let module: serde_json::Result = serde_json::from_str(content); + match module { + Ok(c) => Ok(c), + Err(err) => Err(Error::JsonParse { + message: err.to_string(), + }), + } } -fn main() { +fn main() -> Result<(), Error> { env_logger::init(); use lexopt::prelude::*; @@ -64,14 +66,7 @@ fn main() { let json = Some(parser.value().unwrap().into_string().unwrap()); let json = json.unwrap(); trace!("json: {:?}", json); - let res_cmd = json_to_command(&json); - cmd = Some(match res_cmd { - Ok(c) => c, - Err(err) => { - println!("json_to_command error: {:?}", err); - std::process::exit(3); - } - }); + cmd = Some(json_to_command(&json)?); } Short('v') | Long("snmp-version") => { snmp_version = parser.value().unwrap().into_string().unwrap(); @@ -124,7 +119,7 @@ fn main() { let url = format!("{}:{}", hostname, port); let result = match cmd { - Some(ref cmd) => cmd.execute(&url, &snmp_version, &snmp_community), + Some(ref cmd) => cmd.execute(&url, &snmp_version, &snmp_community)?, None => { println!("json is empty"); std::process::exit(3); @@ -133,4 +128,5 @@ fn main() { //println!("{}", result.output); //std::process::exit(result.status as i32); + Ok(()) }