mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-01 21:13:09 +00:00
* add with_about for echo, server, and auth * update for feedback * finish (most) remaining command documentation * update comments after additional clarification * add expanded_api descriptions * add comments for action_api * add comments for remaining apis * add comment for package-rebuild * fix build errors * missed one with_about * add context to git-info subcommands * remove context from git-info subcommands * Make git-info from_fns generic over context * make version::git_info generic over the context * try removing generics from subcommand and version::git_info * try adding a closure with context * Updates for reviewer feedback
100 lines
2.8 KiB
Rust
100 lines
2.8 KiB
Rust
use std::collections::{BTreeMap, BTreeSet};
|
|
use std::net::IpAddr;
|
|
|
|
use clap::Parser;
|
|
use futures::TryStreamExt;
|
|
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
|
|
use serde::{Deserialize, Serialize};
|
|
use tokio::sync::RwLock;
|
|
use ts_rs::TS;
|
|
|
|
use crate::context::{CliContext, RpcContext};
|
|
use crate::db::model::public::IpInfo;
|
|
use crate::net::utils::{iface_is_physical, list_interfaces};
|
|
use crate::prelude::*;
|
|
use crate::Error;
|
|
|
|
lazy_static::lazy_static! {
|
|
static ref CACHED_IPS: RwLock<BTreeSet<IpAddr>> = RwLock::new(BTreeSet::new());
|
|
}
|
|
|
|
async fn _ips() -> Result<BTreeSet<IpAddr>, Error> {
|
|
Ok(init_ips()
|
|
.await?
|
|
.values()
|
|
.flat_map(|i| {
|
|
std::iter::empty()
|
|
.chain(i.ipv4.map(IpAddr::from))
|
|
.chain(i.ipv6.map(IpAddr::from))
|
|
})
|
|
.collect())
|
|
}
|
|
|
|
pub async fn ips() -> Result<BTreeSet<IpAddr>, Error> {
|
|
let ips = CACHED_IPS.read().await.clone();
|
|
if !ips.is_empty() {
|
|
return Ok(ips);
|
|
}
|
|
let ips = _ips().await?;
|
|
*CACHED_IPS.write().await = ips.clone();
|
|
Ok(ips)
|
|
}
|
|
|
|
pub async fn init_ips() -> Result<BTreeMap<String, IpInfo>, Error> {
|
|
let mut res = BTreeMap::new();
|
|
let mut ifaces = list_interfaces();
|
|
while let Some(iface) = ifaces.try_next().await? {
|
|
if iface_is_physical(&iface).await {
|
|
let ip_info = IpInfo::for_interface(&iface).await?;
|
|
res.insert(iface, ip_info);
|
|
}
|
|
}
|
|
Ok(res)
|
|
}
|
|
|
|
// #[command(subcommands(update))]
|
|
pub fn dhcp<C: Context>() -> ParentHandler<C> {
|
|
ParentHandler::new().subcommand(
|
|
"update",
|
|
from_fn_async::<_, _, (), Error, (RpcContext, UpdateParams)>(update)
|
|
.no_display()
|
|
.with_about("Update IP assigned by dhcp")
|
|
.with_call_remote::<CliContext>(),
|
|
)
|
|
}
|
|
#[derive(Deserialize, Serialize, Parser, TS)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[command(rename_all = "kebab-case")]
|
|
pub struct UpdateParams {
|
|
interface: String,
|
|
}
|
|
|
|
pub async fn update(
|
|
ctx: RpcContext,
|
|
UpdateParams { interface }: UpdateParams,
|
|
) -> Result<(), Error> {
|
|
if iface_is_physical(&interface).await {
|
|
let ip_info = IpInfo::for_interface(&interface).await?;
|
|
ctx.db
|
|
.mutate(|db| {
|
|
db.as_public_mut()
|
|
.as_server_info_mut()
|
|
.as_ip_info_mut()
|
|
.insert(&interface, &ip_info)
|
|
})
|
|
.await?;
|
|
|
|
let mut cached = CACHED_IPS.write().await;
|
|
if cached.is_empty() {
|
|
*cached = _ips().await?;
|
|
} else {
|
|
cached.extend(
|
|
std::iter::empty()
|
|
.chain(ip_info.ipv4.map(IpAddr::from))
|
|
.chain(ip_info.ipv6.map(IpAddr::from)),
|
|
);
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|