use crate::plugin::{PluginName, ENABLED_FILE};
pub const USAGE: &str = "\
Usage: wsb plugin <command>
list the plugins enabled on this machine, and which are running
add <name> enable a plugin: it may register its services with the
daemon, and use the peer bridge
remove <name> disable it; it stops answering at once
A plugin's services are carried between paired machines over the connection
they already hold, each switched per machine and off until switched on:
`wsb peer service <peer> <plugin>.<service> on`.";
pub fn dispatch(args: &[String]) -> u8 {
let verb = args.get(2).map(String::as_str);
let rest = if args.len() > 3 { &args[3..] } else { &[] };
let result = match verb {
None | Some("list") => list(),
Some("add") => add(rest),
Some("remove") => remove(rest),
Some("help") | Some("--help") | Some("-h") => {
crate::outln!("{USAGE}");
return 0;
}
Some(other) => {
crate::errln!("wsb plugin: unknown command '{other}'\n\n{USAGE}");
return 2;
}
};
match result {
Ok(()) => 0,
Err(message) => {
crate::errln!("wsb plugin: {message}");
1
}
}
}
fn name(rest: &[String]) -> Result<PluginName, String> {
match rest {
[one] => PluginName::parse(one),
_ => Err(format!("name one plugin\n\n{USAGE}")),
}
}
fn add(rest: &[String]) -> Result<(), String> {
let plugin = name(rest)?;
let machine_dir = crate::daemon::machine_dir()?;
if crate::plugin::enable(&machine_dir, &plugin)? {
crate::outln!("enabled plugin {plugin} on this machine");
} else {
crate::outln!("plugin {plugin} was already enabled on this machine");
}
Ok(())
}
fn remove(rest: &[String]) -> Result<(), String> {
let plugin = name(rest)?;
let machine_dir = crate::daemon::machine_dir()?;
if crate::plugin::disable(&machine_dir, &plugin)? {
crate::outln!("disabled plugin {plugin}: it answers nothing from now on");
} else {
crate::outln!(
"plugin {plugin} is not enabled on this machine ({})",
machine_dir.join(ENABLED_FILE).display()
);
}
Ok(())
}
fn list() -> Result<(), String> {
let machine_dir = crate::daemon::machine_dir()?;
let enabled = crate::plugin::enabled(&machine_dir)?;
if enabled.is_empty() {
crate::outln!("no plugin is enabled on this machine; `wsb plugin add <name>` enables one");
return Ok(());
}
let running: Vec<serde_json::Value> = match crate::daemon::MachineRendezvous::read(&machine_dir)? {
None => Vec::new(),
Some(rendezvous) => {
let client = crate::daemon::Client::from_rendezvous(&rendezvous)?;
let answer: serde_json::Value = client.operator_get_json(crate::plugin::route::LIST)?;
answer["running"].as_array().cloned().unwrap_or_default()
}
};
for plugin in &enabled {
let entry = running.iter().find(|entry| entry["plugin"] == plugin.as_str());
match entry {
Some(entry) => {
let services: Vec<&str> = entry["services"]
.as_array()
.map(|services| services.iter().filter_map(|s| s.as_str()).collect())
.unwrap_or_default();
crate::outln!(
"{plugin} running (pid {}): {}",
entry["pid"],
services.join(", ")
);
}
None => crate::outln!("{plugin} enabled, not running"),
}
}
Ok(())
}