Files
harmony/opnsense-api/examples/list_dnsmasq.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

150 lines
6.0 KiB
Rust

//! Example: fetch and display OPNsense Dnsmasq DNS/DHCP settings.
//!
//! ```text
//! cargo run --example list_dnsmasq
//! ```
//!
//! This demonstrates the **full target DX** for the opnsense-api crate:
//!
//! 1. Build a typed [`OpnsenseClient`] — prompted for credentials if not set.
//! 2. Call `GET /api/dnsmasq/settings/get` with full type safety.
//! 3. Pretty-print the deserialized response.
//!
//! ## Credentials
//!
//! The client first checks for `OPNSENSE_API_KEY` and `OPNSENSE_API_SECRET`
//! environment variables. If neither is set, it prompts interactively.
use std::env;
use opnsense_api::client::OpnsenseClient;
use opnsense_api::generated::dnsmasq::DnsmasqResponse;
#[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(|_| {
eprintln!("OPNSENSE_BASE_URL not set, using https://192.168.1.1/api");
"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)) => {
log::info!("Using credentials from environment variables");
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/dnsmasq/settings/get ...");
let response: DnsmasqResponse = client
.get_typed("dnsmasq", "settings", "get")
.await
.expect("API call failed");
println!();
println!("╔═══════════════════════════════════════════════════════════╗");
println!("║ OPNsense Dnsmasq Settings ║");
println!("╚═══════════════════════════════════════════════════════════╝");
println!();
let s = &response.dnsmasq;
println!(" General");
println!(" ─────────────────────────────────────────────────────────");
println!(" DNS service enabled: {}", toggle_opt(s.enable));
println!(" DNSSEC validation: {}", toggle_opt(s.dnssec));
println!(" Log queries: {}", toggle_opt(s.log_queries));
println!();
println!(" DNS Options");
println!(" ─────────────────────────────────────────────────────────");
println!(" Domain required: {}", toggle_opt(s.domain_needed));
println!(
" No private revers: {}",
toggle_opt(s.no_private_reverse)
);
println!(" Strict order: {}", toggle_opt(s.strict_order));
println!(" No /etc/hosts: {}", toggle_opt(s.no_hosts));
println!(" Strict bind: {}", toggle_opt(s.strictbind));
println!(
" Cache size: {}",
s.cache_size
.map(|v| v.to_string())
.unwrap_or_else(|| "".to_string())
);
println!(
" Local TTL: {}",
s.local_ttl
.map(|v| v.to_string())
.unwrap_or_else(|| "".to_string())
);
println!(
" DNS port: {}",
s.port
.map(|v| v.to_string())
.unwrap_or_else(|| "53".to_string())
);
println!();
println!(" DHCP Registration");
println!(" ─────────────────────────────────────────────────────────");
println!(" Register DHCP leases: {}", toggle_opt(s.regdhcp));
println!(
" Register static DHCP: {}",
toggle_opt(s.regdhcpstatic)
);
println!(
" DHCP first: {}",
toggle_opt(s.dhcpfirst)
);
println!(" No ident: {}", toggle(s.no_ident));
if let Some(ref domain) = s.regdhcpdomain {
println!(" Domain: {domain}");
}
println!();
println!(" DHCP Options");
println!(" ─────────────────────────────────────────────────────────");
println!(" Add MAC address: {:?}", s.add_mac);
println!(" Add subnet: {}", toggle_opt(s.add_subnet));
println!(" Strip subnet: {}", toggle_opt(s.strip_subnet));
println!(" No /etc/resolv: {}", toggle_opt(s.no_resolv));
if let Some(v) = s.dns_forward_max {
println!(" DNS forward max: {v}");
}
println!();
println!(" Full response (JSON)");
println!(" ─────────────────────────────────────────────────────────");
println!(" {}", serde_json::to_string_pretty(&response).unwrap());
}
fn toggle(b: bool) -> &'static str {
if b { "enabled ✓" } else { "disabled ✗" }
}
fn toggle_opt(b: Option<bool>) -> &'static str {
match b {
Some(true) => "enabled ✓",
Some(false) => "disabled ✗",
None => "not set",
}
}