1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
//! Config data for a munin plugin
// We do not want to write unsafe code
#![forbid(unsafe_code)]
use fastrand;
use log::trace;
use std::{
env,
iter::repeat_with,
path::{Path, PathBuf},
};
/// Plugin configuration.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Config {
/// The name of the plugin.
///
/// Default is "Simple munin plugin in Rust"
pub plugin_name: String,
/// Plugins state directory
///
/// Fallback to /tmp if environment variable MUNIN_PLUGSTATE is
/// not set.
pub plugin_statedir: PathBuf,
/// Cachefile for the plugin
///
/// Plugins that daemonize and continuously fetch data need to
/// write them somewhere, so that the
/// [MuninPlugin::fetch](super::MuninPlugin::fetch) function can
/// output them. The default is a combination of
/// [Config::plugin_statedir] and a random string, with _munin_ and
/// _value_ added, in [std::format!] syntax: `"{}.munin.{}.value",
/// [Config::plugin_statedir], randomstring`.
pub plugin_cache: PathBuf,
/// Does munin support dirtyconfig? (Send data after sending config)
///
/// Checks MUNIN_CAP_DIRTYCONFIG environment variable, if set to 1,
/// this is true, otherwise false.
pub dirtyconfig: bool,
/// Does this plugin need to run in background, continuously fetching data?
///
/// Default to false
pub daemonize: bool,
/// If plugin uses daemonize, whats the pidfile name?
///
/// Defaults to [Config::plugin_statedir] plus "munin-plugin.pid", using
/// [Config::new] will set it to
/// [Config::plugin_statedir]/[Config::plugin_name].pid
pub pidfile: PathBuf,
/// Size of buffer for BufWriter for [MuninPlugin::config](super::MuninPlugin::config).
///
/// Defaults to 8192, but if the plugin outputs huge munin
/// configuration (trivial with multigraph plugins), you may want
/// to increase this.
pub cfgsize: usize,
/// Size of buffer for BufWriter for [MuninPlugin::fetch](super::MuninPlugin::fetch).
///
/// Defaults to 8192, but if the plugin outputs large datasets, it
/// is useful to increase this.
pub fetchsize: usize,
}
impl Config {
/// Create a new Config with defined plugin_name, also setting
/// [Config::pidfile] and [Config::plugin_cache] to a sensible
/// value using the [Config::plugin_name].
///
/// # Examples
///
/// ```
/// # use munin_plugin::config::Config;
/// let config = Config::new(String::from("great-plugin"));
/// println!("My pidfile is {:?}", config.pidfile);
/// ```
pub fn new(plugin_name: String) -> Self {
trace!("Creating new config for plugin {plugin_name}");
let pd = plugin_name.clone();
let mut cfg = Self {
plugin_name,
..Default::default()
};
cfg.pidfile = cfg.plugin_statedir.join(format!("{}.pid", pd));
cfg.plugin_cache = cfg.plugin_statedir.join(format!("munin.{}.value", pd));
cfg
}
}
/// Useful defaults, if possible based on munin environment.
impl Default for Config {
/// Set default values, try to read munin environment variables to
/// fill [Config::plugin_statedir] and [Config::dirtyconfig].
/// [Config::plugin_statedir] falls back to _/tmp_ if no munin
/// environment variables are present.
fn default() -> Self {
let statedir =
PathBuf::from(env::var("MUNIN_PLUGSTATE").unwrap_or_else(|_| String::from("/tmp")));
let insert: String = repeat_with(fastrand::alphanumeric).take(10).collect();
let cachename = Path::new(&statedir).join(format!("munin.{}.value", insert));
Self {
plugin_name: String::from("Simple munin plugin in Rust"),
plugin_statedir: statedir.clone(),
plugin_cache: cachename,
dirtyconfig: match env::var("MUNIN_CAP_DIRTYCONFIG") {
Ok(val) => val.eq(&"1"),
Err(_) => false,
},
daemonize: false,
pidfile: statedir.join("munin-plugin.pid"),
cfgsize: 8192,
fetchsize: 8192,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_modconfig() {
// Whole set of defaults
let config = Config {
..Default::default()
};
assert_eq!(
config.plugin_name,
String::from("Simple munin plugin in Rust")
);
// Use defaults (except for name)
let mut config2 = Config {
plugin_name: String::from("Lala"),
..Default::default()
};
// Is plugin name as given?
assert_eq!(config2.plugin_name, String::from("Lala"));
// Defaults as expected?
assert!(!config2.daemonize);
assert_eq!(config2.fetchsize, 8192);
config2.pidfile = PathBuf::new();
config2.pidfile.push(&config2.plugin_statedir);
config2.pidfile.push(String::from("Lala.pid"));
let config3 = Config::new(String::from("Lala"));
// At this point, the plugin_cache should be different
assert_ne!(config2, config3);
config2.plugin_cache = config2.plugin_statedir.join("munin.Lala.value");
assert_eq!(config2, config3);
}
}