default configs

This commit is contained in:
lda
2026-05-27 02:28:05 +07:00 Verified
parent 69b5313005
commit 71be2b7ccc
6 changed files with 180 additions and 79 deletions
+19 -1
View File
@@ -2,6 +2,7 @@ use anyhow::{Context, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock;
pub const DEFAULT_CONFIG_PATH: &str = "/etc/wakey-agent/config.toml"; pub const DEFAULT_CONFIG_PATH: &str = "/etc/wakey-agent/config.toml";
pub const DEFAULT_PID_FILE: &str = "/var/run/wakey-agent.pid"; pub const DEFAULT_PID_FILE: &str = "/var/run/wakey-agent.pid";
@@ -36,6 +37,20 @@ pub struct AgentConfig {
pub observation_store_path: PathBuf, pub observation_store_path: PathBuf,
} }
pub static DEFAULT_CONFIG: LazyLock<AgentConfig> = LazyLock::new(|| 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: default_reconnect_base_ms(),
reconnect_max_ms: default_reconnect_max_ms(),
observation_sync_interval_seconds: default_observation_sync_interval_seconds(),
observation_retention_days: default_observation_retention_days(),
pid_file: default_pid_file(),
dhcp_leases_path: default_dhcp_leases_path(),
mac_name_cache_path: default_mac_name_cache_path(),
observation_store_path: default_observation_store_path(),
});
impl fmt::Debug for AgentConfig { impl fmt::Debug for AgentConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AgentConfig") f.debug_struct("AgentConfig")
@@ -226,6 +241,9 @@ agent_token = "secret"
) )
.expect("config should parse"); .expect("config should parse");
assert_eq!(config.observation_retention_days, 7); assert_eq!(
config.observation_retention_days,
DEFAULT_OBSERVATION_RETENTION_DAYS
);
} }
} }
+7 -30
View File
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tracing::{info, warn}; use tracing::{info, warn};
use crate::config::{AgentConfig, save_config_with_backup}; use crate::config::{AgentConfig, DEFAULT_CONFIG, save_config_with_backup};
pub struct EnrollOutcome { pub struct EnrollOutcome {
pub config: AgentConfig, pub config: AgentConfig,
@@ -55,35 +55,12 @@ pub async fn enroll(
.await .await
.context("failed to decode enrollment response")?; .context("failed to decode enrollment response")?;
let config = AgentConfig { let mut config = base_config
server_url: payload.server_url.unwrap_or(server_url), .cloned()
agent_id: payload.agent_id, .unwrap_or_else(|| (*DEFAULT_CONFIG).clone());
agent_token: payload.agent_token, config.server_url = payload.server_url.unwrap_or(server_url);
reconnect_base_ms: base_config config.agent_id = payload.agent_id;
.map(|config| config.reconnect_base_ms) config.agent_token = payload.agent_token;
.unwrap_or(1_000),
reconnect_max_ms: base_config
.map(|config| config.reconnect_max_ms)
.unwrap_or(30_000),
observation_sync_interval_seconds: base_config
.map(|config| config.observation_sync_interval_seconds)
.unwrap_or(60),
observation_retention_days: base_config
.map(|config| config.observation_retention_days)
.unwrap_or(crate::config::DEFAULT_OBSERVATION_RETENTION_DAYS),
pid_file: base_config
.map(|config| config.pid_file.clone())
.unwrap_or_else(|| crate::config::DEFAULT_PID_FILE.into()),
dhcp_leases_path: base_config
.map(|config| config.dhcp_leases_path.clone())
.unwrap_or_else(|| "/tmp/dhcp.leases".into()),
mac_name_cache_path: base_config
.map(|config| config.mac_name_cache_path.clone())
.unwrap_or_else(|| "/tmp/wakey_mac_names.json".into()),
observation_store_path: base_config
.map(|config| config.observation_store_path.clone())
.unwrap_or_else(|| "/tmp/wakey_observations.json".into()),
};
let backup_path = save_config_with_backup(config_path, &config)?; let backup_path = save_config_with_backup(config_path, &config)?;
info!(agent_id = %config.agent_id, config_path = %config_path.display(), "agent enrollment succeeded and config was written"); info!(agent_id = %config.agent_id, config_path = %config_path.display(), "agent enrollment succeeded and config was written");
Ok(EnrollOutcome { Ok(EnrollOutcome {
+1 -13
View File
@@ -248,19 +248,7 @@ fn init_config(args: InitConfigArgs) -> Result<()> {
let mut cfg = if let Some(from_config) = &args.from_config { let mut cfg = if let Some(from_config) = &args.from_config {
config::load_config(from_config)? config::load_config(from_config)?
} else { } else {
config::AgentConfig { (*config::DEFAULT_CONFIG).clone()
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,
observation_retention_days: config::DEFAULT_OBSERVATION_RETENTION_DAYS,
pid_file: config::DEFAULT_PID_FILE.into(),
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 { if let Some(server_url) = args.server_url {
+66 -14
View File
@@ -4,7 +4,7 @@ use anyhow::{Context, Result};
use crate::cli::{InitConfigArgs, ServeArgs}; use crate::cli::{InitConfigArgs, ServeArgs};
use crate::config::resolve::{load_file_config, normalize_public_url, resolve_path}; use crate::config::resolve::{load_file_config, normalize_public_url, resolve_path};
use crate::config::types::{WritableConfig, WritableTelemetry}; use crate::config::types::{DEFAULT_CONFIG, WritableConfig, WritableTelemetry};
pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> { pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> {
if args.stdout && args.config_file.is_some() { if args.stdout && args.config_file.is_some() {
@@ -30,6 +30,7 @@ pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> {
Default::default() Default::default()
}; };
let base_telemetry = base.telemetry.unwrap_or_default(); let base_telemetry = base.telemetry.unwrap_or_default();
let defaults = &*DEFAULT_CONFIG;
let bind = match args.bind { let bind = match args.bind {
Some(bind) => bind, Some(bind) => bind,
@@ -43,7 +44,8 @@ pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> {
.unwrap_or_else(|| "<defaults>".to_string()) .unwrap_or_else(|| "<defaults>".to_string())
) )
})?, })?,
None => "0.0.0.0:8080" None => defaults
.bind
.parse() .parse()
.expect("static default bind should parse"), .expect("static default bind should parse"),
}, },
@@ -52,37 +54,38 @@ pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> {
args.public_url args.public_url
.as_deref() .as_deref()
.or(base.public_url.as_deref()) .or(base.public_url.as_deref())
.unwrap_or("http://127.0.0.1:8080"), .unwrap_or(&defaults.public_url),
); );
let data_dir = args let data_dir = args
.data_dir .data_dir
.clone() .clone()
.or(base.data_dir) .or(base.data_dir)
.unwrap_or_else(|| PathBuf::from(crate::cli::DEFAULT_DATA_DIR)); .unwrap_or_else(|| defaults.data_dir.clone());
let state_file_raw = args let state_file_raw = args
.state_file .state_file
.clone() .clone()
.or(base.state_file) .or(base.state_file)
.unwrap_or_else(|| PathBuf::from("state.sqlite3")); .unwrap_or_else(|| defaults.state_file.clone());
let state_file = resolve_path(&data_dir, state_file_raw); let state_file = resolve_path(&data_dir, state_file_raw);
let pid_file_raw = args let pid_file_raw = args
.pid_file .pid_file
.clone() .clone()
.or(base.pid_file) .or(base.pid_file)
.unwrap_or_else(|| PathBuf::from("wakey-control-plane.pid")); .unwrap_or_else(|| defaults.pid_file.clone());
let pid_file = resolve_path(&data_dir, pid_file_raw); let pid_file = resolve_path(&data_dir, pid_file_raw);
let ui_dist_dir = args let ui_dist_dir = args
.ui_dist_dir .ui_dist_dir
.clone() .clone()
.or(base.ui_dist_dir) .or(base.ui_dist_dir)
.unwrap_or_else(|| PathBuf::from("ui/dist")); .unwrap_or_else(|| defaults.ui_dist_dir.clone());
let bootstrap_enroll_tokens = if args.bootstrap_enroll_tokens.is_empty() { let bootstrap_enroll_tokens = if args.bootstrap_enroll_tokens.is_empty() {
base.bootstrap_enroll_tokens.unwrap_or_default() base.bootstrap_enroll_tokens
.unwrap_or_else(|| defaults.bootstrap_enroll_tokens.clone())
} else { } else {
args.bootstrap_enroll_tokens.clone() args.bootstrap_enroll_tokens.clone()
}; };
@@ -95,17 +98,17 @@ pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> {
command_timeout_ms: args command_timeout_ms: args
.command_timeout_ms .command_timeout_ms
.or(base.command_timeout_ms) .or(base.command_timeout_ms)
.unwrap_or(30_000) .unwrap_or(defaults.command_timeout_ms)
.max(1), .max(1),
enroll_token_ttl_seconds: args enroll_token_ttl_seconds: args
.enroll_token_ttl_seconds .enroll_token_ttl_seconds
.or(base.enroll_token_ttl_seconds) .or(base.enroll_token_ttl_seconds)
.unwrap_or(86_400) .unwrap_or(defaults.enroll_token_ttl_seconds)
.max(1), .max(1),
observation_retention_seconds: args observation_retention_seconds: args
.observation_retention_seconds .observation_retention_seconds
.or(base.observation_retention_seconds) .or(base.observation_retention_seconds)
.unwrap_or(2_592_000), .unwrap_or(defaults.observation_retention_seconds),
pid_file, pid_file,
ui_dist_dir, ui_dist_dir,
bootstrap_enroll_tokens, bootstrap_enroll_tokens,
@@ -113,16 +116,17 @@ pub fn write_init_config(args: &InitConfigArgs) -> Result<Option<PathBuf>> {
otlp_endpoint: args otlp_endpoint: args
.telemetry_otlp_endpoint .telemetry_otlp_endpoint
.clone() .clone()
.or(base_telemetry.otlp_endpoint), .or(base_telemetry.otlp_endpoint)
.or_else(|| defaults.telemetry.otlp_endpoint.clone()),
service_name: args service_name: args
.telemetry_service_name .telemetry_service_name
.clone() .clone()
.or(base_telemetry.service_name) .or(base_telemetry.service_name)
.unwrap_or_else(|| "wakey-control-plane".to_string()), .unwrap_or_else(|| defaults.telemetry.service_name.clone()),
json_logs: args json_logs: args
.telemetry_json_logs .telemetry_json_logs
.or(base_telemetry.json_logs) .or(base_telemetry.json_logs)
.unwrap_or(false), .unwrap_or(defaults.telemetry.json_logs),
}, },
}; };
@@ -176,6 +180,7 @@ pub fn bootstrap_config_if_missing(args: &ServeArgs) -> Result<bool> {
mod tests { mod tests {
use super::write_init_config; use super::write_init_config;
use crate::cli::InitConfigArgs; use crate::cli::InitConfigArgs;
use crate::config::types::DEFAULT_CONFIG;
fn temp_test_dir(name: &str) -> std::path::PathBuf { fn temp_test_dir(name: &str) -> std::path::PathBuf {
std::env::temp_dir().join(format!( std::env::temp_dir().join(format!(
@@ -251,4 +256,51 @@ json_logs = true
let _ = std::fs::remove_dir_all(&dir); let _ = std::fs::remove_dir_all(&dir);
} }
#[test]
fn init_config_renders_shared_default_template() {
let dir = temp_test_dir("defaults");
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).expect("create temp dir");
let out = dir.join("out.toml");
write_init_config(&InitConfigArgs {
config_file: Some(out.clone()),
from_config: None,
stdout: false,
data_dir: None,
bind: None,
public_url: None,
state_file: None,
pid_file: None,
ui_dist_dir: None,
command_timeout_ms: None,
enroll_token_ttl_seconds: None,
observation_retention_seconds: None,
bootstrap_enroll_tokens: Vec::new(),
telemetry_otlp_endpoint: None,
telemetry_service_name: None,
telemetry_json_logs: None,
force: false,
})
.expect("write default config");
let rendered = std::fs::read_to_string(&out).expect("read default config");
let parsed: toml::Value = toml::from_str(&rendered).expect("parse default config");
let defaults = &*DEFAULT_CONFIG;
assert_eq!(
parsed["state_file"].as_str(),
defaults.data_dir.join(&defaults.state_file).to_str()
);
assert_eq!(
parsed["command_timeout_ms"].as_integer(),
Some(defaults.command_timeout_ms as i64)
);
assert_eq!(
parsed["telemetry"]["service_name"].as_str(),
Some(defaults.telemetry.service_name.as_str())
);
let _ = std::fs::remove_dir_all(&dir);
}
} }
+62 -16
View File
@@ -9,19 +9,20 @@ use crate::cli::{
RevokeEnrollTokenArgs, ServeArgs, StateStatsArgs, RevokeEnrollTokenArgs, ServeArgs, StateStatsArgs,
}; };
use crate::config::types::{ use crate::config::types::{
DaemonConfig, FileConfig, FileTelemetryConfig, IssueTokenSettings, StateAccessSettings, DEFAULT_CONFIG, DaemonConfig, FileConfig, FileTelemetryConfig, IssueTokenSettings,
TelemetryConfig, StateAccessSettings, TelemetryConfig,
}; };
impl DaemonConfig { impl DaemonConfig {
pub fn from_serve_args(args: &ServeArgs) -> Result<Self> { pub fn from_serve_args(args: &ServeArgs) -> Result<Self> {
let file = load_file_config(&args.config_file)?; let file = load_file_config(&args.config_file)?;
let defaults = &*DEFAULT_CONFIG;
let data_dir = args let data_dir = args
.data_dir .data_dir
.clone() .clone()
.or(file.data_dir.clone()) .or(file.data_dir.clone())
.unwrap_or_else(|| PathBuf::from(crate::cli::DEFAULT_DATA_DIR)); .unwrap_or_else(|| defaults.data_dir.clone());
let bind = match args.bind { let bind = match args.bind {
Some(bind) => bind, Some(bind) => bind,
@@ -32,7 +33,8 @@ impl DaemonConfig {
args.config_file.display() args.config_file.display()
) )
})?, })?,
None => "0.0.0.0:8080" None => defaults
.bind
.parse() .parse()
.expect("static default bind should parse"), .expect("static default bind should parse"),
}, },
@@ -42,34 +44,34 @@ impl DaemonConfig {
args.public_url args.public_url
.as_deref() .as_deref()
.or(file.public_url.as_deref()) .or(file.public_url.as_deref())
.unwrap_or("http://127.0.0.1:8080"), .unwrap_or(&defaults.public_url),
); );
let state_file_raw = args let state_file_raw = args
.state_file .state_file
.clone() .clone()
.or(file.state_file) .or(file.state_file)
.unwrap_or_else(|| PathBuf::from("state.sqlite3")); .unwrap_or_else(|| defaults.state_file.clone());
let state_file = resolve_path(&data_dir, state_file_raw); let state_file = resolve_path(&data_dir, state_file_raw);
let command_timeout = Duration::from_millis( let command_timeout = Duration::from_millis(
args.command_timeout_ms args.command_timeout_ms
.or(file.command_timeout_ms) .or(file.command_timeout_ms)
.unwrap_or(30_000) .unwrap_or(defaults.command_timeout_ms)
.max(1), .max(1),
); );
let enroll_token_ttl = Duration::from_secs( let enroll_token_ttl = Duration::from_secs(
args.enroll_token_ttl_seconds args.enroll_token_ttl_seconds
.or(file.enroll_token_ttl_seconds) .or(file.enroll_token_ttl_seconds)
.unwrap_or(86_400) .unwrap_or(defaults.enroll_token_ttl_seconds)
.max(1), .max(1),
); );
let observation_retention = Duration::from_secs( let observation_retention = Duration::from_secs(
args.observation_retention_seconds args.observation_retention_seconds
.or(file.observation_retention_seconds) .or(file.observation_retention_seconds)
.unwrap_or(2_592_000) .unwrap_or(defaults.observation_retention_seconds)
.max(1), .max(1),
); );
@@ -77,17 +79,18 @@ impl DaemonConfig {
.pid_file .pid_file
.clone() .clone()
.or(file.pid_file) .or(file.pid_file)
.unwrap_or_else(|| PathBuf::from("wakey-control-plane.pid")); .unwrap_or_else(|| defaults.pid_file.clone());
let pid_file = resolve_path(&data_dir, pid_file_raw); let pid_file = resolve_path(&data_dir, pid_file_raw);
let ui_dist_dir = args let ui_dist_dir = args
.ui_dist_dir .ui_dist_dir
.clone() .clone()
.or(file.ui_dist_dir) .or(file.ui_dist_dir)
.unwrap_or_else(|| PathBuf::from("ui/dist")); .unwrap_or_else(|| defaults.ui_dist_dir.clone());
let bootstrap_enroll_tokens = if args.bootstrap_enroll_tokens.is_empty() { let bootstrap_enroll_tokens = if args.bootstrap_enroll_tokens.is_empty() {
file.bootstrap_enroll_tokens.unwrap_or_default() file.bootstrap_enroll_tokens
.unwrap_or_else(|| defaults.bootstrap_enroll_tokens.clone())
} else { } else {
args.bootstrap_enroll_tokens.clone() args.bootstrap_enroll_tokens.clone()
}; };
@@ -131,6 +134,7 @@ pub fn resolve_path(data_dir: &Path, candidate: PathBuf) -> PathBuf {
pub fn resolve_issue_token_settings(args: &IssueEnrollTokenArgs) -> Result<IssueTokenSettings> { pub fn resolve_issue_token_settings(args: &IssueEnrollTokenArgs) -> Result<IssueTokenSettings> {
let file = load_file_config(&args.config_file)?; let file = load_file_config(&args.config_file)?;
let defaults = &*DEFAULT_CONFIG;
let state = resolve_state_access( let state = resolve_state_access(
&args.config_file, &args.config_file,
args.data_dir.clone(), args.data_dir.clone(),
@@ -142,7 +146,7 @@ pub fn resolve_issue_token_settings(args: &IssueEnrollTokenArgs) -> Result<Issue
let ttl = Duration::from_secs( let ttl = Duration::from_secs(
args.ttl_seconds args.ttl_seconds
.or(file.enroll_token_ttl_seconds) .or(file.enroll_token_ttl_seconds)
.unwrap_or(86_400) .unwrap_or(defaults.enroll_token_ttl_seconds)
.max(1), .max(1),
); );
@@ -254,16 +258,17 @@ fn resolve_state_access(
mode: &AdminTargetArgs, mode: &AdminTargetArgs,
) -> Result<StateAccessSettings> { ) -> Result<StateAccessSettings> {
let file = load_file_config(config_file)?; let file = load_file_config(config_file)?;
let defaults = &*DEFAULT_CONFIG;
let data_dir = cli_data_dir let data_dir = cli_data_dir
.or(file.data_dir) .or(file.data_dir)
.unwrap_or_else(|| PathBuf::from(crate::cli::DEFAULT_DATA_DIR)); .unwrap_or_else(|| defaults.data_dir.clone());
let state_file = resolve_path( let state_file = resolve_path(
&data_dir, &data_dir,
cli_state_file cli_state_file
.or(file.state_file) .or(file.state_file)
.unwrap_or_else(|| PathBuf::from("state.sqlite3")), .unwrap_or_else(|| defaults.state_file.clone()),
); );
let resolved_public_url = cli_public_url let resolved_public_url = cli_public_url
@@ -280,7 +285,9 @@ fn resolve_state_access(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{normalize_public_url, resolve_path}; use super::{DaemonConfig, normalize_public_url, resolve_path};
use crate::cli::ServeArgs;
use crate::config::types::DEFAULT_CONFIG;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
@@ -303,4 +310,43 @@ mod tests {
PathBuf::from("/var/lib/wakey-control-plane/state.sqlite3") PathBuf::from("/var/lib/wakey-control-plane/state.sqlite3")
); );
} }
#[test]
fn daemon_config_uses_shared_default_template() {
let config_file = std::env::temp_dir().join(format!(
"wakey-cc-missing-config-{}.toml",
std::process::id()
));
let _ = std::fs::remove_file(&config_file);
let resolved = DaemonConfig::from_serve_args(&ServeArgs {
data_dir: None,
bind: None,
public_url: None,
state_file: None,
bootstrap_enroll_tokens: Vec::new(),
command_timeout_ms: None,
enroll_token_ttl_seconds: None,
observation_retention_seconds: None,
pid_file: None,
ui_dist_dir: None,
config_file,
bootstrap_config: false,
})
.expect("resolve default config");
let defaults = &*DEFAULT_CONFIG;
assert_eq!(resolved.data_dir, defaults.data_dir);
assert_eq!(
resolved.state_file,
defaults.data_dir.join(&defaults.state_file)
);
assert_eq!(
resolved.command_timeout,
std::time::Duration::from_millis(defaults.command_timeout_ms)
);
assert_eq!(
resolved.telemetry.service_name,
defaults.telemetry.service_name
);
}
} }
+25 -5
View File
@@ -1,5 +1,6 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::LazyLock;
use std::time::Duration; use std::time::Duration;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -29,10 +30,11 @@ pub struct TelemetryConfig {
impl Default for TelemetryConfig { impl Default for TelemetryConfig {
fn default() -> Self { fn default() -> Self {
let defaults = &DEFAULT_CONFIG.telemetry;
Self { Self {
otlp_endpoint: None, otlp_endpoint: defaults.otlp_endpoint.clone(),
service_name: "wakey-control-plane".to_string(), service_name: defaults.service_name.clone(),
json_logs: false, json_logs: defaults.json_logs,
} }
} }
} }
@@ -60,7 +62,7 @@ pub(crate) struct FileTelemetryConfig {
pub(crate) json_logs: Option<bool>, pub(crate) json_logs: Option<bool>,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Clone, Serialize)]
pub(crate) struct WritableConfig { pub(crate) struct WritableConfig {
pub(crate) data_dir: PathBuf, pub(crate) data_dir: PathBuf,
pub(crate) bind: String, pub(crate) bind: String,
@@ -76,7 +78,7 @@ pub(crate) struct WritableConfig {
pub(crate) telemetry: WritableTelemetry, pub(crate) telemetry: WritableTelemetry,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Clone, Serialize)]
pub(crate) struct WritableTelemetry { pub(crate) struct WritableTelemetry {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub(crate) otlp_endpoint: Option<String>, pub(crate) otlp_endpoint: Option<String>,
@@ -84,6 +86,24 @@ pub(crate) struct WritableTelemetry {
pub(crate) json_logs: bool, pub(crate) json_logs: bool,
} }
pub(crate) static DEFAULT_CONFIG: LazyLock<WritableConfig> = LazyLock::new(|| WritableConfig {
data_dir: crate::cli::DEFAULT_DATA_DIR.into(),
bind: "0.0.0.0:8080".to_string(),
public_url: "http://127.0.0.1:8080".to_string(),
state_file: "state.sqlite3".into(),
command_timeout_ms: 30_000,
enroll_token_ttl_seconds: 86_400,
observation_retention_seconds: 2_592_000,
pid_file: "wakey-control-plane.pid".into(),
ui_dist_dir: "ui/dist".into(),
bootstrap_enroll_tokens: Vec::new(),
telemetry: WritableTelemetry {
otlp_endpoint: None,
service_name: "wakey-control-plane".to_string(),
json_logs: false,
},
});
pub struct IssueTokenSettings { pub struct IssueTokenSettings {
pub data_dir: PathBuf, pub data_dir: PathBuf,
pub state_file: PathBuf, pub state_file: PathBuf,