im pretty sure every subcommands use the config file
This commit is contained in:
+19
-1
@@ -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
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -167,6 +167,7 @@ pub async fn observe_dhcp_event(
|
||||
hostname: Option<&str>,
|
||||
) -> io::Result<bool> {
|
||||
if !matches!(action, "add" | "update" | "old" | "remove") {
|
||||
// old not emitted by hotplug
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@@ -228,6 +229,7 @@ pub async fn observe_neighbor_event(
|
||||
ip: Option<IpAddr>,
|
||||
) -> io::Result<bool> {
|
||||
if !matches!(action, "add" | "update" | "old" | "remove") {
|
||||
// update and remove not emitted by hotplug
|
||||
return Ok(false);
|
||||
}
|
||||
let Some(key) = mac
|
||||
|
||||
Reference in New Issue
Block a user