i want that filter table bs to be Going Away. restful? idk. we speak Devices now.
This commit is contained in:
+2
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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,
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user