This commit is contained in:
2025-07-19 15:54:23 +02:00
parent f092095e7b
commit 02ffc71aea
65 changed files with 2424 additions and 2165 deletions

View File

@@ -15,4 +15,4 @@ pub mut:
// Error implements the error interface for ZinitError
pub fn (e ZinitError) msg() string {
return 'Zinit Error ${e.code}: ${e.message} - ${e.data}'
}
}

View File

@@ -8,14 +8,14 @@ mut:
rpc_client &jsonrpc.Client
}
@[params]
pub struct ClientParams {
path string = '/tmp/zinit.sock' // Path to the Zinit RPC socket
path string = '/tmp/zinit.sock' // Path to the Zinit RPC socket
}
// new_client creates a new Zinit RPC client with a custom socket path
pub fn new_client(args_ ClientParams) &Client {
mut args:=args_
mut args := args_
mut cl := jsonrpc.new_unix_socket_client(args.path)
return &Client{
rpc_client: cl

View File

@@ -1,6 +1,5 @@
module zinit
// ServiceCreateResponse represents the response from service_create
pub struct ServiceCreateResponse {
pub mut:
@@ -31,57 +30,44 @@ pub mut:
subscription_id string // ID of the log subscription
}
// Module version information
pub const (
version = '1.0.0'
author = 'Hero Code'
license = 'MIT'
)
pub const version = '1.0.0'
pub const author = 'Hero Code'
pub const 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'
)
pub const state_running = 'Running'
pub const state_success = 'Success'
pub const state_error = 'Error'
pub const state_stopped = 'Stopped'
pub const state_failed = 'Failed'
// Common service targets
pub const (
target_up = 'Up'
target_down = 'Down'
)
pub const target_up = 'Up'
pub const target_down = 'Down'
// Common log types
pub const (
log_null = 'null'
log_ring = 'ring'
log_stdout = 'stdout'
)
pub const log_null = 'null'
pub const log_ring = 'ring'
pub const log_stdout = 'stdout'
// Common signals
pub const (
signal_term = 'SIGTERM'
signal_kill = 'SIGKILL'
signal_hup = 'SIGHUP'
signal_usr1 = 'SIGUSR1'
signal_usr2 = 'SIGUSR2'
)
pub const signal_term = 'SIGTERM'
pub const signal_kill = 'SIGKILL'
pub const signal_hup = 'SIGHUP'
pub const signal_usr1 = 'SIGUSR1'
pub const 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
)
pub const error_service_not_found = -32000
pub const error_service_already_monitored = -32001
pub const error_service_is_up = -32002
pub const error_service_is_down = -32003
pub const error_invalid_signal = -32004
pub const error_config_error = -32005
pub const error_shutting_down = -32006
pub const error_service_already_exists = -32007
pub const error_service_file_error = -32008

View File

@@ -20,14 +20,12 @@ pub:
signal string // Signal to send (e.g., SIGTERM, SIGKILL)
}
// RpcDiscoverResponse represents the response from rpc.discover
pub struct RpcDiscoverResponse {
pub mut:
spec map[string]string // OpenRPC specification
}
// rpc_discover returns the OpenRPC specification for the API
pub fn (mut c Client) rpc_discover() !RpcDiscoverResponse {
request := jsonrpc.new_request_generic('rpc.discover', []string{})
@@ -37,8 +35,6 @@ pub fn (mut c Client) rpc_discover() !RpcDiscoverResponse {
}
}
// // Response Models for Zinit API
// //
// // This file contains all the response models used by the Zinit API.
@@ -54,7 +50,7 @@ pub fn (mut c Client) rpc_discover() !RpcDiscoverResponse {
// 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 {
request := jsonrpc.new_request_generic('service_list',map[string]string )
request := jsonrpc.new_request_generic('service_list', map[string]string{})
services := c.rpc_client.send[map[string]string, map[string]string](request)!
// return ServiceListResponse{
// services: services
@@ -76,7 +72,7 @@ pub mut:
// name: the name of the service
pub fn (mut c Client) service_status(name string) !ServiceStatusResponse {
request := jsonrpc.new_request_generic('service_status', name)
// Use a direct struct mapping instead of manual conversion
return c.rpc_client.send[string, ServiceStatusResponse](request)!
}
@@ -121,39 +117,36 @@ pub fn (mut c Client) service_forget(name string) ! {
c.rpc_client.send[string, string](request)!
}
//TODO: make sure the signal is a valid signal and enumerator do as @[params] so its optional
// TODO: make sure the signal is a valid signal and enumerator do as @[params] so its optional
// 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 := KillParams{
name: name
name: name
signal: signal
}
request := jsonrpc.new_request_generic('service_kill', params)
c.rpc_client.send[KillParams, string](request)!
}
// CreateServiceParams represents the parameters for the service_create method
struct CreateServiceParams {
name string // Name of the service to create
content ServiceConfig // Configuration for the service
}
// 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) !ServiceCreateResponse {
params := CreateServiceParams{
name: name
name: name
content: config
}
request := jsonrpc.new_request_generic('service_create', params)
path := c.rpc_client.send[CreateServiceParams, string](request)!
return ServiceCreateResponse{
@@ -164,18 +157,19 @@ pub fn (mut c Client) service_create(name string, config ServiceConfig) !Service
// service_get gets a service configuration file
// name: the name of the service to get
pub fn (mut c Client) service_get(name string) !ServiceConfigResponse {
request := jsonrpc.new_request_generic('service_get', {
'name': name
})
request := jsonrpc.new_request_generic('service_get', {"name":name})
// We need to handle the conversion from ServiceConfig to ServiceConfigResponse
config := c.rpc_client.send[map[string]string, ServiceConfig](request)!
return ServiceConfigResponse{
exec: config.exec
oneshot: config.oneshot
after: config.after
log: config.log
env: config.env
exec: config.exec
oneshot: config.oneshot
after: config.after
log: config.log
env: config.env
shutdown_timeout: config.shutdown_timeout
}
}

View File

@@ -1,6 +1,5 @@
module zinit
pub struct ServiceConfigResponse {
pub mut:
exec string // Command to run
@@ -11,14 +10,13 @@ pub mut:
shutdown_timeout int // Maximum time to wait for service to stop during shutdown
}
// 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{}
exec: exec
oneshot: false
log: log_stdout
env: map[string]string{}
shutdown_timeout: 30
}
}
@@ -26,10 +24,10 @@ pub fn new_service_config(exec string) ServiceConfig {
// 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{}
exec: exec
oneshot: true
log: log_stdout
env: map[string]string{}
shutdown_timeout: 30
}
}

