Update git remote URL from git.ourworld.tf to git.threefold.info
This commit is contained in:
parent
ae6966edb2
commit
fab2d199d1
124
examples/zinit_client_example.vsh
Executable file
124
examples/zinit_client_example.vsh
Executable file
@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.heroweb.clients.zinit
|
||||
import x.json2
|
||||
|
||||
// Create a new Zinit client with the default socket path
|
||||
mut client := zinit.new_default_client()
|
||||
|
||||
println('Connected to Zinit via OpenRPC')
|
||||
|
||||
// Example 1: Get the OpenRPC API specification
|
||||
println('\n=== Getting API Specification ===')
|
||||
api_spec_response := client.rpc_discover() or {
|
||||
println('Error getting API spec: ${err}')
|
||||
return
|
||||
}
|
||||
println('API Specification (first 100 chars): ${json2.encode(api_spec_response.spec)[..100]}...')
|
||||
|
||||
// Example 2: List all services
|
||||
println('\n=== Listing Services ===')
|
||||
service_list_response := client.service_list() or {
|
||||
println('Error listing services: ${err}')
|
||||
return
|
||||
}
|
||||
println('Services:')
|
||||
for name, state in service_list_response.services {
|
||||
println('- ${name}: ${state}')
|
||||
}
|
||||
|
||||
// Example 3: Get detailed status of a service (if any exist)
|
||||
if service_list_response.services.len > 0 {
|
||||
service_name := service_list_response.services.keys()[0]
|
||||
println('\n=== Getting Status for Service: ${service_name} ===')
|
||||
|
||||
status := client.service_status(service_name) or {
|
||||
println('Error getting status: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println('Service Status:')
|
||||
println('- Name: ${status.name}')
|
||||
println('- PID: ${status.pid}')
|
||||
println('- State: ${status.state}')
|
||||
println('- Target: ${status.target}')
|
||||
println('- Dependencies:')
|
||||
for dep_name, dep_state in status.after {
|
||||
println(' - ${dep_name}: ${dep_state}')
|
||||
}
|
||||
|
||||
// Example 4: Get service stats
|
||||
println('\n=== Getting Stats for Service: ${service_name} ===')
|
||||
stats := client.service_stats(service_name) or {
|
||||
println('Error getting stats: ${err}')
|
||||
println('Note: Stats are only available for running services')
|
||||
return
|
||||
}
|
||||
|
||||
println('Service Stats:')
|
||||
println('- Memory Usage: ${stats.memory_usage} bytes (${zinit.format_memory_usage(stats.memory_usage)})')
|
||||
println('- CPU Usage: ${stats.cpu_usage}% (${zinit.format_cpu_usage(stats.cpu_usage)})')
|
||||
if stats.children.len > 0 {
|
||||
println('- Child Processes:')
|
||||
for child in stats.children {
|
||||
println(' - PID: ${child.pid}, Memory: ${zinit.format_memory_usage(child.memory_usage)}, CPU: ${zinit.format_cpu_usage(child.cpu_usage)}')
|
||||
}
|
||||
}
|
||||
|
||||
// Example 5: Get logs for a service
|
||||
println('\n=== Getting Logs for Service: ${service_name} ===')
|
||||
logs_response := client.stream_current_logs(service_name) or {
|
||||
println('Error getting logs: ${err}')
|
||||
return
|
||||
}
|
||||
println('Service logs:')
|
||||
for log in logs_response.logs {
|
||||
println('- ${log}')
|
||||
}
|
||||
} else {
|
||||
println('\nNo services found to query')
|
||||
}
|
||||
|
||||
// Example 6: Create a new service (commented out for safety)
|
||||
/*
|
||||
println('\n=== Creating a New Service ===')
|
||||
new_service_config := zinit.ServiceConfig{
|
||||
exec: '/bin/echo "Hello from Zinit"'
|
||||
oneshot: true
|
||||
after: []string{}
|
||||
log: zinit.log_stdout
|
||||
env: {
|
||||
'ENV_VAR': 'value'
|
||||
}
|
||||
}
|
||||
|
||||
create_response := client.service_create('example_service', new_service_config) or {
|
||||
println('Error creating service: ${err}')
|
||||
return
|
||||
}
|
||||
println('Service created: ${create_response.path}')
|
||||
|
||||
// Start the service
|
||||
client.service_start('example_service') or {
|
||||
println('Error starting service: ${err}')
|
||||
return
|
||||
}
|
||||
println('Service started')
|
||||
|
||||
// Delete the service when done
|
||||
client.service_stop('example_service') or {
|
||||
println('Error stopping service: ${err}')
|
||||
return
|
||||
}
|
||||
client.service_forget('example_service') or {
|
||||
println('Error forgetting service: ${err}')
|
||||
return
|
||||
}
|
||||
delete_response := client.service_delete('example_service') or {
|
||||
println('Error deleting service: ${err}')
|
||||
return
|
||||
}
|
||||
println('Service deleted: ${delete_response.result}')
|
||||
*/
|
||||
|
||||
println('\nZinit OpenRPC client example completed')
|
66
examples/zinit_rpc_example.vsh
Executable file
66
examples/zinit_rpc_example.vsh
Executable file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc
|
||||
import freeflowuniverse.herolib.clients.zinit
|
||||
import json
|
||||
|
||||
// We'll use the ServiceStatusResponse from the zinit module
|
||||
// No need to define our own struct
|
||||
|
||||
// Create a client using the Unix socket transport
|
||||
mut cl := jsonrpc.new_unix_socket_client("/tmp/zinit.sock")
|
||||
|
||||
// Example 1: Discover the API using rpc_discover
|
||||
// Create a request for rpc_discover method with empty parameters
|
||||
discover_request := jsonrpc.new_request_generic('rpc.discover', []string{})
|
||||
|
||||
// Send the request and receive the OpenRPC specification as a JSON string
|
||||
println('Sending rpc_discover request...')
|
||||
println('This will return the OpenRPC specification for the API')
|
||||
|
||||
// Use map[string]string for the result to avoid json2.Any issues
|
||||
api_spec_raw := cl.send[[]string, string](discover_request)!
|
||||
|
||||
// Parse the JSON string manually
|
||||
println('API Specification (raw):')
|
||||
println(api_spec_raw)
|
||||
|
||||
// Example 2: List all services
|
||||
// Create a request for service_list method with empty parameters
|
||||
list_request := jsonrpc.new_request_generic('service_list', []string{})
|
||||
|
||||
// Send the request and receive a map of service names to states
|
||||
println('\nSending service_list request...')
|
||||
service_list := cl.send[[]string, map[string]string](list_request)!
|
||||
|
||||
// Display the service list
|
||||
println('Service List:')
|
||||
println(service_list)
|
||||
|
||||
// Example 3: Get status of a specific service
|
||||
// First, check if we have any services to query
|
||||
if service_list.len > 0 {
|
||||
// Get the first service name from the list
|
||||
service_name := service_list.keys()[0]
|
||||
|
||||
// Create a request for service_status method with the service name as parameter
|
||||
// The parameter for service_status is a single string (service name)
|
||||
status_request := jsonrpc.new_request_generic('service_status', service_name)
|
||||
|
||||
// Send the request and receive a ServiceStatusResponse object
|
||||
println('\nSending service_status request for service: $service_name')
|
||||
service_status := cl.send[string, zinit.ServiceStatusResponse](status_request)!
|
||||
|
||||
// Display the service status details
|
||||
println('Service Status:')
|
||||
println('- Name: ${service_status.name}')
|
||||
println('- PID: ${service_status.pid}')
|
||||
println('- State: ${service_status.state}')
|
||||
println('- Target: ${service_status.target}')
|
||||
println('- Dependencies:')
|
||||
for dep_name, dep_state in service_status.after {
|
||||
println(' - $dep_name: $dep_state')
|
||||
}
|
||||
} else {
|
||||
println('\nNo services found to query status')
|
||||
}
|
0
src/agentui/controllers/fake_data.v
Normal file
0
src/agentui/controllers/fake_data.v
Normal file
@ -7,13 +7,13 @@ pub:
|
||||
}
|
||||
|
||||
// get_all_processes returns all processes in the system
|
||||
pub fn (pc &ProcessController) get_all_processes() []Process {
|
||||
pub fn (pc &ProcessController) get_all_processes() ![]Process {
|
||||
// For now using fake data, will be replaced with openrpc calls
|
||||
return get_all_processes()
|
||||
}
|
||||
|
||||
// get_process_by_pid returns a specific process by PID
|
||||
pub fn (pc &ProcessController) get_process_by_pid(pid int) ?Process {
|
||||
pub fn (pc &ProcessController) get_process_by_pid(pid int) !Process {
|
||||
processes := get_all_processes()
|
||||
for process in processes {
|
||||
if process.pid == pid {
|
||||
|
@ -1,4 +1,6 @@
|
||||
module controllers
|
||||
import freeflowuniverse.herolib.schemas.openrpc
|
||||
|
||||
// OpenRPCController handles OpenRPC-related operations
|
||||
pub struct OpenRPCController {
|
||||
pub:
|
||||
@ -12,7 +14,7 @@ pub fn (oc &OpenRPCController) get_all_specs() []OpenRPCSpec {
|
||||
}
|
||||
|
||||
// get_spec_by_name returns a specific OpenRPC specification by name
|
||||
pub fn (oc &OpenRPCController) get_spec_by_name(name string) ?OpenRPCSpec {
|
||||
pub fn (oc &OpenRPCController) get_spec_by_name(name string) !openrpc.OpenRPC {
|
||||
specs := get_all_openrpc_specs()
|
||||
for spec in specs {
|
||||
if spec.title.to_lower() == name.to_lower() {
|
||||
|
@ -1,406 +0,0 @@
|
||||
# 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:
|
||||
|
||||
```v
|
||||
import zinit
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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 to
|
||||
- `signal`: 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 create
|
||||
- `config`: The service configuration
|
||||
|
||||
**Returns**: Result message.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
// 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.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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.
|
||||
|
||||
```v
|
||||
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
|
||||
|
||||
```v
|
||||
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
|
||||
|
||||
```v
|
||||
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.
|
@ -1,211 +0,0 @@
|
||||
module zinit
|
||||
|
||||
import net.unix
|
||||
import json
|
||||
import time
|
||||
|
||||
// service_status shows detailed status information for a specific service
|
||||
// name: the name of the service
|
||||
pub fn (mut c Client) service_status(name string) !ServiceStatus {
|
||||
params := [name]
|
||||
response := c.send_request('service_status', params)!
|
||||
|
||||
result_map := response.result as map[string]interface{}
|
||||
|
||||
mut after_map := map[string]string{}
|
||||
if after_raw := result_map['after'] {
|
||||
if after_obj := after_raw as map[string]interface{} {
|
||||
for key, value in after_obj {
|
||||
after_map[key] = value.str()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ServiceStatus{
|
||||
name: result_map['name'] or { '' }.str()
|
||||
pid: result_map['pid'] or { 0 }.int()
|
||||
state: result_map['state'] or { '' }.str()
|
||||
target: result_map['target'] or { '' }.str()
|
||||
after: after_map
|
||||
}
|
||||
}
|
||||
|
||||
// service_start starts a service
|
||||
// name: the name of the service to start
|
||||
pub fn (mut c Client) service_start(name string) ! {
|
||||
params := [name]
|
||||
c.send_request('service_start', params)!
|
||||
}
|
||||
|
||||
// service_stop stops a service
|
||||
// name: the name of the service to stop
|
||||
pub fn (mut c Client) service_stop(name string) ! {
|
||||
params := [name]
|
||||
c.send_request('service_stop', params)!
|
||||
}
|
||||
|
||||
// service_monitor starts monitoring a service
|
||||
// The service configuration is loaded from the config directory
|
||||
// name: the name of the service to monitor
|
||||
pub fn (mut c Client) service_monitor(name string) ! {
|
||||
params := [name]
|
||||
c.send_request('service_monitor', params)!
|
||||
}
|
||||
|
||||
// service_forget stops monitoring a service
|
||||
// You can only forget a stopped service
|
||||
// name: the name of the service to forget
|
||||
pub fn (mut c Client) service_forget(name string) ! {
|
||||
params := [name]
|
||||
c.send_request('service_forget', params)!
|
||||
}
|
||||
|
||||
// service_kill sends a signal to a running service
|
||||
// name: the name of the service to send the signal to
|
||||
// signal: the signal to send (e.g., SIGTERM, SIGKILL)
|
||||
pub fn (mut c Client) service_kill(name string, signal string) ! {
|
||||
params := [name, signal]
|
||||
c.send_request('service_kill', params)!
|
||||
}
|
||||
|
||||
// service_create creates a new service configuration file
|
||||
// name: the name of the service to create
|
||||
// config: the service configuration
|
||||
pub fn (mut c Client) service_create(name string, config ServiceConfig) !string {
|
||||
params := [name, config]
|
||||
response := c.send_request('service_create', params)!
|
||||
return response.result.str()
|
||||
}
|
||||
|
||||
// service_delete deletes a service configuration file
|
||||
// name: the name of the service to delete
|
||||
pub fn (mut c Client) service_delete(name string) !string {
|
||||
params := [name]
|
||||
response := c.send_request('service_delete', params)!
|
||||
return response.result.str()
|
||||
}
|
||||
|
||||
// service_get gets a service configuration file
|
||||
// name: the name of the service to get
|
||||
pub fn (mut c Client) service_get(name string) !ServiceConfig {
|
||||
params := [name]
|
||||
response := c.send_request('service_get', params)!
|
||||
|
||||
result_map := response.result as map[string]interface{}
|
||||
|
||||
mut after_list := []string{}
|
||||
if after_raw := result_map['after'] {
|
||||
if after_array := after_raw as []interface{} {
|
||||
for item in after_array {
|
||||
after_list << item.str()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mut env_map := map[string]string{}
|
||||
if env_raw := result_map['env'] {
|
||||
if env_obj := env_raw as map[string]interface{} {
|
||||
for key, value in env_obj {
|
||||
env_map[key] = value.str()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ServiceConfig{
|
||||
exec: result_map['exec'] or { '' }.str()
|
||||
oneshot: result_map['oneshot'] or { false }.bool()
|
||||
after: after_list
|
||||
log: result_map['log'] or { '' }.str()
|
||||
env: env_map
|
||||
shutdown_timeout: result_map['shutdown_timeout'] or { 0 }.int()
|
||||
}
|
||||
}
|
||||
|
||||
// service_stats gets memory and CPU usage statistics for a service
|
||||
// name: the name of the service to get stats for
|
||||
pub fn (mut c Client) service_stats(name string) !ServiceStats {
|
||||
params := [name]
|
||||
response := c.send_request('service_stats', params)!
|
||||
|
||||
result_map := response.result as map[string]interface{}
|
||||
|
||||
mut children_list := []ChildStats{}
|
||||
if children_raw := result_map['children'] {
|
||||
if children_array := children_raw as []interface{} {
|
||||
for child_raw in children_array {
|
||||
if child_map := child_raw as map[string]interface{} {
|
||||
children_list << ChildStats{
|
||||
pid: child_map['pid'] or { 0 }.int()
|
||||
memory_usage: child_map['memory_usage'] or { i64(0) }.i64()
|
||||
cpu_usage: child_map['cpu_usage'] or { 0.0 }.f64()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ServiceStats{
|
||||
name: result_map['name'] or { '' }.str()
|
||||
pid: result_map['pid'] or { 0 }.int()
|
||||
memory_usage: result_map['memory_usage'] or { i64(0) }.i64()
|
||||
cpu_usage: result_map['cpu_usage'] or { 0.0 }.f64()
|
||||
children: children_list
|
||||
}
|
||||
}
|
||||
|
||||
// system_shutdown stops all services and powers off the system
|
||||
pub fn (mut c Client) system_shutdown() ! {
|
||||
c.send_request('system_shutdown', []interface{})!
|
||||
}
|
||||
|
||||
// system_reboot stops all services and reboots the system
|
||||
pub fn (mut c Client) system_reboot() ! {
|
||||
c.send_request('system_reboot', []interface{})!
|
||||
}
|
||||
|
||||
// system_start_http_server starts an HTTP/RPC server at the specified address
|
||||
// address: the network address to bind the server to (e.g., '127.0.0.1:8080')
|
||||
pub fn (mut c Client) system_start_http_server(address string) !string {
|
||||
params := [address]
|
||||
response := c.send_request('system_start_http_server', params)!
|
||||
return response.result.str()
|
||||
}
|
||||
|
||||
// system_stop_http_server stops the HTTP/RPC server if running
|
||||
pub fn (mut c Client) system_stop_http_server() ! {
|
||||
c.send_request('system_stop_http_server', []interface{})!
|
||||
}
|
||||
|
||||
// stream_current_logs gets current logs from zinit and monitored services
|
||||
// name: optional service name filter. If provided, only logs from this service will be returned
|
||||
pub fn (mut c Client) stream_current_logs(name ?string) ![]string {
|
||||
mut params := []interface{}
|
||||
if service_name := name {
|
||||
params << service_name
|
||||
}
|
||||
|
||||
response := c.send_request('stream_currentLogs', params)!
|
||||
|
||||
if logs_array := response.result as []interface{} {
|
||||
mut logs := []string{}
|
||||
for log_entry in logs_array {
|
||||
logs << log_entry.str()
|
||||
}
|
||||
return logs
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// stream_subscribe_logs subscribes to log messages generated by zinit and monitored services
|
||||
// name: optional service name filter. If provided, only logs from this service will be returned
|
||||
// Note: This method returns a single log message. For continuous streaming, call this method repeatedly
|
||||
pub fn (mut c Client) stream_subscribe_logs(name ?string) !string {
|
||||
mut params := []interface{}
|
||||
if service_name := name {
|
||||
params << service_name
|
||||
}
|
||||
|
||||
response := c.send_request('stream_subscribeLogs', params)!
|
||||
return response.result.str()
|
||||
}
|
@ -1,873 +0,0 @@
|
||||
{
|
||||
"openrpc": "1.2.6",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Zinit JSON-RPC API",
|
||||
"description": "JSON-RPC 2.0 API for controlling and querying Zinit services",
|
||||
"license": {
|
||||
"name": "MIT"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"name": "Unix Socket",
|
||||
"url": "unix:///tmp/zinit.sock"
|
||||
}
|
||||
],
|
||||
"methods": [
|
||||
{
|
||||
"name": "rpc_discover",
|
||||
"description": "Returns the OpenRPC specification for the API",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "OpenRPCSpec",
|
||||
"description": "The OpenRPC specification",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Get API specification",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "OpenRPCSpecResult",
|
||||
"value": {
|
||||
"openrpc": "1.2.6",
|
||||
"info": {
|
||||
"version": "1.0.0",
|
||||
"title": "Zinit JSON-RPC API"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_list",
|
||||
"description": "Lists all services managed by Zinit",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "ServiceList",
|
||||
"description": "A map of service names to their current states",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"description": "Service state (Running, Success, Error, etc.)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "List all services",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "ServiceListResult",
|
||||
"value": {
|
||||
"service1": "Running",
|
||||
"service2": "Success",
|
||||
"service3": "Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_status",
|
||||
"description": "Shows detailed status information for a specific service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "ServiceStatus",
|
||||
"description": "Detailed status information for the service",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Service name"
|
||||
},
|
||||
"pid": {
|
||||
"type": "integer",
|
||||
"description": "Process ID of the running service (if running)"
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "Current state of the service (Running, Success, Error, etc.)"
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "Target state of the service (Up, Down)"
|
||||
},
|
||||
"after": {
|
||||
"type": "object",
|
||||
"description": "Dependencies of the service and their states",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"description": "State of the dependency"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Get status of redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "ServiceStatusResult",
|
||||
"value": {
|
||||
"name": "redis",
|
||||
"pid": 1234,
|
||||
"state": "Running",
|
||||
"target": "Up",
|
||||
"after": {
|
||||
"dependency1": "Success",
|
||||
"dependency2": "Running"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "service name \"unknown\" unknown"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_start",
|
||||
"description": "Starts a service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to start",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "StartResult",
|
||||
"description": "Result of the start operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Start redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "StartResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "service name \"unknown\" unknown"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_stop",
|
||||
"description": "Stops a service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to stop",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "StopResult",
|
||||
"description": "Result of the stop operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Stop redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "StopResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "service name \"unknown\" unknown"
|
||||
},
|
||||
{
|
||||
"code": -32003,
|
||||
"message": "Service is down",
|
||||
"data": "service \"redis\" is down"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_monitor",
|
||||
"description": "Starts monitoring a service. The service configuration is loaded from the config directory.",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to monitor",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "MonitorResult",
|
||||
"description": "Result of the monitor operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Monitor redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "MonitorResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32001,
|
||||
"message": "Service already monitored",
|
||||
"data": "service \"redis\" already monitored"
|
||||
},
|
||||
{
|
||||
"code": -32005,
|
||||
"message": "Config error",
|
||||
"data": "failed to load service configuration"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_forget",
|
||||
"description": "Stops monitoring a service. You can only forget a stopped service.",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to forget",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "ForgetResult",
|
||||
"description": "Result of the forget operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Forget redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "ForgetResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "service name \"unknown\" unknown"
|
||||
},
|
||||
{
|
||||
"code": -32002,
|
||||
"message": "Service is up",
|
||||
"data": "service \"redis\" is up"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_kill",
|
||||
"description": "Sends a signal to a running service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to send the signal to",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "signal",
|
||||
"description": "The signal to send (e.g., SIGTERM, SIGKILL)",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "KillResult",
|
||||
"description": "Result of the kill operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Send SIGTERM to redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
},
|
||||
{
|
||||
"name": "signal",
|
||||
"value": "SIGTERM"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "KillResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "service name \"unknown\" unknown"
|
||||
},
|
||||
{
|
||||
"code": -32003,
|
||||
"message": "Service is down",
|
||||
"data": "service \"redis\" is down"
|
||||
},
|
||||
{
|
||||
"code": -32004,
|
||||
"message": "Invalid signal",
|
||||
"data": "invalid signal: INVALID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "system_shutdown",
|
||||
"description": "Stops all services and powers off the system",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "ShutdownResult",
|
||||
"description": "Result of the shutdown operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Shutdown the system",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "ShutdownResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32006,
|
||||
"message": "Shutting down",
|
||||
"data": "system is already shutting down"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "system_reboot",
|
||||
"description": "Stops all services and reboots the system",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "RebootResult",
|
||||
"description": "Result of the reboot operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Reboot the system",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "RebootResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32006,
|
||||
"message": "Shutting down",
|
||||
"data": "system is already shutting down"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_create",
|
||||
"description": "Creates a new service configuration file",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to create",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "content",
|
||||
"description": "The service configuration content",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"exec": {
|
||||
"type": "string",
|
||||
"description": "Command to run"
|
||||
},
|
||||
"oneshot": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the service should be restarted"
|
||||
},
|
||||
"after": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Services that must be running before this one starts"
|
||||
},
|
||||
"log": {
|
||||
"type": "string",
|
||||
"enum": ["null", "ring", "stdout"],
|
||||
"description": "How to handle service output"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Environment variables for the service"
|
||||
},
|
||||
"shutdown_timeout": {
|
||||
"type": "integer",
|
||||
"description": "Maximum time to wait for service to stop during shutdown"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "CreateServiceResult",
|
||||
"description": "Result of the create operation",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"code": -32007,
|
||||
"message": "Service already exists",
|
||||
"data": "Service 'name' already exists"
|
||||
},
|
||||
{
|
||||
"code": -32008,
|
||||
"message": "Service file error",
|
||||
"data": "Failed to create service file"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_delete",
|
||||
"description": "Deletes a service configuration file",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to delete",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "DeleteServiceResult",
|
||||
"description": "Result of the delete operation",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "Service 'name' not found"
|
||||
},
|
||||
{
|
||||
"code": -32008,
|
||||
"message": "Service file error",
|
||||
"data": "Failed to delete service file"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_get",
|
||||
"description": "Gets a service configuration file",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to get",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "GetServiceResult",
|
||||
"description": "The service configuration",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "Service 'name' not found"
|
||||
},
|
||||
{
|
||||
"code": -32008,
|
||||
"message": "Service file error",
|
||||
"data": "Failed to read service file"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "service_stats",
|
||||
"description": "Get memory and CPU usage statistics for a service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the service to get stats for",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "ServiceStats",
|
||||
"description": "Memory and CPU usage statistics for the service",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Service name"
|
||||
},
|
||||
"pid": {
|
||||
"type": "integer",
|
||||
"description": "Process ID of the service"
|
||||
},
|
||||
"memory_usage": {
|
||||
"type": "integer",
|
||||
"description": "Memory usage in bytes"
|
||||
},
|
||||
"cpu_usage": {
|
||||
"type": "number",
|
||||
"description": "CPU usage as a percentage (0-100)"
|
||||
},
|
||||
"children": {
|
||||
"type": "array",
|
||||
"description": "Stats for child processes",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pid": {
|
||||
"type": "integer",
|
||||
"description": "Process ID of the child process"
|
||||
},
|
||||
"memory_usage": {
|
||||
"type": "integer",
|
||||
"description": "Memory usage in bytes"
|
||||
},
|
||||
"cpu_usage": {
|
||||
"type": "number",
|
||||
"description": "CPU usage as a percentage (0-100)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Get stats for redis service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "ServiceStatsResult",
|
||||
"value": {
|
||||
"name": "redis",
|
||||
"pid": 1234,
|
||||
"memory_usage": 10485760,
|
||||
"cpu_usage": 2.5,
|
||||
"children": [
|
||||
{
|
||||
"pid": 1235,
|
||||
"memory_usage": 5242880,
|
||||
"cpu_usage": 1.2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32000,
|
||||
"message": "Service not found",
|
||||
"data": "service name \"unknown\" unknown"
|
||||
},
|
||||
{
|
||||
"code": -32003,
|
||||
"message": "Service is down",
|
||||
"data": "service \"redis\" is down"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "system_start_http_server",
|
||||
"description": "Start an HTTP/RPC server at the specified address",
|
||||
"params": [
|
||||
{
|
||||
"name": "address",
|
||||
"description": "The network address to bind the server to (e.g., '127.0.0.1:8080')",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "StartHttpServerResult",
|
||||
"description": "Result of the start HTTP server operation",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Start HTTP server on localhost:8080",
|
||||
"params": [
|
||||
{
|
||||
"name": "address",
|
||||
"value": "127.0.0.1:8080"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "StartHttpServerResult",
|
||||
"value": "HTTP server started at 127.0.0.1:8080"
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32602,
|
||||
"message": "Invalid address",
|
||||
"data": "Invalid network address format"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "system_stop_http_server",
|
||||
"description": "Stop the HTTP/RPC server if running",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "StopHttpServerResult",
|
||||
"description": "Result of the stop HTTP server operation",
|
||||
"schema": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Stop the HTTP server",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "StopHttpServerResult",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"errors": [
|
||||
{
|
||||
"code": -32602,
|
||||
"message": "Server not running",
|
||||
"data": "No HTTP server is currently running"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stream_currentLogs",
|
||||
"description": "Get current logs from zinit and monitored services",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Optional service name filter. If provided, only logs from this service will be returned",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "LogsResult",
|
||||
"description": "Array of log strings",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Get all logs",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "LogsResult",
|
||||
"value": [
|
||||
"2023-01-01T12:00:00 redis: Starting service",
|
||||
"2023-01-01T12:00:01 nginx: Starting service"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Get logs for a specific service",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "LogsResult",
|
||||
"value": [
|
||||
"2023-01-01T12:00:00 redis: Starting service",
|
||||
"2023-01-01T12:00:02 redis: Service started"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stream_subscribeLogs",
|
||||
"description": "Subscribe to log messages generated by zinit and monitored services",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Optional service name filter. If provided, only logs from this service will be returned",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "LogSubscription",
|
||||
"description": "A subscription to log messages",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"name": "Subscribe to all logs",
|
||||
"params": [],
|
||||
"result": {
|
||||
"name": "LogSubscription",
|
||||
"value": "2023-01-01T12:00:00 redis: Service started"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Subscribe to filtered logs",
|
||||
"params": [
|
||||
{
|
||||
"name": "name",
|
||||
"value": "redis"
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "LogSubscription",
|
||||
"value": "2023-01-01T12:00:00 redis: Service started"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
module zinit
|
||||
|
||||
import freeflowuniverse.herolib.schemas.jsonrpc
|
||||
import net.unix
|
||||
import time
|
||||
import json
|
||||
|
||||
// UnixSocketTransport implements the jsonrpc.IRPCTransportClient interface for Unix domain sockets
|
||||
struct UnixSocketTransport {
|
||||
mut:
|
||||
socket_path string
|
||||
}
|
||||
|
||||
// new_unix_socket_transport creates a new Unix socket transport
|
||||
fn new_unix_socket_transport(socket_path string) &UnixSocketTransport {
|
||||
return &UnixSocketTransport{
|
||||
socket_path: socket_path
|
||||
}
|
||||
}
|
||||
|
||||
// send implements the jsonrpc.IRPCTransportClient interface
|
||||
fn (mut t UnixSocketTransport) send(request string, params jsonrpc.SendParams) !string {
|
||||
// Create a Unix domain socket client
|
||||
mut socket := unix.connect_stream(t.socket_path)!
|
||||
defer { socket.close() or {} }
|
||||
|
||||
// Set timeout if specified
|
||||
if params.timeout > 0 {
|
||||
socket.set_read_timeout(params.timeout * time.second)
|
||||
socket.set_write_timeout(params.timeout * time.second)
|
||||
}
|
||||
|
||||
// Send the request
|
||||
socket.write_string(request + '\n')!
|
||||
|
||||
// Read the response
|
||||
mut response := ''
|
||||
mut buf := []u8{len: 4096}
|
||||
|
||||
for {
|
||||
bytes_read := socket.read(mut buf)!
|
||||
if bytes_read <= 0 {
|
||||
break
|
||||
}
|
||||
response += buf[..bytes_read].bytestr()
|
||||
|
||||
// Check if we've received a complete JSON response
|
||||
if response.ends_with('}') {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
// Client provides a client interface to the zinit JSON-RPC API over Unix socket
|
||||
@[heap]
|
||||
pub struct Client {
|
||||
mut:
|
||||
socket_path string
|
||||
rpc_client &jsonrpc.Client
|
||||
request_id int
|
||||
}
|
||||
|
||||
// new_client creates a new zinit client instance
|
||||
// socket_path: path to the Unix socket (default: /tmp/zinit.sock)
|
||||
pub fn new_client(socket_path string) &Client {
|
||||
mut transport := new_unix_socket_transport(socket_path)
|
||||
mut rpc_client := jsonrpc.new_client(transport)
|
||||
|
||||
return &Client{
|
||||
socket_path: socket_path
|
||||
rpc_client: rpc_client
|
||||
request_id: 0
|
||||
}
|
||||
}
|
||||
|
||||
// new_default_client creates a new zinit client with default socket path
|
||||
pub fn new_default_client() &Client {
|
||||
return new_client('/tmp/zinit.sock')
|
||||
}
|
||||
|
||||
// rpc_discover returns the OpenRPC specification for the API
|
||||
pub fn (mut c Client) rpc_discover() !map[string]json.Any {
|
||||
send_params := jsonrpc.SendParams{
|
||||
timeout: 30
|
||||
retry: 1
|
||||
}
|
||||
|
||||
request := jsonrpc.new_request_generic('rpc_discover', []string{})
|
||||
result := c.rpc_client.send[[]string, map[string]json.Any](request, send_params)!
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// service_list lists all services managed by Zinit
|
||||
// Returns a map of service names to their current states
|
||||
pub fn (mut c Client) service_list() !map[string]string {
|
||||
send_params := jsonrpc.SendParams{
|
||||
timeout: 30
|
||||
retry: 1
|
||||
}
|
||||
|
||||
request := jsonrpc.new_request_generic('service_list', []string{})
|
||||
result := c.rpc_client.send[[]string, map[string]string](request, send_params)!
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// service_status shows detailed status information for a specific service
|
||||
// name: the name of the service
|
||||
pub fn (mut c Client) service_status(name string) !ServiceStatus {
|
||||
send_params := jsonrpc.SendParams{
|
||||
timeout: 30
|
||||
retry: 1
|
||||
}
|
||||
|
||||
request := jsonrpc.new_request_generic('service_status', [name])
|
||||
result_map := c.rpc_client.send[[string], map[string]json.Any](request, send_params)!
|
||||
|
||||
mut after_map := map[string]string{}
|
||||
if after_raw := result_map['after'] {
|
||||
if after_raw is map[string]json.Any {
|
||||
for key, value in after_raw {
|
||||
after_map[key] = value.str()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ServiceStatus{
|
||||
name: result_map['name'].str()
|
||||
pid: result_map['pid'].int()
|
||||
state: result_map['state'].str()
|
||||
target: result_map['target'].str()
|
||||
after: after_map
|
||||
}
|
||||
}
|
||||
|
||||
// service_start starts a service
|
||||
// name: the name of the service to start
|
||||
pub fn (mut c Client) service_start(name string) ! {
|
||||
send_params := jsonrpc.SendParams{
|
||||
timeout: 30
|
||||
retry: 1
|
||||
}
|
||||
|
||||
request := jsonrpc.new_request_generic('service_start', [name])
|
||||
c.rpc_client.send[[string], json.Any](request, send_params)!
|
||||
}
|
||||
|
||||
// service_stop stops a service
|
||||
// name: the name of the service to stop
|
||||
pub fn (mut c Client) service_stop(name string) ! {
|
||||
send_params := jsonrpc.SendParams{
|
||||
timeout: 30
|
||||
retry: 1
|
||||
}
|
||||
|
||||
request := jsonrpc.new_request_generic('service_stop', [name])
|
||||
c.rpc_client.send[[string], json.Any](request, send_params)!
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
module zinit
|
||||
|
||||
import time
|
||||
|
||||
// Basic tests for the zinit client module
|
||||
// Note: These tests require a running zinit instance at /tmp/zinit.sock
|
||||
|
||||
// test_client_creation tests basic client creation
|
||||
fn test_client_creation() {
|
||||
// Test default client creation
|
||||
client1 := new_default_client()
|
||||
assert client1.socket_path == '/tmp/zinit.sock'
|
||||
|
||||
// Test custom client creation
|
||||
client2 := new_client('/custom/path/zinit.sock')
|
||||
assert client2.socket_path == '/custom/path/zinit.sock'
|
||||
|
||||
println('✓ Client creation tests passed')
|
||||
}
|
||||
|
||||
// test_service_config tests ServiceConfig struct
|
||||
fn test_service_config() {
|
||||
config := ServiceConfig{
|
||||
exec: '/usr/bin/test'
|
||||
oneshot: true
|
||||
after: ['dependency1', 'dependency2']
|
||||
log: 'stdout'
|
||||
env: {
|
||||
'TEST_VAR': 'test_value'
|
||||
'PATH': '/usr/bin:/bin'
|
||||
}
|
||||
shutdown_timeout: 30
|
||||
}
|
||||
|
||||
assert config.exec == '/usr/bin/test'
|
||||
assert config.oneshot == true
|
||||
assert config.after.len == 2
|
||||
assert config.after[0] == 'dependency1'
|
||||
assert config.env['TEST_VAR'] == 'test_value'
|
||||
assert config.shutdown_timeout == 30
|
||||
|
||||
println('✓ ServiceConfig tests passed')
|
||||
}
|
||||
|
||||
// test_service_status tests ServiceStatus struct
|
||||
fn test_service_status() {
|
||||
mut after_map := map[string]string{}
|
||||
after_map['dep1'] = 'Running'
|
||||
after_map['dep2'] = 'Success'
|
||||
|
||||
status := ServiceStatus{
|
||||
name: 'test_service'
|
||||
pid: 1234
|
||||
state: 'Running'
|
||||
target: 'Up'
|
||||
after: after_map
|
||||
}
|
||||
|
||||
assert status.name == 'test_service'
|
||||
assert status.pid == 1234
|
||||
assert status.state == 'Running'
|
||||
assert status.target == 'Up'
|
||||
assert status.after['dep1'] == 'Running'
|
||||
|
||||
println('✓ ServiceStatus tests passed')
|
||||
}
|
||||
|
||||
// test_service_stats tests ServiceStats and ChildStats structs
|
||||
fn test_service_stats() {
|
||||
child1 := ChildStats{
|
||||
pid: 1235
|
||||
memory_usage: 1024 * 1024 // 1MB
|
||||
cpu_usage: 2.5
|
||||
}
|
||||
|
||||
child2 := ChildStats{
|
||||
pid: 1236
|
||||
memory_usage: 2 * 1024 * 1024 // 2MB
|
||||
cpu_usage: 1.2
|
||||
}
|
||||
|
||||
stats := ServiceStats{
|
||||
name: 'test_service'
|
||||
pid: 1234
|
||||
memory_usage: 10 * 1024 * 1024 // 10MB
|
||||
cpu_usage: 5.0
|
||||
children: [child1, child2]
|
||||
}
|
||||
|
||||
assert stats.name == 'test_service'
|
||||
assert stats.pid == 1234
|
||||
assert stats.memory_usage == 10 * 1024 * 1024
|
||||
assert stats.cpu_usage == 5.0
|
||||
assert stats.children.len == 2
|
||||
assert stats.children[0].pid == 1235
|
||||
assert stats.children[1].memory_usage == 2 * 1024 * 1024
|
||||
|
||||
println('✓ ServiceStats tests passed')
|
||||
}
|
||||
|
||||
// test_zinit_error tests ZinitError struct and error message
|
||||
fn test_zinit_error() {
|
||||
error := ZinitError{
|
||||
code: -32000
|
||||
message: 'Service not found'
|
||||
data: 'service name "unknown" unknown'
|
||||
}
|
||||
|
||||
assert error.code == -32000
|
||||
assert error.message == 'Service not found'
|
||||
assert error.data == 'service name "unknown" unknown'
|
||||
|
||||
error_msg := error.msg()
|
||||
assert error_msg.contains('Zinit Error -32000')
|
||||
assert error_msg.contains('Service not found')
|
||||
assert error_msg.contains('service name "unknown" unknown')
|
||||
|
||||
println('✓ ZinitError tests passed')
|
||||
}
|
||||
|
||||
// test_connection_handling tests connection management (without actual connection)
|
||||
fn test_connection_handling() {
|
||||
mut client := new_default_client()
|
||||
|
||||
// Initially no connection
|
||||
assert client.conn == none
|
||||
|
||||
// Test disconnect on non-connected client (should not panic)
|
||||
client.disconnect()
|
||||
assert client.conn == none
|
||||
|
||||
println('✓ Connection handling tests passed')
|
||||
}
|
||||
|
||||
// integration_test_basic performs basic integration tests if zinit is available
|
||||
fn integration_test_basic() {
|
||||
mut client := new_default_client()
|
||||
defer {
|
||||
client.disconnect()
|
||||
}
|
||||
|
||||
println('Running integration tests (requires running zinit)...')
|
||||
|
||||
// Test RPC discovery
|
||||
spec := client.rpc_discover() or {
|
||||
println('⚠ Integration test skipped: zinit not available (${err})')
|
||||
return
|
||||
}
|
||||
|
||||
println('✓ RPC discovery successful')
|
||||
|
||||
// Test service list
|
||||
services := client.service_list() or {
|
||||
println('✗ Service list failed: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println('✓ Service list successful (${services.len} services)')
|
||||
|
||||
// If there are services, test getting status of the first one
|
||||
if services.len > 0 {
|
||||
service_name := services.keys()[0]
|
||||
status := client.service_status(service_name) or {
|
||||
println('⚠ Could not get status for ${service_name}: ${err}')
|
||||
return
|
||||
}
|
||||
println('✓ Service status for ${service_name}: ${status.state}')
|
||||
}
|
||||
|
||||
// Test getting current logs
|
||||
logs := client.stream_current_logs(none) or {
|
||||
println('⚠ Could not get logs: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
println('✓ Log streaming successful (${logs.len} log entries)')
|
||||
|
||||
println('✓ All integration tests passed')
|
||||
}
|
||||
|
||||
// run_all_tests runs all test functions
|
||||
pub fn run_all_tests() {
|
||||
println('Running Zinit Client Tests...\n')
|
||||
|
||||
// Unit tests
|
||||
test_client_creation()
|
||||
test_service_config()
|
||||
test_service_status()
|
||||
test_service_stats()
|
||||
test_zinit_error()
|
||||
test_connection_handling()
|
||||
|
||||
println('\n--- Unit Tests Complete ---\n')
|
||||
|
||||
// Integration tests (optional, requires running zinit)
|
||||
integration_test_basic()
|
||||
|
||||
println('\n--- All Tests Complete ---')
|
||||
}
|
||||
|
||||
// main function for running tests directly
|
||||
fn main() {
|
||||
run_all_tests()
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
module zinit
|
||||
|
||||
// ServiceConfig represents the configuration for a zinit service
|
||||
pub 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
|
||||
pub 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
|
||||
pub 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
|
||||
pub 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)
|
||||
}
|
||||
|
||||
// ZinitError represents an error returned by the zinit API
|
||||
pub struct ZinitError {
|
||||
pub mut:
|
||||
code int // Error code
|
||||
message string // Error message
|
||||
data string // Additional error data
|
||||
}
|
||||
|
||||
// Error implements the error interface for ZinitError
|
||||
pub fn (e ZinitError) msg() string {
|
||||
return 'Zinit Error ${e.code}: ${e.message} - ${e.data}'
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
module zinit
|
||||
|
||||
// Zinit Client Module
|
||||
//
|
||||
// This module provides a comprehensive V (Vlang) client library for interacting
|
||||
// with the Zinit service manager via JSON-RPC over Unix socket.
|
||||
//
|
||||
// The module includes:
|
||||
// - Complete type definitions for all API structures
|
||||
// - Full client implementation with all OpenRPC methods
|
||||
// - Comprehensive error handling
|
||||
// - Connection management
|
||||
// - Well-documented API with examples
|
||||
//
|
||||
// Usage:
|
||||
// import zinit
|
||||
//
|
||||
// mut client := zinit.new_default_client()
|
||||
// defer { client.disconnect() }
|
||||
//
|
||||
// services := client.service_list()!
|
||||
// for name, state in services {
|
||||
// println('${name}: ${state}')
|
||||
// }
|
||||
//
|
||||
// For detailed documentation, see README.md
|
||||
// For usage examples, see example.v
|
||||
// For tests, see test.v
|
||||
|
||||
// Module version information
|
||||
pub const (
|
||||
version = '1.0.0'
|
||||
author = 'Hero Code'
|
||||
license = 'MIT'
|
||||
)
|
||||
|
||||
// Default socket path for zinit
|
||||
pub const default_socket_path = '/tmp/zinit.sock'
|
||||
|
||||
// Common service states
|
||||
pub const (
|
||||
state_running = 'Running'
|
||||
state_success = 'Success'
|
||||
state_error = 'Error'
|
||||
state_stopped = 'Stopped'
|
||||
state_failed = 'Failed'
|
||||
)
|
||||
|
||||
// Common service targets
|
||||
pub const (
|
||||
target_up = 'Up'
|
||||
target_down = 'Down'
|
||||
)
|
||||
|
||||
// Common log types
|
||||
pub const (
|
||||
log_null = 'null'
|
||||
log_ring = 'ring'
|
||||
log_stdout = 'stdout'
|
||||
)
|
||||
|
||||
// Common signals
|
||||
pub const (
|
||||
signal_term = 'SIGTERM'
|
||||
signal_kill = 'SIGKILL'
|
||||
signal_hup = 'SIGHUP'
|
||||
signal_usr1 = 'SIGUSR1'
|
||||
signal_usr2 = 'SIGUSR2'
|
||||
)
|
||||
|
||||
// JSON-RPC error codes as defined in the OpenRPC specification
|
||||
pub const (
|
||||
error_service_not_found = -32000
|
||||
error_service_already_monitored = -32001
|
||||
error_service_is_up = -32002
|
||||
error_service_is_down = -32003
|
||||
error_invalid_signal = -32004
|
||||
error_config_error = -32005
|
||||
error_shutting_down = -32006
|
||||
error_service_already_exists = -32007
|
||||
error_service_file_error = -32008
|
||||
)
|
||||
|
||||
// Helper function to create a basic service configuration
|
||||
pub fn new_service_config(exec string) ServiceConfig {
|
||||
return ServiceConfig{
|
||||
exec: exec
|
||||
oneshot: false
|
||||
log: log_stdout
|
||||
env: map[string]string{}
|
||||
shutdown_timeout: 30
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to create a oneshot service configuration
|
||||
pub fn new_oneshot_service_config(exec string) ServiceConfig {
|
||||
return ServiceConfig{
|
||||
exec: exec
|
||||
oneshot: true
|
||||
log: log_stdout
|
||||
env: map[string]string{}
|
||||
shutdown_timeout: 30
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to check if an error is a specific zinit error code
|
||||
pub fn is_zinit_error_code(err IError, code int) bool {
|
||||
if zinit_err := err as ZinitError {
|
||||
return zinit_err.code == code
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Helper function to check if service is not found error
|
||||
pub fn is_service_not_found_error(err IError) bool {
|
||||
return is_zinit_error_code(err, error_service_not_found)
|
||||
}
|
||||
|
||||
// Helper function to check if service is already monitored error
|
||||
pub fn is_service_already_monitored_error(err IError) bool {
|
||||
return is_zinit_error_code(err, error_service_already_monitored)
|
||||
}
|
||||
|
||||
// Helper function to check if service is down error
|
||||
pub fn is_service_down_error(err IError) bool {
|
||||
return is_zinit_error_code(err, error_service_is_down)
|
||||
}
|
||||
|
||||
// Helper function to format memory usage in human-readable format
|
||||
pub fn format_memory_usage(bytes i64) string {
|
||||
if bytes < 1024 {
|
||||
return '${bytes} B'
|
||||
} else if bytes < 1024 * 1024 {
|
||||
return '${bytes / 1024} KB'
|
||||
} else if bytes < 1024 * 1024 * 1024 {
|
||||
return '${bytes / 1024 / 1024} MB'
|
||||
} else {
|
||||
return '${bytes / 1024 / 1024 / 1024} GB'
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to format CPU usage
|
||||
pub fn format_cpu_usage(cpu_percent f64) string {
|
||||
return '${cpu_percent:.1f}%'
|
||||
}
|
Loading…
Reference in New Issue
Block a user