Some checks failed
Run Check Script / check (pull_request) Failing after 19s
167 lines
5.2 KiB
Rust
167 lines
5.2 KiB
Rust
//! Example: list all OPNsense packages (installed and available).
|
|
//!
|
|
//! ```text
|
|
//! cargo run --example list_packages
|
|
//! ```
|
|
//!
|
|
//! Calls `GET /api/core/firmware/info` which returns package listings
|
|
//! from OPNsense's firmware API.
|
|
|
|
use std::env;
|
|
|
|
use opnsense_api::client::OpnsenseClient;
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct FirmwareInfoResponse {
|
|
pub product: ProductInfo,
|
|
#[serde(default)]
|
|
pub package: Vec<PackageInfo>,
|
|
#[serde(default)]
|
|
pub plugin: Vec<PackageInfo>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct ProductInfo {
|
|
pub product_name: String,
|
|
pub product_version: String,
|
|
pub product_arch: String,
|
|
#[serde(default)]
|
|
pub product_check: Option<serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct PackageInfo {
|
|
pub name: String,
|
|
pub version: String,
|
|
#[serde(default)]
|
|
pub comment: String,
|
|
#[serde(default)]
|
|
pub flatsize: String,
|
|
#[serde(default)]
|
|
pub locked: String,
|
|
#[serde(default)]
|
|
pub automatic: String,
|
|
#[serde(default)]
|
|
pub license: String,
|
|
#[serde(default)]
|
|
pub repository: String,
|
|
#[serde(default)]
|
|
pub origin: String,
|
|
#[serde(default)]
|
|
pub provided: String,
|
|
#[serde(default)]
|
|
pub installed: String,
|
|
#[serde(default)]
|
|
pub configured: String,
|
|
#[serde(default)]
|
|
pub tier: String,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
|
|
|
let base_url =
|
|
env::var("OPNSENSE_BASE_URL").unwrap_or_else(|_| "https://192.168.1.1/api".to_string());
|
|
|
|
let client = match (
|
|
env::var("OPNSENSE_API_KEY").ok(),
|
|
env::var("OPNSENSE_API_SECRET").ok(),
|
|
) {
|
|
(Some(key), Some(secret)) => OpnsenseClient::builder()
|
|
.base_url(&base_url)
|
|
.auth_from_key_secret(&key, &secret)
|
|
.skip_tls_verify()
|
|
.build()
|
|
.expect("failed to build HTTP client"),
|
|
_ => {
|
|
eprintln!("ERROR: OPNSENSE_API_KEY and OPNSENSE_API_SECRET must be set.");
|
|
eprintln!(" export OPNSENSE_API_KEY=your_key");
|
|
eprintln!(" export OPNSENSE_API_SECRET=your_secret");
|
|
eprintln!(" export OPNSENSE_BASE_URL=https://your-firewall/api");
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
log::info!("Fetching /api/core/firmware/info ...");
|
|
|
|
let response: FirmwareInfoResponse = client
|
|
.get_typed("core", "firmware", "info")
|
|
.await
|
|
.expect("API call failed");
|
|
|
|
println!();
|
|
println!("╔═══════════════════════════════════════════════════════════╗");
|
|
println!("║ OPNsense Package Information ║");
|
|
println!("╚═══════════════════════════════════════════════════════════╝");
|
|
println!();
|
|
println!(
|
|
" {} {} ({})",
|
|
response.product.product_name,
|
|
response.product.product_version,
|
|
response.product.product_arch
|
|
);
|
|
println!();
|
|
|
|
let installed: Vec<_> = response
|
|
.plugin
|
|
.iter()
|
|
.filter(|p| p.installed == "1")
|
|
.collect();
|
|
|
|
let available: Vec<_> = response
|
|
.plugin
|
|
.iter()
|
|
.filter(|p| p.installed != "1" && p.provided == "1")
|
|
.collect();
|
|
|
|
println!(
|
|
" Installed plugins: {} (showing first 30)",
|
|
installed.len()
|
|
);
|
|
println!(" ─────────────────────────────────────────────────────────");
|
|
for pkg in installed.iter().take(30) {
|
|
println!(" {:40} {}", pkg.name, pkg.version);
|
|
}
|
|
if installed.len() > 30 {
|
|
println!(" ... and {} more", installed.len() - 30);
|
|
}
|
|
println!();
|
|
|
|
println!(
|
|
" Available plugins: {} (showing first 20)",
|
|
available.len()
|
|
);
|
|
println!(" ─────────────────────────────────────────────────────────");
|
|
for pkg in available.iter().take(20) {
|
|
println!(" {:40} {}", pkg.name, pkg.version);
|
|
}
|
|
if available.len() > 20 {
|
|
println!(" ... and {} more", available.len() - 20);
|
|
}
|
|
println!();
|
|
|
|
let os_packages: Vec<_> = response
|
|
.package
|
|
.iter()
|
|
.filter(|p| p.name.starts_with("os-"))
|
|
.collect();
|
|
println!(
|
|
" System packages (os-*): {} (showing first 20)",
|
|
os_packages.len()
|
|
);
|
|
println!(" ─────────────────────────────────────────────────────────");
|
|
for pkg in os_packages.iter().take(20) {
|
|
let installed = if pkg.installed == "1" {
|
|
" [installed]"
|
|
} else {
|
|
""
|
|
};
|
|
println!(" {:40} {}{}", pkg.name, pkg.version, installed);
|
|
}
|
|
if os_packages.len() > 20 {
|
|
println!(" ... and {} more", os_packages.len() - 20);
|
|
}
|
|
}
|