M4: fetch mode, cleanup and documentation

- --fetch with a Jinja-subset renderer and the shipped templates
- clippy clean, cargo fmt, all tests green
- README status and differential testing instructions
This commit is contained in:
glances-rs
2026-10-09 23:59:26 +00:00
parent cb22e53aa6
commit 6819ce4e18
47 changed files with 4145 additions and 935 deletions
+124 -36
View File
@@ -27,37 +27,102 @@ impl Engine {
// Registration order mirrors the alphabetical plugin loading of the
// Python implementation (in particular processcount runs before
// processlist and programlist).
plugins.insert("amps".to_string(), Box::new(AmpsPlugin::new(&config, &args)));
plugins.insert("core".to_string(), Box::new(CorePlugin::new(&config, &args)));
plugins.insert(
"amps".to_string(),
Box::new(AmpsPlugin::new(&config, &args)),
);
plugins.insert(
"core".to_string(),
Box::new(CorePlugin::new(&config, &args)),
);
plugins.insert("cpu".to_string(), Box::new(CpuPlugin::new(&config, &args)));
plugins.insert("diskio".to_string(), Box::new(DiskioPlugin::new(&config, &args)));
plugins.insert("folders".to_string(), Box::new(FoldersPlugin::new(&config, &args)));
plugins.insert(
"diskio".to_string(),
Box::new(DiskioPlugin::new(&config, &args)),
);
plugins.insert(
"folders".to_string(),
Box::new(FoldersPlugin::new(&config, &args)),
);
plugins.insert("fs".to_string(), Box::new(FsPlugin::new(&config, &args)));
plugins.insert("ip".to_string(), Box::new(IpPlugin::new(&config, &args)));
plugins.insert("irq".to_string(), Box::new(IrqPlugin::new(&config, &args)));
plugins.insert("load".to_string(), Box::new(LoadPlugin::new(&config, &args)));
plugins.insert(
"load".to_string(),
Box::new(LoadPlugin::new(&config, &args)),
);
plugins.insert("mem".to_string(), Box::new(MemPlugin::new(&config, &args)));
plugins.insert("memswap".to_string(), Box::new(MemSwapPlugin::new(&config, &args)));
plugins.insert("network".to_string(), Box::new(NetworkPlugin::new(&config, &args)));
plugins.insert(
"memswap".to_string(),
Box::new(MemSwapPlugin::new(&config, &args)),
);
plugins.insert(
"network".to_string(),
Box::new(NetworkPlugin::new(&config, &args)),
);
plugins.insert("now".to_string(), Box::new(NowPlugin::new(&config, &args)));
plugins.insert("percpu".to_string(), Box::new(PerCpuPlugin::new(&config, &args)));
plugins.insert("ports".to_string(), Box::new(PortsPlugin::new(&config, &args)));
plugins.insert("processcount".to_string(), Box::new(ProcessCountPlugin::new(&config, &args)));
plugins.insert("processlist".to_string(), Box::new(ProcessListPlugin::new(&config, &args)));
plugins.insert("programlist".to_string(), Box::new(ProgramListPlugin::new(&config, &args)));
plugins.insert("psutilversion".to_string(), Box::new(PsutilVersionPlugin::new(&config, &args)));
plugins.insert("quicklook".to_string(), Box::new(QuicklookPlugin::new(&config, &args)));
plugins.insert("raid".to_string(), Box::new(RaidPlugin::new(&config, &args)));
plugins.insert("sensors".to_string(), Box::new(SensorsPlugin::new(&config, &args)));
plugins.insert("system".to_string(), Box::new(SystemPlugin::new(&config, &args)));
plugins.insert("uptime".to_string(), Box::new(UptimePlugin::new(&config, &args)));
plugins.insert("version".to_string(), Box::new(VersionPlugin::new(&config, &args)));
plugins.insert("wifi".to_string(), Box::new(WifiPlugin::new(&config, &args)));
plugins.insert(
"percpu".to_string(),
Box::new(PerCpuPlugin::new(&config, &args)),
);
plugins.insert(
"ports".to_string(),
Box::new(PortsPlugin::new(&config, &args)),
);
plugins.insert(
"processcount".to_string(),
Box::new(ProcessCountPlugin::new(&config, &args)),
);
plugins.insert(
"processlist".to_string(),
Box::new(ProcessListPlugin::new(&config, &args)),
);
plugins.insert(
"programlist".to_string(),
Box::new(ProgramListPlugin::new(&config, &args)),
);
plugins.insert(
"psutilversion".to_string(),
Box::new(PsutilVersionPlugin::new(&config, &args)),
);
plugins.insert(
"quicklook".to_string(),
Box::new(QuicklookPlugin::new(&config, &args)),
);
plugins.insert(
"raid".to_string(),
Box::new(RaidPlugin::new(&config, &args)),
);
plugins.insert(
"sensors".to_string(),
Box::new(SensorsPlugin::new(&config, &args)),
);
plugins.insert(
"system".to_string(),
Box::new(SystemPlugin::new(&config, &args)),
);
plugins.insert(
"uptime".to_string(),
Box::new(UptimePlugin::new(&config, &args)),
);
plugins.insert(
"version".to_string(),
Box::new(VersionPlugin::new(&config, &args)),
);
plugins.insert(
"wifi".to_string(),
Box::new(WifiPlugin::new(&config, &args)),
);
// The refresh time is set on the model, which was built with the
// command line value already.
let _ = refresh_time;
let mut engine = Self { args, config, runtime, plugins };
let mut engine = Self {
args,
config,
runtime,
plugins,
};
engine.apply_plugin_options();
engine.apply_process_options();
engine.sync_enabled();
@@ -77,11 +142,11 @@ impl Engine {
fn apply_plugin_options(&mut self) {
// Disable plugins from the configuration file.
for section in self.config.sections() {
if self.config.get_bool_value(section, "disable", false) {
if let Some(plugin) = self.plugins.get_mut(section) {
debug!("{} disabled by the configuration file", section);
plugin.set_enabled(false);
}
if self.config.get_bool_value(section, "disable", false)
&& let Some(plugin) = self.plugins.get_mut(section)
{
debug!("{} disabled by the configuration file", section);
plugin.set_enabled(false);
}
}
@@ -102,10 +167,18 @@ impl Engine {
// --disable-plugin / --enable-plugin.
let mut explicit_enable: Vec<String> = Vec::new();
if let Some(enable) = &self.args.enable_plugin {
explicit_enable = enable.split(',').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect();
explicit_enable = enable
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
}
if let Some(disable) = &self.args.disable_plugin {
let tokens: Vec<String> = disable.split(',').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect();
let tokens: Vec<String> = disable
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
if tokens.iter().any(|t| t == "all") {
for name in self.plugins.keys().cloned().collect::<Vec<_>>() {
self.plugins.get_mut(&name).unwrap().set_enabled(false);
@@ -134,12 +207,18 @@ impl Engine {
}
// Processlist needs processcount to update the shared process list.
let processcount_enabled = self.plugins.get("processcount").map(|p| p.is_enabled()).unwrap_or(false);
let processcount_enabled = self
.plugins
.get("processcount")
.map(|p| p.is_enabled())
.unwrap_or(false);
if !processcount_enabled {
for name in ["processlist", "programlist"] {
if let Some(plugin) = self.plugins.get_mut(name) {
if plugin.is_enabled() {
tracing::warn!("Processcount is disabled, so processlist (updated by processcount) is also disabled");
tracing::warn!(
"Processcount is disabled, so processlist (updated by processcount) is also disabled"
);
}
plugin.set_enabled(false);
}
@@ -210,7 +289,10 @@ impl Engine {
/// Update every enabled plugin.
pub fn update(&mut self) {
let names: Vec<String> = self.plugins.keys().cloned().collect();
let enabled: Vec<String> = names.into_iter().filter(|n| self.plugins[n].is_enabled()).collect();
let enabled: Vec<String> = names
.into_iter()
.filter(|n| self.plugins[n].is_enabled())
.collect();
self.update_plugins(&enabled);
}
@@ -222,7 +304,13 @@ impl Engine {
}
fn update_plugin(&mut self, name: &str) {
let Engine { plugins, args, config, runtime, .. } = self;
let Engine {
plugins,
args,
config,
runtime,
..
} = self;
let Some(plugin) = plugins.get_mut(name) else {
return;
};
@@ -289,10 +377,10 @@ impl Engine {
};
let mut result = serde_json::Map::new();
for name in names {
if let Some(plugin) = self.plugins.get(&name) {
if plugin.is_enabled() {
result.insert(name, plugin.stats().clone());
}
if let Some(plugin) = self.plugins.get(&name)
&& plugin.is_enabled()
{
result.insert(name, plugin.stats().clone());
}
}
result