cli refactor and more tracing
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, instrument};
|
||||
use wakey_core::InterfaceSummary;
|
||||
|
||||
/// Return interface names only.
|
||||
@@ -9,16 +10,22 @@ pub async fn list_interfaces() -> Result<Vec<String>> {
|
||||
}
|
||||
|
||||
/// Return condensed interface summaries useful for CLI and wake routing.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_interface_summaries() -> Result<Vec<InterfaceSummary>> {
|
||||
wakey_linux::devices::list_interface_summaries().await
|
||||
let summaries = wakey_linux::devices::list_interface_summaries().await?;
|
||||
debug!(count = summaries.len(), "loaded interface summaries");
|
||||
Ok(summaries)
|
||||
}
|
||||
|
||||
/// Return one named interface summary when present.
|
||||
#[instrument(skip_all, fields(ifname = name))]
|
||||
pub async fn get_interface_summary(name: &str) -> Result<Option<InterfaceSummary>> {
|
||||
Ok(get_interface_summaries()
|
||||
let summary = get_interface_summaries()
|
||||
.await?
|
||||
.into_iter()
|
||||
.find(|iface| iface.ifname == name))
|
||||
.find(|iface| iface.ifname == name);
|
||||
debug!(found = summary.is_some(), "resolved interface summary");
|
||||
Ok(summary)
|
||||
}
|
||||
|
||||
/// Resolve a hostname through the local resolver and collect all returned IPs.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use tracing::{debug, instrument};
|
||||
use wakey_core::{Device, DeviceQuery, NeighborEntry, Presence, Status};
|
||||
|
||||
use crate::service::inventory::inventory;
|
||||
@@ -11,13 +12,15 @@ pub type StatusResponse = Status<NeighborEntry>;
|
||||
///
|
||||
/// This keeps the old status response shape alive while the underlying model is
|
||||
/// increasingly device-centered.
|
||||
#[instrument(skip_all, fields(name = ?query.name))]
|
||||
pub async fn get_status(query: DeviceQuery) -> Result<StatusResponse> {
|
||||
let inventory = inventory(query.clone()).await?;
|
||||
let table = inventory
|
||||
let table: Vec<NeighborEntry> = inventory
|
||||
.devices
|
||||
.iter()
|
||||
.flat_map(device_to_status_rows)
|
||||
.collect();
|
||||
debug!(rows = table.len(), devices = inventory.devices.len(), "built status response");
|
||||
Ok(Status {
|
||||
name: query.name,
|
||||
table,
|
||||
@@ -26,6 +29,7 @@ pub async fn get_status(query: DeviceQuery) -> Result<StatusResponse> {
|
||||
}
|
||||
|
||||
/// Convenience wrapper around [`get_status`] for free-form user input.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_status_for_input(input: impl Into<String>) -> Result<StatusResponse> {
|
||||
let query = resolve_query(input).await?;
|
||||
get_status(query).await
|
||||
|
||||
+12
-2
@@ -1,20 +1,24 @@
|
||||
use anyhow::{Context, Result};
|
||||
use macaddr::MacAddr;
|
||||
use std::net::IpAddr;
|
||||
use tracing::{debug, instrument};
|
||||
use wakey_core::{InterfaceSummary, WakeResult, WakeTarget};
|
||||
|
||||
use crate::service::interfaces::get_interface_summaries;
|
||||
use crate::service::inventory::resolve_devices;
|
||||
|
||||
/// Send Wake-on-LAN packets for already-concrete wake targets.
|
||||
#[instrument(skip_all, fields(targets = targets.len()))]
|
||||
pub async fn wake_targets(targets: Vec<WakeTarget>) -> Result<WakeResult> {
|
||||
let result = wakey_linux::wake::wake_many(targets)
|
||||
.await
|
||||
.context("failed to send wake packets")?;
|
||||
debug!(results = result.len(), "wake packets sent");
|
||||
Ok(WakeResult { result })
|
||||
}
|
||||
|
||||
/// Resolve free-form input into wake targets and send the packets.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn wake_from_query(input: impl Into<String>) -> Result<WakeResult> {
|
||||
let targets = resolve_wake_targets(input).await?;
|
||||
wake_targets(targets).await
|
||||
@@ -23,12 +27,14 @@ pub async fn wake_from_query(input: impl Into<String>) -> Result<WakeResult> {
|
||||
/// Build broadcast wake targets for every broadcast-capable interface.
|
||||
///
|
||||
/// This is used by explicit manual wake mode when only a MAC address is supplied.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn broadcast_wake_targets(mac: MacAddr) -> Result<Vec<WakeTarget>> {
|
||||
let interfaces = get_interface_summaries().await?;
|
||||
broadcast_wake_targets_from_interfaces(&interfaces, mac)
|
||||
}
|
||||
|
||||
/// Wake a device explicitly by MAC, optionally targeting a specific IP/broadcast.
|
||||
#[instrument(skip_all, fields(has_ip = ip.is_some()))]
|
||||
pub async fn wake_explicit(mac: MacAddr, ip: Option<IpAddr>) -> Result<WakeResult> {
|
||||
let targets = match ip {
|
||||
Some(ip) => explicit_wake_targets_for_ip(mac, ip),
|
||||
@@ -41,9 +47,10 @@ pub async fn wake_explicit(mac: MacAddr, ip: Option<IpAddr>) -> Result<WakeResul
|
||||
///
|
||||
/// The current resolution strategy fans out one wake target per resolved device IP,
|
||||
/// using the first known MAC address for that device.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn resolve_wake_targets(input: impl Into<String>) -> Result<Vec<WakeTarget>> {
|
||||
let devices = resolve_devices(input).await?;
|
||||
Ok(devices
|
||||
let targets: Vec<WakeTarget> = devices
|
||||
.into_iter()
|
||||
.flat_map(|device| {
|
||||
let mac = device.macs.first().copied();
|
||||
@@ -52,7 +59,9 @@ pub async fn resolve_wake_targets(input: impl Into<String>) -> Result<Vec<WakeTa
|
||||
.into_iter()
|
||||
.map(move |ip| WakeTarget { ip: Some(ip), mac })
|
||||
})
|
||||
.collect())
|
||||
.collect();
|
||||
debug!(targets = targets.len(), "resolved wake targets");
|
||||
Ok(targets)
|
||||
}
|
||||
|
||||
fn explicit_wake_targets_for_ip(mac: MacAddr, ip: IpAddr) -> Vec<WakeTarget> {
|
||||
@@ -80,6 +89,7 @@ fn broadcast_wake_targets_from_interfaces(
|
||||
anyhow::bail!("no broadcast-capable interfaces found");
|
||||
}
|
||||
|
||||
debug!(targets = targets.len(), interfaces = interfaces.len(), "built broadcast wake targets");
|
||||
Ok(targets)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user