Compare commits
	
		
			2 Commits
		
	
	
		
			a9255de679
			...
			bb39f3e3f2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | bb39f3e3f2 | ||
|  | 5194f5245d | 
| @@ -3,9 +3,12 @@ | |||||||
|     "gitea": { |     "gitea": { | ||||||
|       "command": "/Users/despiegk/hero/bin/mcpgitea", |       "command": "/Users/despiegk/hero/bin/mcpgitea", | ||||||
|       "args": [ |       "args": [ | ||||||
|         "-t", "stdio", |         "-t", | ||||||
|         "--host", "https://gitea.com", |         "stdio", | ||||||
|         "--token", "5bd13c898368a2edbfcef43f898a34857b51b37a" |         "--host", | ||||||
|  |         "https://gitea.com", | ||||||
|  |         "--token", | ||||||
|  |         "5bd13c898368a2edbfcef43f898a34857b51b37a" | ||||||
|       ], |       ], | ||||||
|       "env": { |       "env": { | ||||||
|         "GITEA_HOST": "https://git.threefold.info/", |         "GITEA_HOST": "https://git.threefold.info/", | ||||||
|   | |||||||
| @@ -53,9 +53,9 @@ tokio = "1.45.0" | |||||||
| tokio-postgres = "0.7.8" # Async PostgreSQL client | tokio-postgres = "0.7.8" # Async PostgreSQL client | ||||||
| tokio-test = "0.4.4" | tokio-test = "0.4.4" | ||||||
| uuid = { version = "1.16.0", features = ["v4"] } | uuid = { version = "1.16.0", features = ["v4"] } | ||||||
| zinit-client = { path = "/Users/timurgordon/code/github/threefoldtech/zinit/zinit-client" } |  | ||||||
| reqwest = { version = "0.12.15", features = ["json"] } | reqwest = { version = "0.12.15", features = ["json"] } | ||||||
| urlencoding = "2.1.3" | urlencoding = "2.1.3" | ||||||
|  | zinit-client = "0.3.0" | ||||||
|  |  | ||||||
| # Optional features for specific OS functionality | # Optional features for specific OS functionality | ||||||
| [target.'cfg(unix)'.dependencies] | [target.'cfg(unix)'.dependencies] | ||||||
|   | |||||||
| @@ -1,8 +1,9 @@ | |||||||
| //! Rhai bindings for SAL crypto functionality | //! Rhai bindings for SAL crypto functionality | ||||||
|  |  | ||||||
| use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _}; | use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _}; | ||||||
| use crate::vault::CryptoError; |  | ||||||
| use ethers::types::{Address, U256}; | use ethers::types::{Address, U256}; | ||||||
|  | use hex; | ||||||
| use once_cell::sync::Lazy; | use once_cell::sync::Lazy; | ||||||
| use rhai::{Dynamic, Engine, EvalAltResult}; | use rhai::{Dynamic, Engine, EvalAltResult}; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| @@ -10,7 +11,6 @@ use std::fs; | |||||||
| use std::path::PathBuf; | use std::path::PathBuf; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
| use std::sync::Mutex; | use std::sync::Mutex; | ||||||
| use hex; |  | ||||||
| use tokio::runtime::Runtime; | use tokio::runtime::Runtime; | ||||||
|  |  | ||||||
| use crate::vault::{ethereum, keyspace}; | use crate::vault::{ethereum, keyspace}; | ||||||
| @@ -268,7 +268,9 @@ fn create_keyspace(name: &str, password: &str) -> bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| fn select_keyspace(name: &str) -> bool { | fn select_keyspace(name: &str) -> bool { | ||||||
|     let session = crate::vault::keyspace::session_manager::SESSION.lock().unwrap(); |     let session = crate::vault::keyspace::session_manager::SESSION | ||||||
|  |         .lock() | ||||||
|  |         .unwrap(); | ||||||
|     if let Some(ref current_space_obj) = session.current_space { |     if let Some(ref current_space_obj) = session.current_space { | ||||||
|         if current_space_obj.name == name { |         if current_space_obj.name == name { | ||||||
|             log::debug!("Keyspace '{}' is already selected.", name); |             log::debug!("Keyspace '{}' is already selected.", name); | ||||||
| @@ -284,7 +286,10 @@ fn rhai_list_keyspaces_actual() -> Vec<String> { | |||||||
|     let key_spaces_dir = home_dir.join(".hero-vault").join("key-spaces"); |     let key_spaces_dir = home_dir.join(".hero-vault").join("key-spaces"); | ||||||
|  |  | ||||||
|     if !key_spaces_dir.exists() { |     if !key_spaces_dir.exists() { | ||||||
|         log::debug!("Key spaces directory does not exist: {}", key_spaces_dir.display()); |         log::debug!( | ||||||
|  |             "Key spaces directory does not exist: {}", | ||||||
|  |             key_spaces_dir.display() | ||||||
|  |         ); | ||||||
|         return Vec::new(); |         return Vec::new(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,11 +2,11 @@ | |||||||
| //! | //! | ||||||
| //! This module provides Rhai wrappers for the functions in the Zinit client module. | //! This module provides Rhai wrappers for the functions in the Zinit client module. | ||||||
|  |  | ||||||
| use rhai::{Engine, EvalAltResult, Array, Dynamic, Map}; |  | ||||||
| use crate::zinit_client as client; |  | ||||||
| use tokio::runtime::Runtime; |  | ||||||
| use serde_json::{json, Value}; |  | ||||||
| use crate::rhai::error::ToRhaiError; | use crate::rhai::error::ToRhaiError; | ||||||
|  | use crate::zinit_client as client; | ||||||
|  | use rhai::{Array, Dynamic, Engine, EvalAltResult, Map}; | ||||||
|  | use serde_json::{json, Value}; | ||||||
|  | use tokio::runtime::Runtime; | ||||||
|  |  | ||||||
| /// Register Zinit module functions with the Rhai engine | /// Register Zinit module functions with the Rhai engine | ||||||
| /// | /// | ||||||
| @@ -32,16 +32,16 @@ pub fn register_zinit_module(engine: &mut Engine) -> Result<(), Box<EvalAltResul | |||||||
|     engine.register_fn("zinit_get_service", zinit_get_service); |     engine.register_fn("zinit_get_service", zinit_get_service); | ||||||
|     engine.register_fn("zinit_logs", zinit_logs); |     engine.register_fn("zinit_logs", zinit_logs); | ||||||
|     engine.register_fn("zinit_logs_all", zinit_logs_all); |     engine.register_fn("zinit_logs_all", zinit_logs_all); | ||||||
|      |  | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T> ToRhaiError<T> for Result<T, zinit_client::ClientError> { | impl<T> ToRhaiError<T> for Result<T, zinit_client::ZinitError> { | ||||||
|     fn to_rhai_error(self) -> Result<T, Box<EvalAltResult>> { |     fn to_rhai_error(self) -> Result<T, Box<EvalAltResult>> { | ||||||
|         self.map_err(|e| { |         self.map_err(|e| { | ||||||
|             Box::new(EvalAltResult::ErrorRuntime( |             Box::new(EvalAltResult::ErrorRuntime( | ||||||
|                 format!("Zinit error: {}", e).into(), |                 format!("Zinit error: {}", e).into(), | ||||||
|                 rhai::Position::NONE |                 rhai::Position::NONE, | ||||||
|             )) |             )) | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @@ -52,7 +52,7 @@ fn get_runtime() -> Result<Runtime, Box<EvalAltResult>> { | |||||||
|     tokio::runtime::Runtime::new().map_err(|e| { |     tokio::runtime::Runtime::new().map_err(|e| { | ||||||
|         Box::new(EvalAltResult::ErrorRuntime( |         Box::new(EvalAltResult::ErrorRuntime( | ||||||
|             format!("Failed to create Tokio runtime: {}", e).into(), |             format!("Failed to create Tokio runtime: {}", e).into(), | ||||||
|             rhai::Position::NONE |             rhai::Position::NONE, | ||||||
|         )) |         )) | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| @@ -66,19 +66,17 @@ fn get_runtime() -> Result<Runtime, Box<EvalAltResult>> { | |||||||
| /// Lists all services managed by Zinit. | /// Lists all services managed by Zinit. | ||||||
| pub fn zinit_list(socket_path: &str) -> Result<Map, Box<EvalAltResult>> { | pub fn zinit_list(socket_path: &str) -> Result<Map, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { client::list(socket_path).await }); | ||||||
|         client::list(socket_path).await |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     let services = result.to_rhai_error()?; |     let services = result.to_rhai_error()?; | ||||||
|      |  | ||||||
|     // Convert HashMap<String, String> to Rhai Map |     // Convert HashMap<String, String> to Rhai Map | ||||||
|     let mut map = Map::new(); |     let mut map = Map::new(); | ||||||
|     for (name, state) in services { |     for (name, state) in services { | ||||||
|         map.insert(name.into(), Dynamic::from(state)); |         map.insert(name.into(), Dynamic::from(state)); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     Ok(map) |     Ok(map) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -87,27 +85,25 @@ pub fn zinit_list(socket_path: &str) -> Result<Map, Box<EvalAltResult>> { | |||||||
| /// Gets the status of a specific service. | /// Gets the status of a specific service. | ||||||
| pub fn zinit_status(socket_path: &str, name: &str) -> Result<Map, Box<EvalAltResult>> { | pub fn zinit_status(socket_path: &str, name: &str) -> Result<Map, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { client::status(socket_path, name).await }); | ||||||
|         client::status(socket_path, name).await |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     let status = result.to_rhai_error()?; |     let status = result.to_rhai_error()?; | ||||||
|      |  | ||||||
|     // Convert Status to Rhai Map |     // Convert Status to Rhai Map | ||||||
|     let mut map = Map::new(); |     let mut map = Map::new(); | ||||||
|     map.insert("name".into(), Dynamic::from(status.name)); |     map.insert("name".into(), Dynamic::from(status.name)); | ||||||
|     map.insert("pid".into(), Dynamic::from(status.pid)); |     map.insert("pid".into(), Dynamic::from(status.pid)); | ||||||
|     map.insert("state".into(), Dynamic::from(status.state)); |     map.insert("state".into(), Dynamic::from(status.state)); | ||||||
|     map.insert("target".into(), Dynamic::from(status.target)); |     map.insert("target".into(), Dynamic::from(status.target)); | ||||||
|      |  | ||||||
|     // Convert dependencies |     // Convert dependencies | ||||||
|     let mut deps_map = Map::new(); |     let mut deps_map = Map::new(); | ||||||
|     for (dep, state) in status.after { |     for (dep, state) in status.after { | ||||||
|         deps_map.insert(dep.into(), Dynamic::from(state)); |         deps_map.insert(dep.into(), Dynamic::from(state)); | ||||||
|     } |     } | ||||||
|     map.insert("after".into(), Dynamic::from_map(deps_map)); |     map.insert("after".into(), Dynamic::from_map(deps_map)); | ||||||
|      |  | ||||||
|     Ok(map) |     Ok(map) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -116,11 +112,9 @@ pub fn zinit_status(socket_path: &str, name: &str) -> Result<Map, Box<EvalAltRes | |||||||
| /// Starts a service. | /// Starts a service. | ||||||
| pub fn zinit_start(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | pub fn zinit_start(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { client::start(socket_path, name).await }); | ||||||
|         client::start(socket_path, name).await |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     result.to_rhai_error()?; |     result.to_rhai_error()?; | ||||||
|     Ok(true) |     Ok(true) | ||||||
| } | } | ||||||
| @@ -130,11 +124,9 @@ pub fn zinit_start(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltRes | |||||||
| /// Stops a service. | /// Stops a service. | ||||||
| pub fn zinit_stop(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | pub fn zinit_stop(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { client::stop(socket_path, name).await }); | ||||||
|         client::stop(socket_path, name).await |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     result.to_rhai_error()?; |     result.to_rhai_error()?; | ||||||
|     Ok(true) |     Ok(true) | ||||||
| } | } | ||||||
| @@ -144,11 +136,9 @@ pub fn zinit_stop(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResu | |||||||
| /// Restarts a service. | /// Restarts a service. | ||||||
| pub fn zinit_restart(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | pub fn zinit_restart(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { client::restart(socket_path, name).await }); | ||||||
|         client::restart(socket_path, name).await |  | ||||||
|     }); |  | ||||||
|      |  | ||||||
|     result.to_rhai_error()?; |     result.to_rhai_error()?; | ||||||
|     Ok(true) |     Ok(true) | ||||||
| } | } | ||||||
| @@ -158,12 +148,12 @@ pub fn zinit_restart(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltR | |||||||
| /// Starts monitoring a service. | /// Starts monitoring a service. | ||||||
| pub fn zinit_monitor(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | pub fn zinit_monitor(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.monitor(name).await |         client.monitor(name).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     result.to_rhai_error()?; |     result.to_rhai_error()?; | ||||||
|     Ok(true) |     Ok(true) | ||||||
| } | } | ||||||
| @@ -173,12 +163,12 @@ pub fn zinit_monitor(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltR | |||||||
| /// Stops monitoring a service. | /// Stops monitoring a service. | ||||||
| pub fn zinit_forget(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | pub fn zinit_forget(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.forget(name).await |         client.forget(name).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     result.to_rhai_error()?; |     result.to_rhai_error()?; | ||||||
|     Ok(true) |     Ok(true) | ||||||
| } | } | ||||||
| @@ -188,12 +178,12 @@ pub fn zinit_forget(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltRe | |||||||
| /// Sends a signal to a service. | /// Sends a signal to a service. | ||||||
| pub fn zinit_kill(socket_path: &str, name: &str, signal: &str) -> Result<bool, Box<EvalAltResult>> { | pub fn zinit_kill(socket_path: &str, name: &str, signal: &str) -> Result<bool, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.kill(name, signal).await |         client.kill(name, signal).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     result.to_rhai_error()?; |     result.to_rhai_error()?; | ||||||
|     Ok(true) |     Ok(true) | ||||||
| } | } | ||||||
| @@ -201,26 +191,34 @@ pub fn zinit_kill(socket_path: &str, name: &str, signal: &str) -> Result<bool, B | |||||||
| /// Wrapper for zinit_client::create_service | /// Wrapper for zinit_client::create_service | ||||||
| /// | /// | ||||||
| /// Creates a new service. | /// Creates a new service. | ||||||
| pub fn zinit_create_service(socket_path: &str, name: &str, exec: &str, oneshot: bool) -> Result<String, Box<EvalAltResult>> { | pub fn zinit_create_service( | ||||||
|  |     socket_path: &str, | ||||||
|  |     name: &str, | ||||||
|  |     exec: &str, | ||||||
|  |     oneshot: bool, | ||||||
|  | ) -> Result<String, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     // Create service configuration |     // Create service configuration | ||||||
|     let content = serde_json::from_value(json!({ |     let content = serde_json::from_value(json!({ | ||||||
|         "exec": exec, |         "exec": exec, | ||||||
|         "oneshot": oneshot |         "oneshot": oneshot | ||||||
|     })).map_err(|e| { |     })) | ||||||
|  |     .map_err(|e| { | ||||||
|         Box::new(EvalAltResult::ErrorRuntime( |         Box::new(EvalAltResult::ErrorRuntime( | ||||||
|             format!("Failed to create service configuration: {}", e).into(), |             format!("Failed to create service configuration: {}", e).into(), | ||||||
|             rhai::Position::NONE |             rhai::Position::NONE, | ||||||
|         )) |         )) | ||||||
|     })?; |     })?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.create_service(name, content).await |         client.create_service(name, content).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     result.to_rhai_error() |     // Convert () result to success message | ||||||
|  |     result.to_rhai_error()?; | ||||||
|  |     Ok(format!("Service '{}' created successfully", name)) | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Wrapper for zinit_client::delete_service | /// Wrapper for zinit_client::delete_service | ||||||
| @@ -228,13 +226,15 @@ pub fn zinit_create_service(socket_path: &str, name: &str, exec: &str, oneshot: | |||||||
| /// Deletes a service. | /// Deletes a service. | ||||||
| pub fn zinit_delete_service(socket_path: &str, name: &str) -> Result<String, Box<EvalAltResult>> { | pub fn zinit_delete_service(socket_path: &str, name: &str) -> Result<String, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.delete_service(name).await |         client.delete_service(name).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     result.to_rhai_error() |     // Convert () result to success message | ||||||
|  |     result.to_rhai_error()?; | ||||||
|  |     Ok(format!("Service '{}' deleted successfully", name)) | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Wrapper for zinit_client::get_service | /// Wrapper for zinit_client::get_service | ||||||
| @@ -242,14 +242,14 @@ pub fn zinit_delete_service(socket_path: &str, name: &str) -> Result<String, Box | |||||||
| /// Gets a service configuration. | /// Gets a service configuration. | ||||||
| pub fn zinit_get_service(socket_path: &str, name: &str) -> Result<Dynamic, Box<EvalAltResult>> { | pub fn zinit_get_service(socket_path: &str, name: &str) -> Result<Dynamic, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.get_service(name).await |         client.get_service(name).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     let value = result.to_rhai_error()?; |     let value = result.to_rhai_error()?; | ||||||
|      |  | ||||||
|     // Convert Value to Dynamic |     // Convert Value to Dynamic | ||||||
|     match value { |     match value { | ||||||
|         Value::Object(map) => { |         Value::Object(map) => { | ||||||
| @@ -258,11 +258,11 @@ pub fn zinit_get_service(socket_path: &str, name: &str) -> Result<Dynamic, Box<E | |||||||
|                 rhai_map.insert(k.into(), value_to_dynamic(v)); |                 rhai_map.insert(k.into(), value_to_dynamic(v)); | ||||||
|             } |             } | ||||||
|             Ok(Dynamic::from_map(rhai_map)) |             Ok(Dynamic::from_map(rhai_map)) | ||||||
|         }, |         } | ||||||
|         _ => Err(Box::new(EvalAltResult::ErrorRuntime( |         _ => Err(Box::new(EvalAltResult::ErrorRuntime( | ||||||
|             "Expected object from get_service".into(), |             "Expected object from get_service".into(), | ||||||
|             rhai::Position::NONE |             rhai::Position::NONE, | ||||||
|         ))) |         ))), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -271,22 +271,22 @@ pub fn zinit_get_service(socket_path: &str, name: &str) -> Result<Dynamic, Box<E | |||||||
| /// Gets logs for a specific service. | /// Gets logs for a specific service. | ||||||
| pub fn zinit_logs(socket_path: &str, filter: &str) -> Result<Array, Box<EvalAltResult>> { | pub fn zinit_logs(socket_path: &str, filter: &str) -> Result<Array, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let filter_string = Some(filter.to_string()); |     let filter_string = Some(filter.to_string()); | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.logs(filter_string).await |         client.logs(filter_string).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     let logs = result.to_rhai_error()?; |     let logs = result.to_rhai_error()?; | ||||||
|      |  | ||||||
|     // Convert Vec<String> to Rhai Array |     // Convert Vec<String> to Rhai Array | ||||||
|     let mut array = Array::new(); |     let mut array = Array::new(); | ||||||
|     for log in logs { |     for log in logs { | ||||||
|         array.push(Dynamic::from(log)); |         array.push(Dynamic::from(log)); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     Ok(array) |     Ok(array) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -295,20 +295,20 @@ pub fn zinit_logs(socket_path: &str, filter: &str) -> Result<Array, Box<EvalAltR | |||||||
| /// Gets all logs. | /// Gets all logs. | ||||||
| pub fn zinit_logs_all(socket_path: &str) -> Result<Array, Box<EvalAltResult>> { | pub fn zinit_logs_all(socket_path: &str) -> Result<Array, Box<EvalAltResult>> { | ||||||
|     let rt = get_runtime()?; |     let rt = get_runtime()?; | ||||||
|      |  | ||||||
|     let result = rt.block_on(async { |     let result = rt.block_on(async { | ||||||
|         let client = client::get_zinit_client(socket_path).await?; |         let client = client::get_zinit_client(socket_path).await?; | ||||||
|         client.logs(None).await |         client.logs(None).await | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     let logs = result.to_rhai_error()?; |     let logs = result.to_rhai_error()?; | ||||||
|      |  | ||||||
|     // Convert Vec<String> to Rhai Array |     // Convert Vec<String> to Rhai Array | ||||||
|     let mut array = Array::new(); |     let mut array = Array::new(); | ||||||
|     for log in logs { |     for log in logs { | ||||||
|         array.push(Dynamic::from(log)); |         array.push(Dynamic::from(log)); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     Ok(array) |     Ok(array) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -325,7 +325,7 @@ fn value_to_dynamic(value: Value) -> Dynamic { | |||||||
|             } else { |             } else { | ||||||
|                 Dynamic::from(n.to_string()) |                 Dynamic::from(n.to_string()) | ||||||
|             } |             } | ||||||
|         }, |         } | ||||||
|         Value::String(s) => Dynamic::from(s), |         Value::String(s) => Dynamic::from(s), | ||||||
|         Value::Array(arr) => { |         Value::Array(arr) => { | ||||||
|             let mut rhai_arr = Array::new(); |             let mut rhai_arr = Array::new(); | ||||||
| @@ -333,7 +333,7 @@ fn value_to_dynamic(value: Value) -> Dynamic { | |||||||
|                 rhai_arr.push(value_to_dynamic(item)); |                 rhai_arr.push(value_to_dynamic(item)); | ||||||
|             } |             } | ||||||
|             Dynamic::from(rhai_arr) |             Dynamic::from(rhai_arr) | ||||||
|         }, |         } | ||||||
|         Value::Object(map) => { |         Value::Object(map) => { | ||||||
|             let mut rhai_map = Map::new(); |             let mut rhai_map = Map::new(); | ||||||
|             for (k, v) in map { |             for (k, v) in map { | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| // File: /root/code/git.threefold.info/herocode/sal/src/virt/nerdctl/container_builder.rs | // File: /root/code/git.threefold.info/herocode/sal/src/virt/nerdctl/container_builder.rs | ||||||
|  |  | ||||||
| use std::collections::HashMap; |  | ||||||
| use crate::virt::nerdctl::{execute_nerdctl_command, NerdctlError}; |  | ||||||
| use super::container_types::{Container, HealthCheck}; | use super::container_types::{Container, HealthCheck}; | ||||||
| use super::health_check_script::prepare_health_check_command; | use super::health_check_script::prepare_health_check_command; | ||||||
|  | use crate::virt::nerdctl::{execute_nerdctl_command, NerdctlError}; | ||||||
|  | use std::collections::HashMap; | ||||||
|  |  | ||||||
| impl Container { | impl Container { | ||||||
|     /// Reset the container configuration to defaults while keeping the name and image |     /// Reset the container configuration to defaults while keeping the name and image | ||||||
| @@ -15,18 +15,21 @@ impl Container { | |||||||
|     pub fn reset(self) -> Self { |     pub fn reset(self) -> Self { | ||||||
|         let name = self.name; |         let name = self.name; | ||||||
|         let image = self.image.clone(); |         let image = self.image.clone(); | ||||||
|          |  | ||||||
|         // If container exists, stop and remove it |         // If container exists, stop and remove it | ||||||
|         if let Some(container_id) = &self.container_id { |         if let Some(container_id) = &self.container_id { | ||||||
|             println!("Container exists. Stopping and removing container '{}'...", name); |             println!( | ||||||
|              |                 "Container exists. Stopping and removing container '{}'...", | ||||||
|  |                 name | ||||||
|  |             ); | ||||||
|  |  | ||||||
|             // Try to stop the container |             // Try to stop the container | ||||||
|             let _ = execute_nerdctl_command(&["stop", container_id]); |             let _ = execute_nerdctl_command(&["stop", container_id]); | ||||||
|              |  | ||||||
|             // Try to remove the container |             // Try to remove the container | ||||||
|             let _ = execute_nerdctl_command(&["rm", container_id]); |             let _ = execute_nerdctl_command(&["rm", container_id]); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Create a new container with just the name and image, but no container_id |         // Create a new container with just the name and image, but no container_id | ||||||
|         Self { |         Self { | ||||||
|             name, |             name, | ||||||
| @@ -48,7 +51,7 @@ impl Container { | |||||||
|             snapshotter: None, |             snapshotter: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add a port mapping |     /// Add a port mapping | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -62,7 +65,7 @@ impl Container { | |||||||
|         self.ports.push(port.to_string()); |         self.ports.push(port.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add multiple port mappings |     /// Add multiple port mappings | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -78,7 +81,7 @@ impl Container { | |||||||
|         } |         } | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add a volume mount |     /// Add a volume mount | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -92,7 +95,7 @@ impl Container { | |||||||
|         self.volumes.push(volume.to_string()); |         self.volumes.push(volume.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add multiple volume mounts |     /// Add multiple volume mounts | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -108,7 +111,7 @@ impl Container { | |||||||
|         } |         } | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add an environment variable |     /// Add an environment variable | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -123,7 +126,7 @@ impl Container { | |||||||
|         self.env_vars.insert(key.to_string(), value.to_string()); |         self.env_vars.insert(key.to_string(), value.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add multiple environment variables |     /// Add multiple environment variables | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -139,7 +142,7 @@ impl Container { | |||||||
|         } |         } | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set the network for the container |     /// Set the network for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -153,7 +156,7 @@ impl Container { | |||||||
|         self.network = Some(network.to_string()); |         self.network = Some(network.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add a network alias for the container |     /// Add a network alias for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -167,7 +170,7 @@ impl Container { | |||||||
|         self.network_aliases.push(alias.to_string()); |         self.network_aliases.push(alias.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Add multiple network aliases for the container |     /// Add multiple network aliases for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -183,7 +186,7 @@ impl Container { | |||||||
|         } |         } | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set CPU limit for the container |     /// Set CPU limit for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -197,7 +200,7 @@ impl Container { | |||||||
|         self.cpu_limit = Some(cpus.to_string()); |         self.cpu_limit = Some(cpus.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set memory limit for the container |     /// Set memory limit for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -211,7 +214,7 @@ impl Container { | |||||||
|         self.memory_limit = Some(memory.to_string()); |         self.memory_limit = Some(memory.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set memory swap limit for the container |     /// Set memory swap limit for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -225,7 +228,7 @@ impl Container { | |||||||
|         self.memory_swap_limit = Some(memory_swap.to_string()); |         self.memory_swap_limit = Some(memory_swap.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set CPU shares for the container (relative weight) |     /// Set CPU shares for the container (relative weight) | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -239,7 +242,7 @@ impl Container { | |||||||
|         self.cpu_shares = Some(shares.to_string()); |         self.cpu_shares = Some(shares.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set restart policy for the container |     /// Set restart policy for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -253,7 +256,7 @@ impl Container { | |||||||
|         self.restart_policy = Some(policy.to_string()); |         self.restart_policy = Some(policy.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set a simple health check for the container |     /// Set a simple health check for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -266,7 +269,7 @@ impl Container { | |||||||
|     pub fn with_health_check(mut self, cmd: &str) -> Self { |     pub fn with_health_check(mut self, cmd: &str) -> Self { | ||||||
|         // Use the health check script module to prepare the command |         // Use the health check script module to prepare the command | ||||||
|         let prepared_cmd = prepare_health_check_command(cmd, &self.name); |         let prepared_cmd = prepare_health_check_command(cmd, &self.name); | ||||||
|          |  | ||||||
|         self.health_check = Some(HealthCheck { |         self.health_check = Some(HealthCheck { | ||||||
|             cmd: prepared_cmd, |             cmd: prepared_cmd, | ||||||
|             interval: None, |             interval: None, | ||||||
| @@ -276,7 +279,7 @@ impl Container { | |||||||
|         }); |         }); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set a health check with custom options for the container |     /// Set a health check with custom options for the container | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -300,7 +303,7 @@ impl Container { | |||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         // Use the health check script module to prepare the command |         // Use the health check script module to prepare the command | ||||||
|         let prepared_cmd = prepare_health_check_command(cmd, &self.name); |         let prepared_cmd = prepare_health_check_command(cmd, &self.name); | ||||||
|          |  | ||||||
|         let mut health_check = HealthCheck { |         let mut health_check = HealthCheck { | ||||||
|             cmd: prepared_cmd, |             cmd: prepared_cmd, | ||||||
|             interval: None, |             interval: None, | ||||||
| @@ -308,27 +311,27 @@ impl Container { | |||||||
|             retries: None, |             retries: None, | ||||||
|             start_period: None, |             start_period: None, | ||||||
|         }; |         }; | ||||||
|          |  | ||||||
|         if let Some(interval_value) = interval { |         if let Some(interval_value) = interval { | ||||||
|             health_check.interval = Some(interval_value.to_string()); |             health_check.interval = Some(interval_value.to_string()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(timeout_value) = timeout { |         if let Some(timeout_value) = timeout { | ||||||
|             health_check.timeout = Some(timeout_value.to_string()); |             health_check.timeout = Some(timeout_value.to_string()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(retries_value) = retries { |         if let Some(retries_value) = retries { | ||||||
|             health_check.retries = Some(retries_value); |             health_check.retries = Some(retries_value); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(start_period_value) = start_period { |         if let Some(start_period_value) = start_period { | ||||||
|             health_check.start_period = Some(start_period_value.to_string()); |             health_check.start_period = Some(start_period_value.to_string()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         self.health_check = Some(health_check); |         self.health_check = Some(health_check); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set the snapshotter |     /// Set the snapshotter | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -342,7 +345,7 @@ impl Container { | |||||||
|         self.snapshotter = Some(snapshotter.to_string()); |         self.snapshotter = Some(snapshotter.to_string()); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Set whether to run in detached mode |     /// Set whether to run in detached mode | ||||||
|     /// |     /// | ||||||
|     /// # Arguments |     /// # Arguments | ||||||
| @@ -356,7 +359,7 @@ impl Container { | |||||||
|         self.detach = detach; |         self.detach = detach; | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     /// Build the container |     /// Build the container | ||||||
|     /// |     /// | ||||||
|     /// # Returns |     /// # Returns | ||||||
| @@ -367,126 +370,130 @@ impl Container { | |||||||
|         if self.container_id.is_some() { |         if self.container_id.is_some() { | ||||||
|             return Ok(self); |             return Ok(self); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // If no image is specified, return an error |         // If no image is specified, return an error | ||||||
|         let image = match &self.image { |         let image = match &self.image { | ||||||
|             Some(img) => img, |             Some(img) => img, | ||||||
|             None => return Err(NerdctlError::Other("No image specified for container creation".to_string())), |             None => { | ||||||
|  |                 return Err(NerdctlError::Other( | ||||||
|  |                     "No image specified for container creation".to_string(), | ||||||
|  |                 )) | ||||||
|  |             } | ||||||
|         }; |         }; | ||||||
|          |  | ||||||
|         // Build the command arguments as strings |         // Build the command arguments as strings | ||||||
|         let mut args_strings = Vec::new(); |         let mut args_strings = Vec::new(); | ||||||
|         args_strings.push("run".to_string()); |         args_strings.push("run".to_string()); | ||||||
|          |  | ||||||
|         if self.detach { |         if self.detach { | ||||||
|             args_strings.push("-d".to_string()); |             args_strings.push("-d".to_string()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         args_strings.push("--name".to_string()); |         args_strings.push("--name".to_string()); | ||||||
|         args_strings.push(self.name.clone()); |         args_strings.push(self.name.clone()); | ||||||
|          |  | ||||||
|         // Add port mappings |         // Add port mappings | ||||||
|         for port in &self.ports { |         for port in &self.ports { | ||||||
|             args_strings.push("-p".to_string()); |             args_strings.push("-p".to_string()); | ||||||
|             args_strings.push(port.clone()); |             args_strings.push(port.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add volume mounts |         // Add volume mounts | ||||||
|         for volume in &self.volumes { |         for volume in &self.volumes { | ||||||
|             args_strings.push("-v".to_string()); |             args_strings.push("-v".to_string()); | ||||||
|             args_strings.push(volume.clone()); |             args_strings.push(volume.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add environment variables |         // Add environment variables | ||||||
|         for (key, value) in &self.env_vars { |         for (key, value) in &self.env_vars { | ||||||
|             args_strings.push("-e".to_string()); |             args_strings.push("-e".to_string()); | ||||||
|             args_strings.push(format!("{}={}", key, value)); |             args_strings.push(format!("{}={}", key, value)); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add network configuration |         // Add network configuration | ||||||
|         if let Some(network) = &self.network { |         if let Some(network) = &self.network { | ||||||
|             args_strings.push("--network".to_string()); |             args_strings.push("--network".to_string()); | ||||||
|             args_strings.push(network.clone()); |             args_strings.push(network.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add network aliases |         // Add network aliases | ||||||
|         for alias in &self.network_aliases { |         for alias in &self.network_aliases { | ||||||
|             args_strings.push("--network-alias".to_string()); |             args_strings.push("--network-alias".to_string()); | ||||||
|             args_strings.push(alias.clone()); |             args_strings.push(alias.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add resource limits |         // Add resource limits | ||||||
|         if let Some(cpu_limit) = &self.cpu_limit { |         if let Some(cpu_limit) = &self.cpu_limit { | ||||||
|             args_strings.push("--cpus".to_string()); |             args_strings.push("--cpus".to_string()); | ||||||
|             args_strings.push(cpu_limit.clone()); |             args_strings.push(cpu_limit.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(memory_limit) = &self.memory_limit { |         if let Some(memory_limit) = &self.memory_limit { | ||||||
|             args_strings.push("--memory".to_string()); |             args_strings.push("--memory".to_string()); | ||||||
|             args_strings.push(memory_limit.clone()); |             args_strings.push(memory_limit.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(memory_swap_limit) = &self.memory_swap_limit { |         if let Some(memory_swap_limit) = &self.memory_swap_limit { | ||||||
|             args_strings.push("--memory-swap".to_string()); |             args_strings.push("--memory-swap".to_string()); | ||||||
|             args_strings.push(memory_swap_limit.clone()); |             args_strings.push(memory_swap_limit.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(cpu_shares) = &self.cpu_shares { |         if let Some(cpu_shares) = &self.cpu_shares { | ||||||
|             args_strings.push("--cpu-shares".to_string()); |             args_strings.push("--cpu-shares".to_string()); | ||||||
|             args_strings.push(cpu_shares.clone()); |             args_strings.push(cpu_shares.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add restart policy |         // Add restart policy | ||||||
|         if let Some(restart_policy) = &self.restart_policy { |         if let Some(restart_policy) = &self.restart_policy { | ||||||
|             args_strings.push("--restart".to_string()); |             args_strings.push("--restart".to_string()); | ||||||
|             args_strings.push(restart_policy.clone()); |             args_strings.push(restart_policy.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add health check |         // Add health check | ||||||
|         if let Some(health_check) = &self.health_check { |         if let Some(health_check) = &self.health_check { | ||||||
|             args_strings.push("--health-cmd".to_string()); |             args_strings.push("--health-cmd".to_string()); | ||||||
|             args_strings.push(health_check.cmd.clone()); |             args_strings.push(health_check.cmd.clone()); | ||||||
|              |  | ||||||
|             if let Some(interval) = &health_check.interval { |             if let Some(interval) = &health_check.interval { | ||||||
|                 args_strings.push("--health-interval".to_string()); |                 args_strings.push("--health-interval".to_string()); | ||||||
|                 args_strings.push(interval.clone()); |                 args_strings.push(interval.clone()); | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             if let Some(timeout) = &health_check.timeout { |             if let Some(timeout) = &health_check.timeout { | ||||||
|                 args_strings.push("--health-timeout".to_string()); |                 args_strings.push("--health-timeout".to_string()); | ||||||
|                 args_strings.push(timeout.clone()); |                 args_strings.push(timeout.clone()); | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             if let Some(retries) = &health_check.retries { |             if let Some(retries) = &health_check.retries { | ||||||
|                 args_strings.push("--health-retries".to_string()); |                 args_strings.push("--health-retries".to_string()); | ||||||
|                 args_strings.push(retries.to_string()); |                 args_strings.push(retries.to_string()); | ||||||
|             } |             } | ||||||
|              |  | ||||||
|             if let Some(start_period) = &health_check.start_period { |             if let Some(start_period) = &health_check.start_period { | ||||||
|                 args_strings.push("--health-start-period".to_string()); |                 args_strings.push("--health-start-period".to_string()); | ||||||
|                 args_strings.push(start_period.clone()); |                 args_strings.push(start_period.clone()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         if let Some(snapshotter_value) = &self.snapshotter { |         if let Some(snapshotter_value) = &self.snapshotter { | ||||||
|             args_strings.push("--snapshotter".to_string()); |             args_strings.push("--snapshotter".to_string()); | ||||||
|             args_strings.push(snapshotter_value.clone()); |             args_strings.push(snapshotter_value.clone()); | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         // Add flags to avoid BPF issues |         // Add flags to avoid BPF issues | ||||||
|         args_strings.push("--cgroup-manager=cgroupfs".to_string()); |         args_strings.push("--cgroup-manager=cgroupfs".to_string()); | ||||||
|          |  | ||||||
|         args_strings.push(image.clone()); |         args_strings.push(image.clone()); | ||||||
|          |  | ||||||
|         // Convert to string slices for the command |         // Convert to string slices for the command | ||||||
|         let args: Vec<&str> = args_strings.iter().map(|s| s.as_str()).collect(); |         let args: Vec<&str> = args_strings.iter().map(|s| s.as_str()).collect(); | ||||||
|          |  | ||||||
|         // Execute the command |         // Execute the command | ||||||
|         let result = execute_nerdctl_command(&args)?; |         let result = execute_nerdctl_command(&args)?; | ||||||
|          |  | ||||||
|         // Get the container ID from the output |         // Get the container ID from the output | ||||||
|         let container_id = result.stdout.trim().to_string(); |         let container_id = result.stdout.trim().to_string(); | ||||||
|          |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             name: self.name, |             name: self.name, | ||||||
|             container_id: Some(container_id), |             container_id: Some(container_id), | ||||||
| @@ -507,4 +514,4 @@ impl Container { | |||||||
|             snapshotter: self.snapshotter, |             snapshotter: self.snapshotter, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| // File: /root/code/git.threefold.info/herocode/sal/src/virt/nerdctl/images.rs | // File: /root/code/git.threefold.info/herocode/sal/src/virt/nerdctl/images.rs | ||||||
|  |  | ||||||
| use crate::virt::nerdctl::execute_nerdctl_command; |  | ||||||
| use crate::process::CommandResult; |  | ||||||
| use super::NerdctlError; | use super::NerdctlError; | ||||||
|  | use crate::process::CommandResult; | ||||||
|  | use crate::virt::nerdctl::execute_nerdctl_command; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
| /// Represents a container image | /// Represents a container image | ||||||
| @@ -26,18 +26,18 @@ pub fn images() -> Result<CommandResult, NerdctlError> { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// Remove one or more images | /// Remove one or more images | ||||||
| ///  | /// | ||||||
| /// # Arguments | /// # Arguments | ||||||
| ///  | /// | ||||||
| /// * `image` - Image ID or name | /// * `image` - Image ID or name | ||||||
| pub fn image_remove(image: &str) -> Result<CommandResult, NerdctlError> { | pub fn image_remove(image: &str) -> Result<CommandResult, NerdctlError> { | ||||||
|     execute_nerdctl_command(&["rmi", image]) |     execute_nerdctl_command(&["rmi", image]) | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Push an image to a registry | /// Push an image to a registry | ||||||
| ///  | /// | ||||||
| /// # Arguments | /// # Arguments | ||||||
| ///  | /// | ||||||
| /// * `image` - Image name | /// * `image` - Image name | ||||||
| /// * `destination` - Destination registry URL | /// * `destination` - Destination registry URL | ||||||
| pub fn image_push(image: &str, destination: &str) -> Result<CommandResult, NerdctlError> { | pub fn image_push(image: &str, destination: &str) -> Result<CommandResult, NerdctlError> { | ||||||
| @@ -45,9 +45,9 @@ pub fn image_push(image: &str, destination: &str) -> Result<CommandResult, Nerdc | |||||||
| } | } | ||||||
|  |  | ||||||
| /// Add an additional name to a local image | /// Add an additional name to a local image | ||||||
| ///  | /// | ||||||
| /// # Arguments | /// # Arguments | ||||||
| ///  | /// | ||||||
| /// * `image` - Image ID or name | /// * `image` - Image ID or name | ||||||
| /// * `new_name` - New name for the image | /// * `new_name` - New name for the image | ||||||
| pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, NerdctlError> { | pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, NerdctlError> { | ||||||
| @@ -55,18 +55,18 @@ pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, NerdctlEr | |||||||
| } | } | ||||||
|  |  | ||||||
| /// Pull an image from a registry | /// Pull an image from a registry | ||||||
| ///  | /// | ||||||
| /// # Arguments | /// # Arguments | ||||||
| ///  | /// | ||||||
| /// * `image` - Image name | /// * `image` - Image name | ||||||
| pub fn image_pull(image: &str) -> Result<CommandResult, NerdctlError> { | pub fn image_pull(image: &str) -> Result<CommandResult, NerdctlError> { | ||||||
|     execute_nerdctl_command(&["pull", image]) |     execute_nerdctl_command(&["pull", image]) | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Commit a container to an image | /// Commit a container to an image | ||||||
| ///  | /// | ||||||
| /// # Arguments | /// # Arguments | ||||||
| ///  | /// | ||||||
| /// * `container` - Container ID or name | /// * `container` - Container ID or name | ||||||
| /// * `image_name` - New name for the image | /// * `image_name` - New name for the image | ||||||
| pub fn image_commit(container: &str, image_name: &str) -> Result<CommandResult, NerdctlError> { | pub fn image_commit(container: &str, image_name: &str) -> Result<CommandResult, NerdctlError> { | ||||||
| @@ -74,11 +74,11 @@ pub fn image_commit(container: &str, image_name: &str) -> Result<CommandResult, | |||||||
| } | } | ||||||
|  |  | ||||||
| /// Build an image using a Dockerfile | /// Build an image using a Dockerfile | ||||||
| ///  | /// | ||||||
| /// # Arguments | /// # Arguments | ||||||
| ///  | /// | ||||||
| /// * `tag` - Tag for the new image | /// * `tag` - Tag for the new image | ||||||
| /// * `context_path` - Path to the build context | /// * `context_path` - Path to the build context | ||||||
| pub fn image_build(tag: &str, context_path: &str) -> Result<CommandResult, NerdctlError> { | pub fn image_build(tag: &str, context_path: &str) -> Result<CommandResult, NerdctlError> { | ||||||
|     execute_nerdctl_command(&["build", "-t", tag, context_path]) |     execute_nerdctl_command(&["build", "-t", tag, context_path]) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| use std::sync::{Arc, Mutex, Once}; |  | ||||||
| use std::sync::atomic::{AtomicBool, Ordering}; |  | ||||||
| use lazy_static::lazy_static; | use lazy_static::lazy_static; | ||||||
| use zinit_client::{Client as ZinitClient, ClientError, Status}; |  | ||||||
| use std::collections::HashMap; |  | ||||||
| use serde_json::{Map, Value}; | use serde_json::{Map, Value}; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | use std::sync::atomic::{AtomicBool, Ordering}; | ||||||
|  | use std::sync::{Arc, Mutex, Once}; | ||||||
|  | use zinit_client::{ServiceState, ServiceStatus as Status, ZinitClient, ZinitError}; | ||||||
|  |  | ||||||
| // Global Zinit client instance using lazy_static | // Global Zinit client instance using lazy_static | ||||||
| lazy_static! { | lazy_static! { | ||||||
| @@ -27,7 +27,7 @@ impl ZinitClientWrapper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Initialize the client |     // Initialize the client | ||||||
|     async fn initialize(&self) -> Result<(), ClientError> { |     async fn initialize(&self) -> Result<(), ZinitError> { | ||||||
|         if self.initialized.load(Ordering::Relaxed) { |         if self.initialized.load(Ordering::Relaxed) { | ||||||
|             return Ok(()); |             return Ok(()); | ||||||
|         } |         } | ||||||
| @@ -43,88 +43,86 @@ impl ZinitClientWrapper { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // List all services |     // List all services | ||||||
|     pub async fn list(&self) -> Result<HashMap<String, String>, ClientError> { |     pub async fn list(&self) -> Result<HashMap<String, ServiceState>, ZinitError> { | ||||||
|         self.client.list().await |         self.client.list().await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Get status of a service |     // Get status of a service | ||||||
|     pub async fn status(&self, name: &str) -> Result<Status, ClientError> { |     pub async fn status(&self, name: &str) -> Result<Status, ZinitError> { | ||||||
|         self.client.status(name).await |         self.client.status(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Start a service |     // Start a service | ||||||
|     pub async fn start(&self, name: &str) -> Result<(), ClientError> { |     pub async fn start(&self, name: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.start(name).await |         self.client.start(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Stop a service |     // Stop a service | ||||||
|     pub async fn stop(&self, name: &str) -> Result<(), ClientError> { |     pub async fn stop(&self, name: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.stop(name).await |         self.client.stop(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Restart a service |     // Restart a service | ||||||
|     pub async fn restart(&self, name: &str) -> Result<(), ClientError> { |     pub async fn restart(&self, name: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.restart(name).await |         self.client.restart(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Monitor a service |     // Monitor a service | ||||||
|     pub async fn monitor(&self, name: &str) -> Result<(), ClientError> { |     pub async fn monitor(&self, name: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.monitor(name).await |         self.client.monitor(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Forget a service |     // Forget a service | ||||||
|     pub async fn forget(&self, name: &str) -> Result<(), ClientError> { |     pub async fn forget(&self, name: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.forget(name).await |         self.client.forget(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Send a signal to a service |     // Send a signal to a service | ||||||
|     pub async fn kill(&self, name: &str, signal: &str) -> Result<(), ClientError> { |     pub async fn kill(&self, name: &str, signal: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.kill(name, signal).await |         self.client.kill(name, signal).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create a new service |     // Create a new service | ||||||
|     pub async fn create_service(&self, name: &str, content: Map<String, Value>) -> Result<String, ClientError> { |     pub async fn create_service( | ||||||
|         self.client.create_service(name, content).await |         &self, | ||||||
|  |         name: &str, | ||||||
|  |         content: Map<String, Value>, | ||||||
|  |     ) -> Result<(), ZinitError> { | ||||||
|  |         self.client | ||||||
|  |             .create_service(name, Value::Object(content)) | ||||||
|  |             .await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Delete a service |     // Delete a service | ||||||
|     pub async fn delete_service(&self, name: &str) -> Result<String, ClientError> { |     pub async fn delete_service(&self, name: &str) -> Result<(), ZinitError> { | ||||||
|         self.client.delete_service(name).await |         self.client.delete_service(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Get a service configuration |     // Get a service configuration | ||||||
|     pub async fn get_service(&self, name: &str) -> Result<Value, ClientError> { |     pub async fn get_service(&self, name: &str) -> Result<Value, ZinitError> { | ||||||
|         self.client.get_service(name).await |         self.client.get_service(name).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Shutdown the system |     // Shutdown the system | ||||||
|     pub async fn shutdown(&self) -> Result<(), ClientError> { |     pub async fn shutdown(&self) -> Result<(), ZinitError> { | ||||||
|         self.client.shutdown().await |         self.client.shutdown().await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Reboot the system |     // Reboot the system | ||||||
|     pub async fn reboot(&self) -> Result<(), ClientError> { |     pub async fn reboot(&self) -> Result<(), ZinitError> { | ||||||
|         self.client.reboot().await |         self.client.reboot().await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Start HTTP server |     // Get logs (simplified implementation - returns empty for now due to LogStream complexity) | ||||||
|     pub async fn start_http_server(&self, address: &str) -> Result<String, ClientError> { |     pub async fn logs(&self, _filter: Option<String>) -> Result<Vec<String>, ZinitError> { | ||||||
|         self.client.start_http_server(address).await |         // TODO: Implement proper LogStream handling when tokio-stream is available | ||||||
|     } |         // For now, return empty logs to avoid compilation errors | ||||||
|  |         Ok(Vec::new()) | ||||||
|     // Stop HTTP server |  | ||||||
|     pub async fn stop_http_server(&self) -> Result<(), ClientError> { |  | ||||||
|         self.client.stop_http_server().await |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Get logs |  | ||||||
|     pub async fn logs(&self, filter: Option<String>) -> Result<Vec<String>, ClientError> { |  | ||||||
|         self.client.logs(filter).await |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| // Get the Zinit client instance | // Get the Zinit client instance | ||||||
| pub async fn get_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ClientError> { | pub async fn get_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ZinitError> { | ||||||
|     // Check if we already have a client |     // Check if we already have a client | ||||||
|     { |     { | ||||||
|         let guard = ZINIT_CLIENT.lock().unwrap(); |         let guard = ZINIT_CLIENT.lock().unwrap(); | ||||||
| @@ -132,39 +130,39 @@ pub async fn get_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrappe | |||||||
|             return Ok(Arc::clone(client)); |             return Ok(Arc::clone(client)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     // Create a new client |     // Create a new client | ||||||
|     let client = create_zinit_client(socket_path).await?; |     let client = create_zinit_client(socket_path).await?; | ||||||
|      |  | ||||||
|     // Store the client globally |     // Store the client globally | ||||||
|     { |     { | ||||||
|         let mut guard = ZINIT_CLIENT.lock().unwrap(); |         let mut guard = ZINIT_CLIENT.lock().unwrap(); | ||||||
|         *guard = Some(Arc::clone(&client)); |         *guard = Some(Arc::clone(&client)); | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     Ok(client) |     Ok(client) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Create a new Zinit client | // Create a new Zinit client | ||||||
| async fn create_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ClientError> { | async fn create_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ZinitError> { | ||||||
|     // Connect via Unix socket |     // Connect via Unix socket - use new() instead of unix_socket() | ||||||
|     let client = ZinitClient::unix_socket(socket_path).await?; |     let client = ZinitClient::new(socket_path); | ||||||
|     let wrapper = Arc::new(ZinitClientWrapper::new(client)); |     let wrapper = Arc::new(ZinitClientWrapper::new(client)); | ||||||
|      |  | ||||||
|     // Initialize the client |     // Initialize the client | ||||||
|     wrapper.initialize().await?; |     wrapper.initialize().await?; | ||||||
|      |  | ||||||
|     Ok(wrapper) |     Ok(wrapper) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Reset the Zinit client | // Reset the Zinit client | ||||||
| pub async fn reset(socket_path: &str) -> Result<(), ClientError> { | pub async fn reset(socket_path: &str) -> Result<(), ZinitError> { | ||||||
|     // Clear the existing client |     // Clear the existing client | ||||||
|     { |     { | ||||||
|         let mut client_guard = ZINIT_CLIENT.lock().unwrap(); |         let mut client_guard = ZINIT_CLIENT.lock().unwrap(); | ||||||
|         *client_guard = None; |         *client_guard = None; | ||||||
|     } |     } | ||||||
|      |  | ||||||
|     // Create a new client, only return error if it fails |     // Create a new client, only return error if it fails | ||||||
|     get_zinit_client(socket_path).await?; |     get_zinit_client(socket_path).await?; | ||||||
|     Ok(()) |     Ok(()) | ||||||
| @@ -172,32 +170,40 @@ pub async fn reset(socket_path: &str) -> Result<(), ClientError> { | |||||||
|  |  | ||||||
| // Convenience functions for common operations | // Convenience functions for common operations | ||||||
|  |  | ||||||
| // List all services | // List all services - convert ServiceState to String for compatibility | ||||||
| pub async fn list(socket_path: &str) -> Result<HashMap<String, String>, ClientError> { | pub async fn list(socket_path: &str) -> Result<HashMap<String, String>, ZinitError> { | ||||||
|     let client = get_zinit_client(socket_path).await?; |     let client = get_zinit_client(socket_path).await?; | ||||||
|     client.list().await |     let services = client.list().await?; | ||||||
|  |  | ||||||
|  |     // Convert HashMap<String, ServiceState> to HashMap<String, String> | ||||||
|  |     let mut result = HashMap::new(); | ||||||
|  |     for (name, state) in services { | ||||||
|  |         result.insert(name, format!("{:?}", state)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Ok(result) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Get status of a service | // Get status of a service | ||||||
| pub async fn status(socket_path: &str, name: &str) -> Result<Status, ClientError> { | pub async fn status(socket_path: &str, name: &str) -> Result<Status, ZinitError> { | ||||||
|     let client = get_zinit_client(socket_path).await?; |     let client = get_zinit_client(socket_path).await?; | ||||||
|     client.status(name).await |     client.status(name).await | ||||||
| } | } | ||||||
|  |  | ||||||
| // Start a service | // Start a service | ||||||
| pub async fn start(socket_path: &str, name: &str) -> Result<(), ClientError> { | pub async fn start(socket_path: &str, name: &str) -> Result<(), ZinitError> { | ||||||
|     let client = get_zinit_client(socket_path).await?; |     let client = get_zinit_client(socket_path).await?; | ||||||
|     client.start(name).await |     client.start(name).await | ||||||
| } | } | ||||||
|  |  | ||||||
| // Stop a service | // Stop a service | ||||||
| pub async fn stop(socket_path: &str, name: &str) -> Result<(), ClientError> { | pub async fn stop(socket_path: &str, name: &str) -> Result<(), ZinitError> { | ||||||
|     let client = get_zinit_client(socket_path).await?; |     let client = get_zinit_client(socket_path).await?; | ||||||
|     client.stop(name).await |     client.stop(name).await | ||||||
| } | } | ||||||
|  |  | ||||||
| // Restart a service | // Restart a service | ||||||
| pub async fn restart(socket_path: &str, name: &str) -> Result<(), ClientError> { | pub async fn restart(socket_path: &str, name: &str) -> Result<(), ZinitError> { | ||||||
|     let client = get_zinit_client(socket_path).await?; |     let client = get_zinit_client(socket_path).await?; | ||||||
|     client.restart(name).await |     client.restart(name).await | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,6 +17,6 @@ serde_json = "1.0.140" | |||||||
| chacha20poly1305 = "0.10.1" | chacha20poly1305 = "0.10.1" | ||||||
| k256 = { version = "0.13.4", features = ["ecdh"] } | k256 = { version = "0.13.4", features = ["ecdh"] } | ||||||
| sha2 = "0.10.9" | sha2 = "0.10.9" | ||||||
| kv = { git = "https://git.ourworld.tf/samehabouelsaad/sal-modular", package = "kvstore", rev = "9dce815daa" } | kv = { git = "https://git.threefold.info/samehabouelsaad/sal-modular", package = "kvstore", rev = "9dce815daa" } | ||||||
| bincode = { version = "2.0.1", features = ["serde"] } | bincode = { version = "2.0.1", features = ["serde"] } | ||||||
| pbkdf2 = "0.12.2" | pbkdf2 = "0.12.2" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user