use crate::discovery::NginxDiscovery;
use crate::error::{Error, Result};
use std::path::PathBuf;
use std::process::Command;
pub fn find_nginx() -> Result<PathBuf> {
which::which("nginx").map_err(|e| {
Error::System(format!(
"nginx binary not found in PATH: {e}. \
Please ensure nginx is installed and accessible."
))
})
}
pub fn nginx_version() -> Result<String> {
let nginx = find_nginx()?;
let output = Command::new(nginx)
.arg("-v")
.output()
.map_err(|e| Error::System(format!("Failed to execute nginx -v: {e}")))?;
let version_text = String::from_utf8_lossy(&output.stderr);
let version = version_text.lines().next().unwrap_or("unknown").to_string();
Ok(version)
}
pub fn dump_config() -> Result<String> {
let nginx = find_nginx()?;
let output = Command::new(nginx).arg("-T").output().map_err(|e| {
Error::System(format!(
"Failed to execute nginx -T: {e}. \
You may need to run with sudo or as root."
))
})?;
if output.status.success() {
String::from_utf8(output.stdout)
.map_err(|e| Error::System(format!("nginx -T output contains invalid UTF-8: {e}")))
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
Err(Error::System(format!(
"nginx -T failed with status {}: {stderr}\n\
Common causes:\n\
- Insufficient permissions (try running with sudo)\n\
- NGINX is not running\n\
- Configuration has syntax errors",
output.status
)))
}
}
pub fn test_config() -> Result<String> {
let nginx = find_nginx()?;
let output = Command::new(nginx)
.arg("-t")
.output()
.map_err(|e| Error::System(format!("Failed to execute nginx -t: {e}")))?;
let stderr = String::from_utf8_lossy(&output.stderr);
if output.status.success() {
Ok(stderr.to_string())
} else {
Err(Error::System(format!(
"Configuration test failed:\n{stderr}"
)))
}
}
pub fn detect_and_parse() -> Result<NginxDiscovery> {
let config_text = dump_config()?;
NginxDiscovery::from_config_text(&config_text)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore = "requires nginx to be installed"]
fn test_find_nginx() {
let result = find_nginx();
assert!(result.is_ok(), "nginx should be findable if installed");
}
#[test]
#[ignore = "requires nginx to be installed"]
fn test_nginx_version() {
let result = nginx_version();
assert!(result.is_ok());
if let Ok(version) = result {
assert!(version.contains("nginx"));
}
}
#[test]
#[ignore = "requires nginx to be installed and running with proper permissions"]
fn test_dump_config() {
let result = dump_config();
if let Err(err) = result {
assert!(err.to_string().contains("sudo") || err.to_string().contains("permission"));
}
}
#[test]
#[ignore = "requires nginx to be installed"]
fn test_test_config() {
let result = test_config();
let _ = result;
}
#[test]
fn test_error_messages() {
let err = Error::System("nginx not found".to_string());
assert!(err.to_string().contains("nginx not found"));
}
}