use anyhow::Result;
use herolib_clients::zinit::{ServiceConfigBuilder, ZinitHandle};
fn main() -> Result<()> {
println!("=== Advanced Zinit Service Management ===\n");
println!("1. Connecting to zinit server...");
let z = match ZinitHandle::new() {
Ok(handle) => handle,
Err(e) => {
eprintln!("✗ Failed to connect to zinit server: {}", e);
eprintln!("\nPlease start the zinit server with: zinit");
return Ok(());
}
};
println!("✓ Connected to zinit server\n");
println!("2. Creating database service:");
let db_config = ServiceConfigBuilder::new("database")
.exec("postgres -D /var/lib/postgres")
.dir("/var/lib/postgres")
.critical(true)
.restart("on-failure")
.restart_delay_ms(5000)
.max_restarts(5)
.health_tcp("127.0.0.1:5432")
.health_interval_ms(10000)
.log_buffer_lines(5000)
.log_file("/var/log/postgres.log")
.build();
match z.service_set(db_config) {
Ok(_) => println!(),
Err(e) => println!("✗ Error: {}\n", e),
}
println!("3. Creating app service with database dependency:");
let app_config = ServiceConfigBuilder::new("api_server")
.exec("node /app/server.js")
.dir("/app")
.env("DB_HOST", "localhost")
.env("DB_PORT", "5432")
.env("NODE_ENV", "production")
.requires("database")
.after("database")
.restart("on-failure")
.restart_delay_ms(5000)
.max_restarts(5)
.health_http("http://localhost:3000/health")
.log_buffer_lines(10000)
.build();
match z.service_set(app_config) {
Ok(_) => println!(),
Err(e) => println!("✗ Error: {}\n", e),
}
println!("4. Creating alternative API service (conflicts with api_server):");
let alt_config = ServiceConfigBuilder::new("api_server_v2")
.exec("python3 /app/main.py")
.dir("/app")
.env("DB_HOST", "localhost")
.conflicts("api_server")
.build();
match z.service_set(alt_config) {
Ok(_) => println!(),
Err(e) => println!("✗ Error: {}\n", e),
}
println!("5. All services:");
match z.list() {
Ok(services) => {
println!(" Total services: {}", services.len());
for service in &services {
match z.status(service) {
Ok(status) => {
println!(
" - {} (state: {:?}, pid: {:?})",
service, status.state, status.pid
);
}
Err(_) => {
println!(" - {} (status unavailable)", service);
}
}
}
println!();
}
Err(e) => {
println!(" Error listing services: {}\n", e);
}
}
println!("6. Service dependency tree:");
match z.tree() {
Ok(tree_output) => {
println!("{}", tree_output);
println!();
}
Err(e) => {
println!(" Error getting tree: {}\n", e);
}
}
println!("7. Service configuration details:");
match z.list() {
Ok(services) => {
if let Some(service_name) = services.first() {
println!(" Checking service: {}", service_name);
match z.service_get(service_name) {
Ok(config) => {
println!(" Name: {}", config.service.name);
println!(" Exec: {}", config.service.exec);
println!(" Oneshot: {}", config.service.oneshot);
println!(" Critical: {}", config.service.critical);
if !config.service.env.is_empty() {
println!(" Environment variables:");
for (key, value) in &config.service.env {
println!(" {} = {}", key, value);
}
}
if !config.dependencies.requires.is_empty() {
println!(" Requires: {:?}", config.dependencies.requires);
}
if !config.dependencies.after.is_empty() {
println!(" After: {:?}", config.dependencies.after);
}
match z.logs_tail(Some(service_name), Some(5)) {
Ok(logs) => {
println!(" Recent logs ({} entries):", logs.len());
for (i, log) in logs.iter().take(3).enumerate() {
println!(" [{}] {}", i, log.content);
}
}
Err(_) => {
println!(" (No logs available)");
}
}
println!();
}
Err(e) => {
println!(" Error getting config: {}\n", e);
}
}
} else {
println!(" No services available\n");
}
}
Err(e) => {
println!(" Error: {}\n", e);
}
}
println!("8. Service control operations:");
match z.list() {
Ok(services) => {
if let Some(service_name) = services.first() {
println!(" Operating on service: {}", service_name);
match z.restart(service_name) {
Ok(_) => println!(),
Err(e) => println!(" ✗ Restart failed: {}\n", e),
}
match z.status(service_name) {
Ok(status) => {
println!(" Current state: {:?}\n", status.state);
}
Err(e) => {
println!(" ✗ Status check failed: {}\n", e);
}
}
}
}
Err(e) => {
println!(" Error: {}\n", e);
}
}
println!("9. System operations:");
match z.xinet_list() {
Ok(proxies) => {
println!(" Xinit proxies: {}", proxies.len());
for proxy in &proxies {
println!(" - {}", proxy);
}
println!();
}
Err(e) => {
println!(" No xinit proxies or error: {}\n", e);
}
}
println!("10. Cleaning up services:");
for service in &["database", "api_server", "api_server_v2"] {
match z.service_delete(service) {
Ok(_) => println!("✓ Deleted {}", service),
Err(e) => println!("✗ Error deleting {}: {}", service, e),
}
}
println!("\n✓ Done");
Ok(())
}