zinit 0.3.7

Process supervisor with dependency management
Documentation
//! Example: Dynamically create and manage a service
//!
//! This example demonstrates how to:
//! - Create a new service configuration
//! - Add it to the supervisor
//! - Start, stop, and delete it
//! - Check its status
//!
//! Run with: cargo run --example create_service --features client

use std::collections::HashMap;
use zinit::{RestartPolicy, ServiceClass, ServiceConfig, ServiceDef, ZinitClient};

fn main() {
    println!("Connecting to zinit supervisor...");
    let mut client = match ZinitClient::connect_default() {
        Ok(c) => c,
        Err(e) => {
            eprintln!("✗ Failed to connect: {}", e);
            std::process::exit(1);
        }
    };

    // Create a simple service that outputs a message and exits
    let service_name = "example-hello";
    println!("\n=== Creating Service: {} ===\n", service_name);

    // Build the service configuration
    let mut config = ServiceConfig::default();
    config.service = ServiceDef {
        name: service_name.to_string(),
        exec: "echo 'Hello from zinit!'".to_string(),
        dir: None,
        env: HashMap::new(),
        status: "start".to_string(),
        class: ServiceClass::User,
        critical: false,
        oneshot: true, // Exit without restarting
    };

    // Add the service (persist=false means it's ephemeral)
    match client.add(&config, false) {
        Ok(result) => {
            println!("✓ Service created: {}", result.name);
            if let Some(path) = result.path {
                println!("  Config path: {}", path);
            }
        }
        Err(e) => {
            eprintln!("✗ Failed to create service: {}", e);
            std::process::exit(1);
        }
    }

    // Wait a moment for the service to start
    std::thread::sleep(std::time::Duration::from_millis(500));

    // Get the service status
    println!("\n=== Service Status ===\n");
    match client.status(service_name) {
        Ok(status) => {
            println!("State:      {}", status.state);
            println!("PID:        {}", status.pid);
            if let Some(exit_code) = status.exit_code {
                println!("Exit Code:  {}", exit_code);
            }
        }
        Err(e) => {
            eprintln!("✗ Failed to get status: {}", e);
        }
    }

    // Check if running
    match client.is_running(service_name) {
        Ok(running) => {
            println!("Running:    {}", if running { "yes" } else { "no" });
        }
        Err(e) => {
            eprintln!("✗ Failed to check if running: {}", e);
        }
    }

    // Get logs
    println!("\n=== Service Logs ===\n");
    match client.logs(Some(service_name), Some(10)) {
        Ok(logs) => {
            for log_line in logs {
                println!("{}: {}", log_line.service, log_line.content);
            }
        }
        Err(e) => {
            eprintln!("✗ Failed to get logs: {}", e);
        }
    }

    // Delete the service
    println!("\n=== Deleting Service ===\n");
    match client.delete(service_name) {
        Ok(_) => {
            println!("✓ Service deleted");
        }
        Err(e) => {
            eprintln!("✗ Failed to delete service: {}", e);
        }
    }

    println!("\n✓ Done");
}