View File

@@ -5,19 +5,19 @@ import freeflowuniverse.herolib.schemas.jsonrpc
// ServiceStatsResponse represents the response from service_stats
pub struct ServiceStatsResponse {
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 []ChildStatsResponse // Stats for child processes
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 []ChildStatsResponse // Stats for child processes
}
// ChildStatsResponse represents statistics for a child process
pub struct ChildStatsResponse {
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)
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)
}
// Serv
@@ -26,19 +26,19 @@ pub mut:
// name: the name of the service to get stats for
pub fn (mut c Client) service_stats(name string) !ServiceStatsResponse {
request := jsonrpc.new_request_generic('service_stats', name)
// We need to handle the conversion from the raw response to our model
raw_stats := c.rpc_client.send[string, map[string]string](request)!
// Parse the raw stats into our response model
mut children := []ChildStatsResponse{}
// In a real implementation, we would parse the children from the raw response
return ServiceStatsResponse{
name: raw_stats['name'] or { '' }
pid: raw_stats['pid'].int()
name: raw_stats['name'] or { '' }
pid: raw_stats['pid'].int()
memory_usage: raw_stats['memory_usage'].i64()
cpu_usage: raw_stats['cpu_usage'].f64()
children: children
cpu_usage: raw_stats['cpu_usage'].f64()
children: children
}
}

View File

@@ -2,7 +2,6 @@ module zinit
import freeflowuniverse.herolib.schemas.jsonrpc
// system_shutdown stops all services and powers off the system
pub fn (mut c Client) system_shutdown() ! {
request := jsonrpc.new_request_generic('system_shutdown', []string{})
@@ -15,7 +14,6 @@ pub fn (mut c Client) system_reboot() ! {
c.rpc_client.send[[]string, string](request)!
}
// 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) !SystemStartHttpServerResponse {
@@ -34,16 +32,18 @@ pub fn (mut c Client) system_stop_http_server() ! {
@[params]
pub struct LogParams {
name string
name string
}
// 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(args LogParams) ![]string {
mut logs := []string{}
if args.name != '' {
request := jsonrpc.new_request_generic('stream_currentLogs', {"name":args.name})
request := jsonrpc.new_request_generic('stream_currentLogs', {
'name': args.name
})
logs = c.rpc_client.send[map[string]string, map[string]string](request)!
} else {
request := jsonrpc.new_request_generic('stream_currentLogs', map[string]string{})
@@ -56,7 +56,7 @@ pub fn (mut c Client) stream_current_logs(args LogParams) ![]string {
// name: optional service name filter. If provided, only logs from this service will be returned
pub fn (mut c Client) stream_subscribe_logs(name ?string) !StreamSubscribeLogsResponse {
mut subscription_id := ''
if service_name := name {
request := jsonrpc.new_request_generic('stream_subscribeLogs', service_name)
subscription_id = c.rpc_client.send[string, string](request)!
@@ -64,8 +64,8 @@ pub fn (mut c Client) stream_subscribe_logs(name ?string) !StreamSubscribeLogsRe
request := jsonrpc.new_request_generic('stream_subscribeLogs', []string{})
subscription_id = c.rpc_client.send[[]string, string](request)!
}
return StreamSubscribeLogsResponse{
subscription_id: subscription_id
}
}
}

View File

@@ -1,6 +1,5 @@
module zinit
// Helper function to format memory usage in human-readable format
pub fn format_memory_usage(bytes i64) string {
if bytes < 1024 {
@@ -17,4 +16,4 @@ pub fn format_memory_usage(bytes i64) string {
// Helper function to format CPU usage
pub fn format_cpu_usage(cpu_percent f64) string {
return '${cpu_percent:.1f}%'
}
}