Files
harmony/opnsense-api/examples/install_and_wait.rs
Jean-Gabriel Gill-Couture da90dc55ad
Some checks failed
Run Check Script / check (pull_request) Failing after 19s
chore: cargo fmt across workspace
2026-03-25 23:20:57 -04:00

94 lines
2.4 KiB
Rust

//! Example: install an OPNsense package and poll until completion.
//!
//! ```text
//! cargo run --example install_and_wait -- os-haproxy
//! ```
//!
//! The firmware install endpoint is async — it returns a `msg_uuid` that
//! must be polled via `GET /api/core/firmware/upgradestatus`.
mod common;
use serde::Deserialize;
use std::env;
#[derive(Debug, Deserialize)]
struct InstallResponse {
status: String,
#[serde(default)]
msg_uuid: String,
}
#[derive(Debug, Deserialize)]
struct UpgradeStatus {
#[serde(default)]
status: String,
#[serde(default)]
log: String,
}
#[tokio::main]
async fn main() {
let client = common::client_from_env();
let pkg_name = env::args().nth(1).unwrap_or_else(|| {
eprintln!("Usage: cargo run --example install_and_wait -- <package_name>");
std::process::exit(1);
});
println!("Installing {pkg_name}...");
let resp: InstallResponse = client
.post_typed(
"core",
"firmware",
&format!("install/{pkg_name}"),
None::<&()>,
)
.await
.expect("install API call failed");
println!(
"Install triggered: status={}, msg_uuid={}",
resp.status, resp.msg_uuid
);
if resp.status != "ok" {
eprintln!("Install did not return 'ok'. Response: {resp:?}");
std::process::exit(1);
}
// Poll for completion
loop {
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
let status: UpgradeStatus = client
.get_typed("core", "firmware", "upgradestatus")
.await
.expect("upgradestatus API call failed");
let last_line = status.log.lines().last().unwrap_or("");
println!(" status={}, last_log={}", status.status, last_line);
if status.status == "done" {
println!("Installation complete.");
break;
}
}
// Verify
let info: serde_json::Value = client
.get_typed("core", "firmware", "info")
.await
.expect("info API call failed");
if let Some(pkgs) = info["package"].as_array() {
if let Some(pkg) = pkgs.iter().find(|p| p["name"].as_str() == Some(&pkg_name)) {
println!(
"Package {} version={} installed={}",
pkg["name"], pkg["version"], pkg["installed"]
);
}
}
}