i want that filter table bs to be Going Away. restful? idk. we speak Devices now.

This commit is contained in:
lda
2026-04-14 01:07:22 +07:00 Unverified
parent 834a56d439
commit 42cdc720a3
9 changed files with 43 additions and 87 deletions
+2 -1
View File
@@ -141,6 +141,7 @@ pub async fn run(cli: Cli) -> Result<()> {
Command::Status(args) => { Command::Status(args) => {
let as_json = args.json; let as_json = args.json;
let query = status_args_to_query(args); let query = status_args_to_query(args);
let selected_name = query.name.clone();
debug!(?query, json = as_json, "dispatching status command"); debug!(?query, json = as_json, "dispatching status command");
let status = if query.name.is_some() let status = if query.name.is_some()
&& query.filter.ips.is_empty() && query.filter.ips.is_empty()
@@ -155,7 +156,7 @@ pub async fn run(cli: Cli) -> Result<()> {
if as_json { if as_json {
println!("{}", serde_json::to_string_pretty(&status)?); println!("{}", serde_json::to_string_pretty(&status)?);
} else { } else {
if let Some(name) = &status.name { if let Some(name) = &selected_name {
println!("name: {name}"); println!("name: {name}");
} }
println!("{}", table::render_status_table(&status)); println!("{}", table::render_status_table(&status));
+26 -8
View File
@@ -1,16 +1,34 @@
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use comfy_table::{Cell, ContentArrangement, Table, presets::UTF8_FULL}; use comfy_table::{Cell, ContentArrangement, Table, presets::UTF8_FULL};
use wakey_core::{DhcpLeaseWithState, InterfaceSummary, Status, WakeResult}; use wakey_core::{DeviceInventory, DhcpLeaseWithState, InterfaceSummary, WakeResult};
pub fn render_status_table(status: &Status<wakey_core::NeighborEntry>) -> Table { pub fn render_status_table(status: &DeviceInventory) -> Table {
let mut table = base_table(); let mut table = base_table();
table.set_header(vec!["IP", "MAC", "Dev", "State"]); table.set_header(vec!["Name", "IP", "MAC", "Presence", "Interfaces"]);
for row in &status.table { for row in &status.devices {
table.add_row(vec![ table.add_row(vec![
Cell::new(row.ip.to_string()), Cell::new(
Cell::new(row.mac.map(|v| v.to_string()).unwrap_or_default()), row.names
Cell::new(row.dev.clone().unwrap_or_default()), .first()
Cell::new(row.state.to_string()), .cloned()
.unwrap_or_else(|| "(unnamed)".into()),
),
Cell::new(
row.ips
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", "),
),
Cell::new(
row.macs
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", "),
),
Cell::new(format!("{:?}", row.presence)),
Cell::new(row.interfaces.join(", ")),
]); ]);
} }
table table
+4 -5
View File
@@ -2,11 +2,10 @@ pub mod service;
pub mod utils; pub mod utils;
pub use service::{ pub use service::{
StatusResponse, broadcast_wake_targets, device_to_status_rows, get_interface_summaries, StatusResponse, broadcast_wake_targets, get_interface_summaries, get_interface_summary,
get_interface_summary, get_ips, get_leases, get_status, get_status_for_input, inventory, get_ips, get_leases, get_status, get_status_for_input, inventory, leases_without_state,
leases_without_state, list_interfaces, merge_devices, query_to_device_query, resolve_devices, list_interfaces, merge_devices, query_to_device_query, resolve_devices, resolve_query,
resolve_query, resolve_selector, resolve_wake_targets, wake_explicit, wake_from_query, resolve_selector, resolve_wake_targets, wake_explicit, wake_from_query, wake_targets,
wake_targets,
}; };
#[cfg(test)] #[cfg(test)]
+1 -1
View File
@@ -9,7 +9,7 @@ pub use interfaces::{get_interface_summaries, get_interface_summary, get_ips, li
pub use inventory::{inventory, merge_devices, resolve_devices}; pub use inventory::{inventory, merge_devices, resolve_devices};
pub use leases::{get_leases, leases_without_state}; pub use leases::{get_leases, leases_without_state};
pub use query::{query_to_device_query, resolve_query, resolve_selector}; pub use query::{query_to_device_query, resolve_query, resolve_selector};
pub use status::{StatusResponse, device_to_status_rows, get_status, get_status_for_input}; pub use status::{StatusResponse, get_status, get_status_for_input};
pub use wake::{ pub use wake::{
broadcast_wake_targets, resolve_wake_targets, wake_explicit, wake_from_query, wake_targets, broadcast_wake_targets, resolve_wake_targets, wake_explicit, wake_from_query, wake_targets,
}; };
+7 -54
View File
@@ -1,35 +1,19 @@
use anyhow::Result; use anyhow::Result;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use wakey_core::{Device, DeviceQuery, NeighborEntry, Presence, Status}; use wakey_core::{DeviceInventory, DeviceQuery};
use crate::service::inventory::inventory; use crate::service::inventory::inventory;
use crate::service::query::resolve_query; use crate::service::query::resolve_query;
/// Service status payload, still expressed in terms of legacy neighbor rows. /// Service status payload expressed in terms of merged device inventory.
pub type StatusResponse = Status<NeighborEntry>; pub type StatusResponse = DeviceInventory;
/// Return status rows derived from the merged device inventory. /// Return status payload from merged device inventory.
///
/// This keeps the old status response shape alive while the underlying model is
/// increasingly device-centered.
#[instrument(skip_all, fields(name = ?query.name))] #[instrument(skip_all, fields(name = ?query.name))]
pub async fn get_status(query: DeviceQuery) -> Result<StatusResponse> { pub async fn get_status(query: DeviceQuery) -> Result<StatusResponse> {
let inventory = inventory(query.clone()).await?; let inventory = inventory(query).await?;
let table: Vec<NeighborEntry> = inventory debug!(devices = inventory.devices.len(), "built status response");
.devices Ok(inventory)
.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,
filters: query.filter,
})
} }
/// Convenience wrapper around [`get_status`] for free-form user input. /// Convenience wrapper around [`get_status`] for free-form user input.
@@ -38,34 +22,3 @@ pub async fn get_status_for_input(input: impl Into<String>) -> Result<StatusResp
let query = resolve_query(input).await?; let query = resolve_query(input).await?;
get_status(query).await get_status(query).await
} }
/// Project a device aggregate back into legacy status rows.
///
/// If the device already has neighbor rows they are reused directly; otherwise a
/// fallback row is synthesized from the best available device data.
pub fn device_to_status_rows(device: &Device) -> Vec<NeighborEntry> {
if !device.neighbors.is_empty() {
return device.neighbors.clone();
}
let fallback_mac = device.macs.first().copied();
let fallback_dev = device.interfaces.first().cloned();
let fallback_state = match device.presence {
Presence::Online => wakey_core::NeighborState::Reachable,
Presence::LikelyOnline => wakey_core::NeighborState::Stale,
Presence::Offline => wakey_core::NeighborState::Failed,
Presence::Unknown => wakey_core::NeighborState::None,
};
device
.ips
.iter()
.copied()
.map(|ip| NeighborEntry {
ip,
dev: fallback_dev.clone(),
mac: fallback_mac,
state: fallback_state,
})
.collect()
}
+1 -1
View File
@@ -31,7 +31,7 @@ async fn dispatch_status(req: StatusRequest) -> Result<CommandResult> {
} else { } else {
wakey::get_status(query).await? wakey::get_status(query).await?
}; };
debug!(rows = status.table.len(), "dispatched status command"); debug!(devices = status.devices.len(), "dispatched status command");
Ok(CommandResult::Status(status)) Ok(CommandResult::Status(status))
} }
+2 -3
View File
@@ -4,8 +4,7 @@ use std::fmt;
use std::net::IpAddr; use std::net::IpAddr;
use wakey_core::parse::mac; use wakey_core::parse::mac;
use wakey_core::{ use wakey_core::{
DeviceFilters, DeviceInventory, DeviceQuery, DhcpLeaseWithState, InterfaceSummary, DeviceFilters, DeviceInventory, DeviceQuery, DhcpLeaseWithState, InterfaceSummary, WakeResult,
NeighborEntry, Status, WakeResult,
}; };
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -174,7 +173,7 @@ pub enum AgentCommand {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(tag = "kind", rename_all = "snake_case")] #[serde(tag = "kind", rename_all = "snake_case")]
pub enum CommandResult { pub enum CommandResult {
Status(Status<NeighborEntry>), Status(DeviceInventory),
Leases { rows: Vec<DhcpLeaseWithState> }, Leases { rows: Vec<DhcpLeaseWithState> },
Devs { rows: Vec<InterfaceSummary> }, Devs { rows: Vec<InterfaceSummary> },
Inventory(DeviceInventory), Inventory(DeviceInventory),
-2
View File
@@ -3,7 +3,6 @@ mod dhcp;
mod interface; mod interface;
mod neighbor; mod neighbor;
mod query; mod query;
mod status;
mod wake; mod wake;
pub use device::{Device, DeviceId, DeviceInventory, Presence}; pub use device::{Device, DeviceId, DeviceInventory, Presence};
@@ -11,5 +10,4 @@ pub use dhcp::{DhcpLease, DhcpLeaseWithState, LeaseQuery};
pub use interface::{InterfaceAddr, InterfaceSummary}; pub use interface::{InterfaceAddr, InterfaceSummary};
pub use neighbor::{NeighborEntry, NeighborParseError, NeighborState, parse_neighbor_line}; pub use neighbor::{NeighborEntry, NeighborParseError, NeighborState, parse_neighbor_line};
pub use query::{DeviceFilters, DeviceQuery, NamePath, Query, QueryInput}; pub use query::{DeviceFilters, DeviceQuery, NamePath, Query, QueryInput};
pub use status::Status;
pub use wake::{WakeResult, WakeStatus, WakeTarget, WakeTargetResult}; pub use wake::{WakeResult, WakeStatus, WakeTarget, WakeTargetResult};
-12
View File
@@ -1,12 +0,0 @@
use serde::Serialize;
use serde_with::skip_serializing_none;
use crate::model::DeviceFilters;
#[skip_serializing_none]
#[derive(Debug, Default, Serialize)]
pub struct Status<T> {
pub name: Option<String>,
pub table: Vec<T>,
pub filters: DeviceFilters,
}