im pretty sure every subcommands use the config file

This commit is contained in:
lda
2026-04-27 04:13:50 +07:00 Verified
parent 1a259ed1cf
commit 4efa70c228
4 changed files with 86 additions and 24 deletions
+19 -1
View File
@@ -14,6 +14,10 @@ pub struct Cli {
#[arg(short = 'v', long = "verbose", action = ArgAction::Count, global = true)]
pub verbose: u8,
/// Path to the agent config file for commands that use agent config.
#[arg(long, global = true)]
pub config: Option<PathBuf>,
#[command(subcommand)]
pub command: Command,
}
@@ -28,6 +32,9 @@ pub enum Command {
InitConfig(InitConfigArgs),
/// Reload a running agent daemon by sending SIGHUP.
Reload(ReloadArgs),
/// Upload local observations to the control plane once and exit.
#[command(visible_alias = "sync")]
SyncObservations(SyncObservationsArgs),
/// Pass local hotplug observations through to the wakey CLI.
Observe(ObserveArgs),
}
@@ -76,6 +83,10 @@ pub struct InitConfigArgs {
#[arg(long)]
pub config: Option<PathBuf>,
/// Existing agent config to use as a base before applying explicit overrides.
#[arg(long)]
pub from_config: Option<PathBuf>,
/// Print config to stdout.
#[arg(long, conflicts_with = "config")]
pub stdout: bool,
@@ -104,10 +115,17 @@ pub struct ReloadArgs {
pub pid_file: PathBuf,
}
#[derive(Args)]
pub struct SyncObservationsArgs {
/// Path to the agent config file.
#[arg(long, default_value = config::DEFAULT_CONFIG_PATH)]
pub config: PathBuf,
}
#[derive(Args)]
pub struct ObserveArgs {
/// Path to the agent config file. If present, local path settings are passed through.
#[arg(long, default_value = config::DEFAULT_CONFIG_PATH)]
#[arg(long, global = true, default_value = config::DEFAULT_CONFIG_PATH)]
pub config: PathBuf,
#[command(subcommand)]
+57 -20
View File
@@ -15,13 +15,20 @@ use cli::{Cli, Command, InitConfigArgs, ObserveCommand};
async fn main() -> Result<()> {
let cli = Cli::parse();
tracing::init(cli.verbose);
let global_config = cli.config.as_deref();
match cli.command {
Command::Serve(args) => {
Command::Serve(mut args) => {
if let Some(config) = global_config {
args.config = config.to_path_buf();
}
::tracing::info!("wakey-agent command: serve");
serve::serve(args).await?
}
Command::Enroll(args) => {
Command::Enroll(mut args) => {
if let Some(config) = global_config {
args.config = config.to_path_buf();
}
let resolved_server_url = if let Some(server_url) = args.server_url.as_deref() {
server_url.to_string()
} else {
@@ -81,12 +88,34 @@ async fn main() -> Result<()> {
);
}
}
Command::InitConfig(args) => init_config(args)?,
Command::InitConfig(mut args) => {
if let Some(config) = global_config
&& args.config.is_none()
&& !args.stdout
{
args.config = Some(config.to_path_buf());
}
init_config(args)?
}
Command::Reload(args) => {
::tracing::info!(pid_file = %args.pid_file.display(), "wakey-agent command: reload");
serve::reload_daemon(&args.pid_file)?
}
Command::Observe(args) => observe(args)?,
Command::SyncObservations(mut args) => {
if let Some(config) = global_config {
args.config = config.to_path_buf();
}
::tracing::info!(config = %args.config.display(), "wakey-agent command: sync-observations");
let cfg = config::load_config(&args.config)?;
let accepted = session::sync_observations_once(&cfg).await?;
println!("observations_synced={accepted}");
}
Command::Observe(mut args) => {
if let Some(config) = global_config {
args.config = config.to_path_buf();
}
observe(args)?
}
}
Ok(())
@@ -164,24 +193,32 @@ fn init_config(args: InitConfigArgs) -> Result<()> {
);
}
let cfg = config::AgentConfig {
server_url: args
.server_url
.unwrap_or_else(|| "https://wakey.ldlda.com".to_string()),
agent_id: args
.agent_id
.unwrap_or_else(|| "REPLACE_ME_AGENT_ID".to_string()),
agent_token: args
.agent_token
.unwrap_or_else(|| "REPLACE_ME_AGENT_TOKEN".to_string()),
reconnect_base_ms: 1_000,
reconnect_max_ms: 30_000,
observation_sync_interval_seconds: 60,
dhcp_leases_path: "/tmp/dhcp.leases".into(),
mac_name_cache_path: "/tmp/wakey_mac_names.json".into(),
observation_store_path: "/tmp/wakey_observations.json".into(),
let mut cfg = if let Some(from_config) = &args.from_config {
config::load_config(from_config)?
} else {
config::AgentConfig {
server_url: "https://wakey.ldlda.com".to_string(),
agent_id: "REPLACE_ME_AGENT_ID".to_string(),
agent_token: "REPLACE_ME_AGENT_TOKEN".to_string(),
reconnect_base_ms: 1_000,
reconnect_max_ms: 30_000,
observation_sync_interval_seconds: 60,
dhcp_leases_path: "/tmp/dhcp.leases".into(),
mac_name_cache_path: "/tmp/wakey_mac_names.json".into(),
observation_store_path: "/tmp/wakey_observations.json".into(),
}
};
if let Some(server_url) = args.server_url {
cfg.server_url = server_url;
}
if let Some(agent_id) = args.agent_id {
cfg.agent_id = agent_id;
}
if let Some(agent_token) = args.agent_token {
cfg.agent_token = agent_token;
}
if let Some(path) = &args.config {
config::save_config(path, &cfg)?;
println!("config={}", path.display());
+8 -3
View File
@@ -164,13 +164,18 @@ struct AgentObservationRequest {
last_seen_unix: u64,
}
async fn send_agent_observations(client: &reqwest::Client, config: &AgentConfig) -> Result<()> {
pub async fn sync_observations_once(config: &AgentConfig) -> Result<usize> {
let client = reqwest::Client::new();
send_agent_observations(&client, config).await
}
async fn send_agent_observations(client: &reqwest::Client, config: &AgentConfig) -> Result<usize> {
let observations =
wakey::wakey_linux::dhcp::list_local_observations_from_path(&config.observation_store_path)
.await
.context("failed to read local observations")?;
if observations.is_empty() {
return Ok(());
return Ok(0);
}
let url = observations_url(&config.server_url)?;
@@ -210,7 +215,7 @@ async fn send_agent_observations(client: &reqwest::Client, config: &AgentConfig)
observations = payload.observations.len(),
"synced local observations"
);
Ok(())
Ok(payload.observations.len())
}
pub fn next_backoff_ms(current_ms: u64, max_ms: u64) -> u64 {