The start of greatness is hella rocky
This commit is contained in:
1 parent
93a88741f9
commit
65111d7895
20 files changed
+2225
-37
No files matched your search
@@ -0,0 +1,114 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::protocol::{
|
||||
AgentCommand, CommandResult, DevsRequest, InventoryRequest, LeasesRequest, StatusRequest,
|
||||
WakeRequest,
|
||||
};
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn dispatch_command(command: AgentCommand) -> Result<CommandResult> {
|
||||
match command {
|
||||
AgentCommand::Status(req) => dispatch_status(req).await,
|
||||
AgentCommand::Leases(req) => dispatch_leases(req).await,
|
||||
AgentCommand::Devs(req) => dispatch_devs(req).await,
|
||||
AgentCommand::Inventory(req) => dispatch_inventory(req).await,
|
||||
AgentCommand::Wake(req) => dispatch_wake(req).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn dispatch_status(req: StatusRequest) -> Result<CommandResult> {
|
||||
let query = req.into_device_query();
|
||||
let status = if query.name.is_some()
|
||||
&& query.filter.ips.is_empty()
|
||||
&& query.filter.devs.is_empty()
|
||||
&& query.filter.nuds.is_empty()
|
||||
&& query.filter.macs.is_empty()
|
||||
{
|
||||
wakey::get_status_for_input(query.name.clone().unwrap_or_default()).await?
|
||||
} else {
|
||||
wakey::get_status(query).await?
|
||||
};
|
||||
debug!(rows = status.table.len(), "dispatched status command");
|
||||
Ok(CommandResult::Status(status))
|
||||
}
|
||||
|
||||
async fn dispatch_leases(req: LeasesRequest) -> Result<CommandResult> {
|
||||
let leases = wakey::get_leases(wakey_core::LeaseQuery {
|
||||
include_state: req.include_state,
|
||||
})
|
||||
.await?;
|
||||
Ok(CommandResult::Leases(leases))
|
||||
}
|
||||
|
||||
async fn dispatch_devs(req: DevsRequest) -> Result<CommandResult> {
|
||||
let mut devs = if let Some(name) = &req.dev {
|
||||
wakey::get_interface_summary(name).await?.into_iter().collect()
|
||||
} else {
|
||||
wakey::get_interface_summaries().await?
|
||||
};
|
||||
if req.up_only {
|
||||
devs.retain(|dev| dev.operstate == "up");
|
||||
}
|
||||
Ok(CommandResult::Devs(devs))
|
||||
}
|
||||
|
||||
async fn dispatch_inventory(req: InventoryRequest) -> Result<CommandResult> {
|
||||
let inventory = wakey::inventory(req.into_device_query()).await?;
|
||||
Ok(CommandResult::Inventory(inventory))
|
||||
}
|
||||
|
||||
async fn dispatch_wake(req: WakeRequest) -> Result<CommandResult> {
|
||||
validate_wake_request(&req)?;
|
||||
let result = match (req.query, req.mac, req.ip) {
|
||||
(Some(query), None, None) => wakey::wake_from_query(query).await?,
|
||||
(None, Some(mac), ip) => wakey::wake_explicit(mac, ip).await?,
|
||||
_ => unreachable!("wake request validated before dispatch"),
|
||||
};
|
||||
Ok(CommandResult::Wake(result))
|
||||
}
|
||||
|
||||
pub fn validate_wake_request(req: &WakeRequest) -> Result<()> {
|
||||
let has_query = req.query.is_some();
|
||||
let has_mac = req.mac.is_some();
|
||||
let has_ip = req.ip.is_some();
|
||||
|
||||
if has_ip && !has_mac {
|
||||
anyhow::bail!("wake request `ip` requires `mac`");
|
||||
}
|
||||
if has_query && (has_mac || has_ip) {
|
||||
anyhow::bail!("wake query mode and explicit mode are mutually exclusive");
|
||||
}
|
||||
if !has_query && !has_mac {
|
||||
anyhow::bail!("wake request requires either `query` or `mac`");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::protocol::WakeRequest;
|
||||
|
||||
#[test]
|
||||
fn wake_rejects_ip_without_mac() {
|
||||
let err = validate_wake_request(&WakeRequest {
|
||||
query: None,
|
||||
mac: None,
|
||||
ip: Some("192.168.1.1".parse().expect("ip")),
|
||||
})
|
||||
.expect_err("should reject");
|
||||
assert!(err.to_string().contains("requires `mac`"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wake_rejects_mixed_mode() {
|
||||
let err = validate_wake_request(&WakeRequest {
|
||||
query: Some("pc".into()),
|
||||
mac: Some("aa:bb:cc:dd:ee:ff".parse().expect("mac")),
|
||||
ip: None,
|
||||
})
|
||||
.expect_err("should reject");
|
||||
assert!(err.to_string().contains("mutually exclusive"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user