[Fix] Stability

This commit is contained in:
Alex Emmet 2026-08-28 13:22:59 +02:00
commit 8160f8d0cb
No known key found for this signature in database
44 changed files with 796 additions and 1296 deletions

View file

@ -13,7 +13,6 @@ iota-paths = { path = "../iota-paths" }
iota-terms = { path = "../iota-terms" }
iota-util = { path = "../iota-util" }
tokio = { version = "1.50.0", features = ["full"] }
tokio-util = { version = "0.7", features = ["rt"] }
serde_json = "1"
serde_yaml = "0.9"
clap = { version = "4.5", features = ["derive"] }

View file

@ -93,6 +93,7 @@ enum CliCommand {
yes: bool,
},
Components,
Health,
Logs {
#[arg(long, default_value_t = 100)]
limit: usize,
@ -209,6 +210,12 @@ enum DaemonAction {
#[arg(long)]
operator: Option<String>,
},
Bootstrap {
#[arg(long)]
bundle: String,
#[arg(long)]
operator: Option<String>,
},
}
#[derive(Args, Debug)]
struct UpdateArgs {
@ -276,6 +283,10 @@ pub enum Command {
bundle: String,
operator: Option<String>,
},
Bootstrap {
bundle: String,
operator: Option<String>,
},
Status,
Tasks,
UsersList,
@ -329,6 +340,7 @@ pub enum Command {
confirmed: bool,
},
Components,
Health,
Logs {
limit: usize,
},
@ -388,6 +400,7 @@ impl CliInvocation {
Some(CliCommand::Status) => Command::Status,
Some(CliCommand::Tasks) => Command::Tasks,
Some(CliCommand::Components) => Command::Components,
Some(CliCommand::Health) => Command::Health,
Some(CliCommand::Completions { shell }) => Command::Completions { shell },
Some(CliCommand::Man) => Command::ManPage,
Some(CliCommand::Users(users)) => match users.action {
@ -463,6 +476,9 @@ impl CliInvocation {
DaemonAction::RestartService => Command::DaemonRestartService,
DaemonAction::StopService => Command::DaemonStopService,
DaemonAction::Install { bundle, operator } => Command::Install { bundle, operator },
DaemonAction::Bootstrap { bundle, operator } => {
Command::Bootstrap { bundle, operator }
}
},
};
Ok(Self {
@ -541,6 +557,12 @@ mod tests {
assert_eq!(invocation.command, Command::UsersList);
}
#[test]
fn parses_health() {
let invocation = CliInvocation::parse(["health".into()]).unwrap();
assert_eq!(invocation.command, Command::Health);
}
#[test]
fn parses_terminal_capability_overrides() {
let invocation =
@ -599,6 +621,26 @@ mod tests {
);
}
#[test]
fn parses_bootstrap_operator() {
let invocation = CliInvocation::parse([
"daemon".into(),
"bootstrap".into(),
"--bundle".into(),
"release.zip".into(),
"--operator".into(),
"alice".into(),
])
.unwrap();
assert_eq!(
invocation.command,
Command::Bootstrap {
bundle: "release.zip".into(),
operator: Some("alice".into()),
}
);
}
#[test]
fn parses_unconfirmed_destructive_commands_explicitly() {
let invocation = CliInvocation::parse(["daemon".into(), "stop".into()]).unwrap();

View file

@ -40,33 +40,6 @@ async fn run() -> Result<(), StartupError> {
unicode,
command,
} = invocation;
let local_endpoint = match iota_paths::IotaPaths::resolve(iota_paths::Scope::User)
.map_err(|error| StartupError::Other(format!("Cannot resolve user IPC path: {error}")))?
.ipc_endpoint
{
iota_paths::IpcEndpoint::UnixSocket(path) => path,
iota_paths::IpcEndpoint::WindowsPipe(name) => {
return Err(StartupError::Other(format!(
"Windows IPC endpoint {name} is not supported by this client build"
)));
}
};
let system_endpoint = match iota_paths::IotaPaths::resolve(iota_paths::Scope::System)
.map_err(|error| StartupError::Other(format!("Cannot resolve system IPC path: {error}")))?
.ipc_endpoint
{
iota_paths::IpcEndpoint::UnixSocket(path) => path,
iota_paths::IpcEndpoint::WindowsPipe(name) => {
return Err(StartupError::Other(format!(
"Windows IPC endpoint {name} is not supported by this client build"
)));
}
};
let endpoints = daemon_setup_flow::DaemonEndpoints {
local: local_endpoint,
system: system_endpoint,
};
match command {
Command::Help => {
print_help();
@ -91,7 +64,12 @@ async fn run() -> Result<(), StartupError> {
)
.map_err(|error| StartupError::Other(format!("Installation failed: {error}")))
}
Command::Bootstrap { bundle, operator } => {
iota_installer::bootstrap_linux_bundle(Path::new(&bundle), operator.as_deref())
.map_err(|error| StartupError::Other(format!("Bootstrap failed: {error}")))
}
command => {
let endpoints = resolve_endpoints()?;
if matches!(
command,
Command::DaemonEnable { .. }
@ -123,6 +101,32 @@ async fn run() -> Result<(), StartupError> {
}
}
fn resolve_endpoints() -> Result<daemon_setup_flow::DaemonEndpoints, StartupError> {
let local = match iota_paths::IotaPaths::resolve(iota_paths::Scope::User)
.map_err(|error| StartupError::Other(format!("Cannot resolve user IPC path: {error}")))?
.ipc_endpoint
{
iota_paths::IpcEndpoint::UnixSocket(path) => path,
iota_paths::IpcEndpoint::WindowsPipe(name) => {
return Err(StartupError::Other(format!(
"Windows IPC endpoint {name} is not supported by this client build"
)));
}
};
let system = match iota_paths::IotaPaths::resolve(iota_paths::Scope::System)
.map_err(|error| StartupError::Other(format!("Cannot resolve system IPC path: {error}")))?
.ipc_endpoint
{
iota_paths::IpcEndpoint::UnixSocket(path) => path,
iota_paths::IpcEndpoint::WindowsPipe(name) => {
return Err(StartupError::Other(format!(
"Windows IPC endpoint {name} is not supported by this client build"
)));
}
};
Ok(daemon_setup_flow::DaemonEndpoints { local, system })
}
async fn run_startup_command(command: Command) -> Result<(), StartupError> {
let manager = iota_process_manager::detect()
.await
@ -406,6 +410,7 @@ fn print_help() {
println!(" config get Show current configuration");
println!(" config set <KEY> <VAL> Set a configuration value");
println!(" config reload Reload configuration");
println!(" health Show component health");
println!(" components Show component health");
println!(" logs [--limit N] Show recent log entries");
println!(" update check Check for updates");
@ -422,6 +427,7 @@ fn print_help() {
println!(" daemon restart-service Restart the daemon service");
println!(" daemon stop-service Stop the daemon service");
println!(" daemon install Install from a bundle");
println!(" daemon bootstrap Install and enable a Linux systemd bundle");
println!(" help Show this help message");
println!(" completions <SHELL> Generate shell completions");
println!(" man Show the man page");
@ -630,6 +636,7 @@ async fn run_command(
Command::ConfigGet => LocalRequest::GetConfig,
Command::ConfigSet { key, value } => LocalRequest::SetConfig { key, value },
Command::ConfigReload => LocalRequest::ReloadConfig,
Command::Health => LocalRequest::ListComponents,
Command::Components => LocalRequest::ListComponents,
Command::Logs { limit } => LocalRequest::GetLogs { limit },
Command::UpdateCheck => LocalRequest::CheckUpdate,
@ -657,6 +664,7 @@ async fn run_command(
| Command::Completions { .. }
| Command::ManPage
| Command::Install { .. }
| Command::Bootstrap { .. }
| Command::TermsStatus { .. }
| Command::TermsShow { .. }
| Command::TermsAccept { .. }