clearer idea?
This commit is contained in:
1 parent
c2ae0f3d25
commit
66c9d139dc
8 files changed
+66
-27
No files matched your search
@@ -1,10 +1,10 @@
|
|||||||
data_dir = "/var/lib/wakey-control-plane"
|
data_dir = "/var/lib/wakey-control-plane"
|
||||||
bind = "0.0.0.0:8080"
|
bind = "0.0.0.0:8080"
|
||||||
public_url = "http://127.0.0.1:8080"
|
public_url = "http://127.0.0.1:8080"
|
||||||
state_file = "/var/lib/wakey-control-plane/state.db"
|
state_file = "state.db"
|
||||||
command_timeout_ms = 30000
|
command_timeout_ms = 30000
|
||||||
enroll_token_ttl_seconds = 86400
|
enroll_token_ttl_seconds = 86400
|
||||||
pid_file = "/var/lib/wakey-control-plane/wakey-control-plane.pid"
|
pid_file = "wakey-control-plane.pid"
|
||||||
|
|
||||||
[telemetry]
|
[telemetry]
|
||||||
service_name = "wakey-control-plane"
|
service_name = "wakey-control-plane"
|
||||||
|
|||||||
@@ -7,6 +7,15 @@ pub const DEFAULT_PID_FILE: &str = "/var/lib/wakey-control-plane/wakey-control-p
|
|||||||
pub const DEFAULT_DATA_DIR: &str = "/var/lib/wakey-control-plane";
|
pub const DEFAULT_DATA_DIR: &str = "/var/lib/wakey-control-plane";
|
||||||
pub const DEFAULT_CONFIG_FILE: &str = "/etc/wakey-control-plane/config.toml";
|
pub const DEFAULT_CONFIG_FILE: &str = "/etc/wakey-control-plane/config.toml";
|
||||||
|
|
||||||
|
#[derive(Args, Clone, Copy, Default)]
|
||||||
|
pub struct AdminTargetArgs {
|
||||||
|
#[arg(long, conflicts_with = "offline")]
|
||||||
|
pub live: bool,
|
||||||
|
|
||||||
|
#[arg(long, conflicts_with = "live")]
|
||||||
|
pub offline: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "wakey-control-plane")]
|
#[command(name = "wakey-control-plane")]
|
||||||
#[command(version, about = "Control plane server for wakey-agent fleets")]
|
#[command(version, about = "Control plane server for wakey-agent fleets")]
|
||||||
@@ -50,8 +59,8 @@ pub struct ServeArgs {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub state_file: Option<PathBuf>,
|
pub state_file: Option<PathBuf>,
|
||||||
|
|
||||||
#[arg(long = "enroll-token")]
|
#[arg(long = "bootstrap-enroll-token", visible_alias = "enroll-token")]
|
||||||
pub enroll_tokens: Vec<String>,
|
pub bootstrap_enroll_tokens: Vec<String>,
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub command_timeout_ms: Option<u64>,
|
pub command_timeout_ms: Option<u64>,
|
||||||
@@ -95,8 +104,8 @@ pub struct InitConfigArgs {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub enroll_token_ttl_seconds: Option<u64>,
|
pub enroll_token_ttl_seconds: Option<u64>,
|
||||||
|
|
||||||
#[arg(long = "enroll-token")]
|
#[arg(long = "bootstrap-enroll-token", visible_alias = "enroll-token")]
|
||||||
pub enroll_tokens: Vec<String>,
|
pub bootstrap_enroll_tokens: Vec<String>,
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub telemetry_otlp_endpoint: Option<String>,
|
pub telemetry_otlp_endpoint: Option<String>,
|
||||||
@@ -122,14 +131,14 @@ pub struct IssueEnrollTokenArgs {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub data_dir: Option<PathBuf>,
|
pub data_dir: Option<PathBuf>,
|
||||||
|
|
||||||
#[arg(long = "enroll-token")]
|
|
||||||
pub enroll_tokens: Vec<String>,
|
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub public_url: Option<String>,
|
pub public_url: Option<String>,
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub ttl_seconds: Option<u64>,
|
pub ttl_seconds: Option<u64>,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub target: AdminTargetArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
@@ -151,6 +160,9 @@ pub struct ListEnrollTokensArgs {
|
|||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub json: bool,
|
pub json: bool,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub target: AdminTargetArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
@@ -169,6 +181,9 @@ pub struct RevokeEnrollTokenArgs {
|
|||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub token: String,
|
pub token: String,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub target: AdminTargetArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
@@ -187,6 +202,9 @@ pub struct StateStatsArgs {
|
|||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub json: bool,
|
pub json: bool,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
pub target: AdminTargetArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub fn write_init_config(args: &InitConfigArgs) -> Result<()> {
|
|||||||
command_timeout_ms: args.command_timeout_ms.unwrap_or(30_000).max(1),
|
command_timeout_ms: args.command_timeout_ms.unwrap_or(30_000).max(1),
|
||||||
enroll_token_ttl_seconds: args.enroll_token_ttl_seconds.unwrap_or(86_400).max(1),
|
enroll_token_ttl_seconds: args.enroll_token_ttl_seconds.unwrap_or(86_400).max(1),
|
||||||
pid_file,
|
pid_file,
|
||||||
enroll_tokens: args.enroll_tokens.clone(),
|
bootstrap_enroll_tokens: args.bootstrap_enroll_tokens.clone(),
|
||||||
telemetry: WritableTelemetry {
|
telemetry: WritableTelemetry {
|
||||||
otlp_endpoint: args.telemetry_otlp_endpoint.clone(),
|
otlp_endpoint: args.telemetry_otlp_endpoint.clone(),
|
||||||
service_name: args
|
service_name: args
|
||||||
@@ -86,7 +86,7 @@ pub fn bootstrap_config_if_missing(args: &ServeArgs) -> Result<bool> {
|
|||||||
pid_file: args.pid_file.clone(),
|
pid_file: args.pid_file.clone(),
|
||||||
command_timeout_ms: args.command_timeout_ms,
|
command_timeout_ms: args.command_timeout_ms,
|
||||||
enroll_token_ttl_seconds: args.enroll_token_ttl_seconds,
|
enroll_token_ttl_seconds: args.enroll_token_ttl_seconds,
|
||||||
enroll_tokens: args.enroll_tokens.clone(),
|
bootstrap_enroll_tokens: args.bootstrap_enroll_tokens.clone(),
|
||||||
telemetry_otlp_endpoint: None,
|
telemetry_otlp_endpoint: None,
|
||||||
telemetry_service_name: None,
|
telemetry_service_name: None,
|
||||||
telemetry_json_logs: false,
|
telemetry_json_logs: false,
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ mod types;
|
|||||||
|
|
||||||
pub use init::{bootstrap_config_if_missing, write_init_config};
|
pub use init::{bootstrap_config_if_missing, write_init_config};
|
||||||
pub use resolve::{
|
pub use resolve::{
|
||||||
issue_token_endpoint, normalize_public_url, resolve_issue_token_settings,
|
issue_token_endpoint, resolve_issue_token_settings, resolve_list_enroll_token_settings,
|
||||||
resolve_list_enroll_token_settings, resolve_revoke_enroll_token_settings,
|
resolve_revoke_enroll_token_settings, resolve_state_stats_settings,
|
||||||
resolve_state_stats_settings,
|
|
||||||
};
|
};
|
||||||
pub use types::{DaemonConfig, TelemetryConfig};
|
pub use types::{DaemonConfig, TelemetryConfig};
|
||||||
@@ -5,7 +5,8 @@ use std::time::Duration;
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use crate::cli::{
|
use crate::cli::{
|
||||||
IssueEnrollTokenArgs, ListEnrollTokensArgs, RevokeEnrollTokenArgs, ServeArgs, StateStatsArgs,
|
AdminTargetArgs, IssueEnrollTokenArgs, ListEnrollTokensArgs, RevokeEnrollTokenArgs, ServeArgs,
|
||||||
|
StateStatsArgs,
|
||||||
};
|
};
|
||||||
use crate::config::types::{
|
use crate::config::types::{
|
||||||
DaemonConfig, FileConfig, FileTelemetryConfig, IssueTokenSettings, StateAccessSettings,
|
DaemonConfig, FileConfig, FileTelemetryConfig, IssueTokenSettings, StateAccessSettings,
|
||||||
@@ -72,10 +73,10 @@ impl DaemonConfig {
|
|||||||
.unwrap_or_else(|| PathBuf::from("wakey-control-plane.pid"));
|
.unwrap_or_else(|| PathBuf::from("wakey-control-plane.pid"));
|
||||||
let pid_file = resolve_path(&data_dir, pid_file_raw);
|
let pid_file = resolve_path(&data_dir, pid_file_raw);
|
||||||
|
|
||||||
let enroll_tokens = if args.enroll_tokens.is_empty() {
|
let bootstrap_enroll_tokens = if args.bootstrap_enroll_tokens.is_empty() {
|
||||||
file.enroll_tokens.unwrap_or_default()
|
file.bootstrap_enroll_tokens.unwrap_or_default()
|
||||||
} else {
|
} else {
|
||||||
args.enroll_tokens.clone()
|
args.bootstrap_enroll_tokens.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let telemetry = resolve_telemetry(file.telemetry);
|
let telemetry = resolve_telemetry(file.telemetry);
|
||||||
@@ -88,7 +89,7 @@ impl DaemonConfig {
|
|||||||
command_timeout,
|
command_timeout,
|
||||||
enroll_token_ttl,
|
enroll_token_ttl,
|
||||||
pid_file,
|
pid_file,
|
||||||
enroll_tokens,
|
bootstrap_enroll_tokens,
|
||||||
telemetry,
|
telemetry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -120,6 +121,7 @@ pub fn resolve_issue_token_settings(args: &IssueEnrollTokenArgs) -> Result<Issue
|
|||||||
args.data_dir.clone(),
|
args.data_dir.clone(),
|
||||||
args.state_file.clone(),
|
args.state_file.clone(),
|
||||||
args.public_url.clone(),
|
args.public_url.clone(),
|
||||||
|
&args.target,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let ttl = Duration::from_secs(
|
let ttl = Duration::from_secs(
|
||||||
@@ -132,6 +134,7 @@ pub fn resolve_issue_token_settings(args: &IssueEnrollTokenArgs) -> Result<Issue
|
|||||||
Ok(IssueTokenSettings {
|
Ok(IssueTokenSettings {
|
||||||
data_dir: state.data_dir,
|
data_dir: state.data_dir,
|
||||||
state_file: state.state_file,
|
state_file: state.state_file,
|
||||||
|
public_url: state.public_url,
|
||||||
ttl,
|
ttl,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -144,6 +147,7 @@ pub fn resolve_list_enroll_token_settings(
|
|||||||
args.data_dir.clone(),
|
args.data_dir.clone(),
|
||||||
args.state_file.clone(),
|
args.state_file.clone(),
|
||||||
args.public_url.clone(),
|
args.public_url.clone(),
|
||||||
|
&args.target,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +159,7 @@ pub fn resolve_revoke_enroll_token_settings(
|
|||||||
args.data_dir.clone(),
|
args.data_dir.clone(),
|
||||||
args.state_file.clone(),
|
args.state_file.clone(),
|
||||||
args.public_url.clone(),
|
args.public_url.clone(),
|
||||||
|
&args.target,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +169,7 @@ pub fn resolve_state_stats_settings(args: &StateStatsArgs) -> Result<StateAccess
|
|||||||
args.data_dir.clone(),
|
args.data_dir.clone(),
|
||||||
args.state_file.clone(),
|
args.state_file.clone(),
|
||||||
args.public_url.clone(),
|
args.public_url.clone(),
|
||||||
|
&args.target,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,6 +184,19 @@ pub(crate) fn load_file_config(path: &Path) -> Result<FileConfig> {
|
|||||||
.with_context(|| format!("failed to parse config file {}", path.display()))
|
.with_context(|| format!("failed to parse config file {}", path.display()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_admin_public_url(
|
||||||
|
mode: &AdminTargetArgs,
|
||||||
|
config_public_url: Option<String>,
|
||||||
|
) -> Result<Option<String>> {
|
||||||
|
match (mode.live, mode.offline) {
|
||||||
|
(true, false) => config_public_url
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("--live requires --public-url or a configured public_url"))
|
||||||
|
.map(Some),
|
||||||
|
(false, true) => Ok(None),
|
||||||
|
_ => Ok(config_public_url),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_telemetry(file: Option<FileTelemetryConfig>) -> TelemetryConfig {
|
fn resolve_telemetry(file: Option<FileTelemetryConfig>) -> TelemetryConfig {
|
||||||
let mut out = TelemetryConfig::default();
|
let mut out = TelemetryConfig::default();
|
||||||
if let Some(file) = file {
|
if let Some(file) = file {
|
||||||
@@ -205,6 +224,7 @@ fn resolve_state_access(
|
|||||||
cli_data_dir: Option<PathBuf>,
|
cli_data_dir: Option<PathBuf>,
|
||||||
cli_state_file: Option<PathBuf>,
|
cli_state_file: Option<PathBuf>,
|
||||||
cli_public_url: Option<String>,
|
cli_public_url: Option<String>,
|
||||||
|
mode: &AdminTargetArgs,
|
||||||
) -> Result<StateAccessSettings> {
|
) -> Result<StateAccessSettings> {
|
||||||
let file = load_file_config(config_file)?;
|
let file = load_file_config(config_file)?;
|
||||||
|
|
||||||
@@ -219,9 +239,10 @@ fn resolve_state_access(
|
|||||||
.unwrap_or_else(|| PathBuf::from("state.db")),
|
.unwrap_or_else(|| PathBuf::from("state.db")),
|
||||||
);
|
);
|
||||||
|
|
||||||
let public_url = cli_public_url
|
let resolved_public_url = cli_public_url
|
||||||
.or(file.public_url)
|
.or(file.public_url)
|
||||||
.map(|url| normalize_public_url(&url));
|
.map(|url| normalize_public_url(&url));
|
||||||
|
let public_url = resolve_admin_public_url(mode, resolved_public_url)?;
|
||||||
|
|
||||||
Ok(StateAccessSettings {
|
Ok(StateAccessSettings {
|
||||||
data_dir,
|
data_dir,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ pub struct DaemonConfig {
|
|||||||
pub command_timeout: Duration,
|
pub command_timeout: Duration,
|
||||||
pub enroll_token_ttl: Duration,
|
pub enroll_token_ttl: Duration,
|
||||||
pub pid_file: PathBuf,
|
pub pid_file: PathBuf,
|
||||||
pub enroll_tokens: Vec<String>,
|
pub bootstrap_enroll_tokens: Vec<String>,
|
||||||
pub telemetry: TelemetryConfig,
|
pub telemetry: TelemetryConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,8 @@ pub(crate) struct FileConfig {
|
|||||||
pub(crate) command_timeout_ms: Option<u64>,
|
pub(crate) command_timeout_ms: Option<u64>,
|
||||||
pub(crate) enroll_token_ttl_seconds: Option<u64>,
|
pub(crate) enroll_token_ttl_seconds: Option<u64>,
|
||||||
pub(crate) pid_file: Option<PathBuf>,
|
pub(crate) pid_file: Option<PathBuf>,
|
||||||
pub(crate) enroll_tokens: Option<Vec<String>>,
|
#[serde(alias = "enroll_tokens")]
|
||||||
|
pub(crate) bootstrap_enroll_tokens: Option<Vec<String>>,
|
||||||
pub(crate) telemetry: Option<FileTelemetryConfig>,
|
pub(crate) telemetry: Option<FileTelemetryConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ pub(crate) struct WritableConfig {
|
|||||||
pub(crate) enroll_token_ttl_seconds: u64,
|
pub(crate) enroll_token_ttl_seconds: u64,
|
||||||
pub(crate) pid_file: PathBuf,
|
pub(crate) pid_file: PathBuf,
|
||||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
pub(crate) enroll_tokens: Vec<String>,
|
pub(crate) bootstrap_enroll_tokens: Vec<String>,
|
||||||
pub(crate) telemetry: WritableTelemetry,
|
pub(crate) telemetry: WritableTelemetry,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@ pub(crate) struct WritableTelemetry {
|
|||||||
pub struct IssueTokenSettings {
|
pub struct IssueTokenSettings {
|
||||||
pub data_dir: PathBuf,
|
pub data_dir: PathBuf,
|
||||||
pub state_file: PathBuf,
|
pub state_file: PathBuf,
|
||||||
|
pub public_url: Option<String>,
|
||||||
pub ttl: Duration,
|
pub ttl: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ use crate::state;
|
|||||||
pub async fn issue_enroll_token(args: IssueEnrollTokenArgs) -> Result<()> {
|
pub async fn issue_enroll_token(args: IssueEnrollTokenArgs) -> Result<()> {
|
||||||
let settings = config::resolve_issue_token_settings(&args)?;
|
let settings = config::resolve_issue_token_settings(&args)?;
|
||||||
|
|
||||||
if let Some(url) = args.public_url {
|
if let Some(base) = settings.public_url.as_deref() {
|
||||||
let base = config::normalize_public_url(&url);
|
|
||||||
let ttl_seconds = settings.ttl.as_secs().max(1);
|
let ttl_seconds = settings.ttl.as_secs().max(1);
|
||||||
let endpoint = format!(
|
let endpoint = format!(
|
||||||
"{}?ttl_seconds={ttl_seconds}",
|
"{}?ttl_seconds={ttl_seconds}",
|
||||||
@@ -53,7 +52,7 @@ pub async fn issue_enroll_token(args: IssueEnrollTokenArgs) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tracing::info!(data_dir = %settings.data_dir.display(), state_file = %settings.state_file.display(), ttl_seconds = settings.ttl.as_secs(), "issuing enroll token via offline state file fallback");
|
tracing::info!(data_dir = %settings.data_dir.display(), state_file = %settings.state_file.display(), ttl_seconds = settings.ttl.as_secs(), "issuing enroll token via offline state file fallback");
|
||||||
let store = state::Store::load_or_init(&settings.state_file, args.enroll_tokens, settings.ttl)
|
let store = state::Store::load_or_init(&settings.state_file, Vec::new(), settings.ttl)
|
||||||
.await
|
.await
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ pub async fn serve(daemon: config::DaemonConfig) -> Result<()> {
|
|||||||
|
|
||||||
let store = state::Store::load_or_init(
|
let store = state::Store::load_or_init(
|
||||||
&daemon.state_file,
|
&daemon.state_file,
|
||||||
daemon.enroll_tokens.clone(),
|
daemon.bootstrap_enroll_tokens.clone(),
|
||||||
daemon.enroll_token_ttl,
|
daemon.enroll_token_ttl,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
Reference in new issue
Block a user