.. | ||
client.v | ||
openrpc.json | ||
openrpc.v | ||
README.md | ||
test.v | ||
types.v | ||
zinit.v |
Zinit Client Module
A well-documented V (Vlang) client library for interacting with the Zinit service manager via JSON-RPC over Unix socket.
Overview
This module provides a complete client implementation for the Zinit JSON-RPC API, allowing you to manage services, monitor system resources, and control the Zinit service manager programmatically.
Features
- Service Management: Start, stop, monitor, and forget services
- Service Configuration: Create, delete, and retrieve service configurations
- System Control: Shutdown, reboot, and HTTP server management
- Monitoring: Get service status, statistics, and resource usage
- Logging: Stream current logs and subscribe to log updates
- Error Handling: Comprehensive error handling with detailed error messages
- Type Safety: Strongly typed structs for all API responses
- Connection Management: Automatic connection handling with proper cleanup
Installation
Simply import the module in your V project:
import zinit
Quick Start
import zinit
fn main() {
// Create a client with default socket path (/tmp/zinit.sock)
mut client := zinit.new_default_client()
// Or specify a custom socket path
// mut client := zinit.new_client('/custom/path/to/zinit.sock')
defer {
client.disconnect()
}
// List all services
services := client.service_list() or {
eprintln('Error: ${err}')
return
}
for name, state in services {
println('${name}: ${state}')
}
}
API Reference
Client Creation
new_client(socket_path string) &Client
Creates a new zinit client with a custom socket path.
new_default_client() &Client
Creates a new zinit client with the default socket path (/tmp/zinit.sock
).
Connection Management
connect() !
Establishes a connection to the zinit Unix socket. Called automatically by API methods.
disconnect()
Closes the connection to the zinit Unix socket. Should be called when done with the client.
Service Management
service_list() !map[string]string
Lists all services managed by Zinit.
Returns: A map of service names to their current states.
services := client.service_list()!
for name, state in services {
println('${name}: ${state}')
}
service_status(name string) !ServiceStatus
Shows detailed status information for a specific service.
Parameters:
name
: The name of the service
Returns: ServiceStatus
struct with detailed information.
status := client.service_status('redis')!
println('Service: ${status.name}')
println('State: ${status.state}')
println('PID: ${status.pid}')
service_start(name string) !
Starts a service.
Parameters:
name
: The name of the service to start
service_stop(name string) !
Stops a service.
Parameters:
name
: The name of the service to stop
service_monitor(name string) !
Starts monitoring a service. The service configuration is loaded from the config directory.
Parameters:
name
: The name of the service to monitor
service_forget(name string) !
Stops monitoring a service. You can only forget a stopped service.
Parameters:
name
: The name of the service to forget
service_kill(name string, signal string) !
Sends a signal to a running service.
Parameters:
name
: The name of the service to send the signal tosignal
: The signal to send (e.g., "SIGTERM", "SIGKILL")
Service Configuration
service_create(name string, config ServiceConfig) !string
Creates a new service configuration file.
Parameters:
name
: The name of the service to createconfig
: The service configuration
Returns: Result message.
config := zinit.ServiceConfig{
exec: '/usr/bin/redis-server'
oneshot: false
log: 'stdout'
env: {
'REDIS_PORT': '6379'
}
shutdown_timeout: 30
}
result := client.service_create('redis', config)!
println('Service created: ${result}')
service_delete(name string) !string
Deletes a service configuration file.
Parameters:
name
: The name of the service to delete
Returns: Result message.
service_get(name string) !ServiceConfig
Gets a service configuration file.
Parameters:
name
: The name of the service to get
Returns: ServiceConfig
struct with the service configuration.
Service Statistics
service_stats(name string) !ServiceStats
Gets memory and CPU usage statistics for a service.
Parameters:
name
: The name of the service to get stats for
Returns: ServiceStats
struct with usage information.
stats := client.service_stats('redis')!
println('Memory Usage: ${stats.memory_usage / 1024 / 1024} MB')
println('CPU Usage: ${stats.cpu_usage}%')
System Operations
system_shutdown() !
Stops all services and powers off the system.
⚠️ Warning: This will actually shut down the system!
system_reboot() !
Stops all services and reboots the system.
⚠️ Warning: This will actually reboot the system!
system_start_http_server(address string) !string
Starts an HTTP/RPC server at the specified address.
Parameters:
address
: The network address to bind the server to (e.g., "127.0.0.1:8080")
Returns: Result message.
system_stop_http_server() !
Stops the HTTP/RPC server if running.
Logging
stream_current_logs(name ?string) ![]string
Gets current logs from zinit and monitored services.
Parameters:
name
: Optional service name filter. If provided, only logs from this service will be returned.
Returns: Array of log strings.
// Get all logs
all_logs := client.stream_current_logs(none)!
// Get logs for a specific service
redis_logs := client.stream_current_logs('redis')!
stream_subscribe_logs(name ?string) !string
Subscribes to log messages generated by zinit and monitored services.
Parameters:
name
: Optional service name filter.
Returns: A single log message.
Note: For continuous streaming, call this method repeatedly.
API Discovery
rpc_discover() !map[string]interface{}
Returns the OpenRPC specification for the API.
Returns: The complete OpenRPC specification as a map.
Data Types
ServiceConfig
Represents the configuration for a zinit service.
struct ServiceConfig {
pub mut:
exec string // Command to run
oneshot bool // Whether the service should be restarted
after []string // Services that must be running before this one starts
log string // How to handle service output (null, ring, stdout)
env map[string]string // Environment variables for the service
shutdown_timeout int // Maximum time to wait for service to stop during shutdown
}
ServiceStatus
Represents the detailed status information for a service.
struct ServiceStatus {
pub mut:
name string // Service name
pid int // Process ID of the running service (if running)
state string // Current state of the service (Running, Success, Error, etc.)
target string // Target state of the service (Up, Down)
after map[string]string // Dependencies of the service and their states
}
ServiceStats
Represents memory and CPU usage statistics for a service.
struct ServiceStats {
pub mut:
name string // Service name
pid int // Process ID of the service
memory_usage i64 // Memory usage in bytes
cpu_usage f64 // CPU usage as a percentage (0-100)
children []ChildStats // Stats for child processes
}
ChildStats
Represents statistics for a child process.
struct ChildStats {
pub mut:
pid int // Process ID of the child process
memory_usage i64 // Memory usage in bytes
cpu_usage f64 // CPU usage as a percentage (0-100)
}
Error Handling
The client provides comprehensive error handling through V's error system. All API methods that can fail return a result type (!
).
ZinitError
Custom error type for zinit-specific errors.
struct ZinitError {
pub mut:
code int // Error code
message string // Error message
data string // Additional error data
}
Common error codes:
-32000
: Service not found-32001
: Service already monitored-32002
: Service is up-32003
: Service is down-32004
: Invalid signal-32005
: Config error-32006
: Shutting down-32007
: Service already exists-32008
: Service file error
Examples
See example.v
for comprehensive usage examples covering all API methods.
Basic Service Management
import zinit
fn manage_service() ! {
mut client := zinit.new_default_client()
defer { client.disconnect() }
// Create a service
config := zinit.ServiceConfig{
exec: '/usr/bin/nginx'
oneshot: false
log: 'stdout'
after: ['network']
}
client.service_create('nginx', config)!
client.service_monitor('nginx')!
client.service_start('nginx')!
// Check status
status := client.service_status('nginx')!
println('Nginx is ${status.state}')
// Get statistics
stats := client.service_stats('nginx')!
println('Memory: ${stats.memory_usage / 1024 / 1024} MB')
}
Log Monitoring
import zinit
import time
fn monitor_logs() ! {
mut client := zinit.new_default_client()
defer { client.disconnect() }
// Get current logs
logs := client.stream_current_logs(none)!
for log in logs {
println(log)
}
// Subscribe to new logs (simplified example)
for i in 0..10 {
log_entry := client.stream_subscribe_logs(none) or { continue }
println('New log: ${log_entry}')
time.sleep(1 * time.second)
}
}
Thread Safety
The client is not thread-safe. If you need to use it from multiple threads, you should create separate client instances or implement your own synchronization.
Requirements
- V compiler
- Unix-like operating system (for Unix socket support)
- Running Zinit service manager
License
This module follows the same license as the parent project.