diff --git a/src/virt/buildah/buildah.rs b/src/virt/buildah/buildah.rs deleted file mode 100644 index cd3d10d..0000000 --- a/src/virt/buildah/buildah.rs +++ /dev/null @@ -1,60 +0,0 @@ -// Basic buildah operations for container management -use std::process::Command; -use rhai::{Dynamic, Map}; - -/// A structure to hold command execution results -#[derive(Clone)] -pub struct CommandResult { - pub stdout: String, - pub stderr: String, - pub success: bool, - pub code: i32, -} - -impl CommandResult { - /// Create a result map from CommandResult - pub fn to_dynamic(&self) -> Dynamic { - let mut result = Map::new(); - result.insert("stdout".into(), Dynamic::from(self.stdout.clone())); - result.insert("stderr".into(), Dynamic::from(self.stderr.clone())); - result.insert("success".into(), Dynamic::from(self.success)); - result.insert("code".into(), Dynamic::from(self.code)); - Dynamic::from(result) - } - - /// Create a default failed result with an error message - pub fn error(message: &str) -> Self { - Self { - stdout: String::new(), - stderr: message.to_string(), - success: false, - code: -1, - } - } -} - -/// Execute a buildah command and return the result -pub fn execute_buildah_command(args: &[&str]) -> Dynamic { - let output = Command::new("buildah") - .args(args) - .output(); - - match output { - Ok(output) => { - let stdout = String::from_utf8_lossy(&output.stdout).to_string(); - let stderr = String::from_utf8_lossy(&output.stderr).to_string(); - - let result = CommandResult { - stdout, - stderr, - success: output.status.success(), - code: output.status.code().unwrap_or(-1), - }; - - result.to_dynamic() - }, - Err(e) => { - CommandResult::error(&format!("Failed to execute buildah command: {}", e)).to_dynamic() - } - } -} diff --git a/src/virt/buildah/buildah_register.rs b/src/virt/buildah/buildah_register.rs deleted file mode 100644 index efd437b..0000000 --- a/src/virt/buildah/buildah_register.rs +++ /dev/null @@ -1,671 +0,0 @@ -use rhai::{Engine, Dynamic, Map, Array, EvalAltResult}; -use std::process::Command; -use crate::herocontainer::buildah::execute_buildah_command; -use crate::herocontainer::buildah_build::{build_copy, build_add}; -use crate::herocontainer::buildah_images::{image_commit, image_pull, image_tag, image_push, images, config, image_remove}; -use crate::herocontainer::engine::create_error_result; - -// Implement functions needed for container operations -pub fn from_wrapper(image: &str, name: &str) -> Result> { - // Implementation of the function to create container from image with name - let result = execute_buildah_command(&["from", "--name", name, image]); - let mut result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to create container from image {} with name {}: {}", image, name, error).into()); - } - - // Extract the container ID from stdout and add it to the result - let stdout = match result_map.get("stdout") { - Some(val) => val.to_string(), - None => "".to_string(), - }; - let container_id = stdout.trim(); - - result_map.insert("container_id".into(), Dynamic::from(container_id.to_string())); - - Ok(Dynamic::from(result_map)) -} - -// Single argument version for backward compatibility -pub fn from_wrapper_single(image: &str) -> Result> { - // Implementation of the function to create container from image - let result = execute_buildah_command(&["from", image]); - let mut result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to create container from image {}: {}", image, error).into()); - } - - // Extract the container ID from stdout and add it to the result - let stdout = match result_map.get("stdout") { - Some(val) => val.to_string(), - None => "".to_string(), - }; - let container_id = stdout.trim(); - - result_map.insert("container_id".into(), Dynamic::from(container_id.to_string())); - - Ok(Dynamic::from(result_map)) -} - -pub fn run_wrapper(container: &str, command: &str) -> Result> { - let result = execute_buildah_command(&["run", container, "--", "sh", "-c", command]); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to run command '{}' in container {}: {}", command, container, error).into()); - } - Ok(result) -} - -pub fn run_with_args_wrapper(container: &str, command: &str, args: Array) -> Result> { - // Create owned strings to avoid lifetime issues - let mut cmd_args_owned: Vec = Vec::new(); - cmd_args_owned.push("run".to_string()); - cmd_args_owned.push(container.to_string()); - cmd_args_owned.push("--".to_string()); - cmd_args_owned.push(command.to_string()); - - for arg in args.iter() { - cmd_args_owned.push(arg.to_string()); - } - - // Convert to &str for the command - let cmd_args: Vec<&str> = cmd_args_owned.iter().map(|s| s.as_str()).collect(); - - let result = execute_buildah_command(&cmd_args); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to run command '{}' with args in container {}: {}", command, container, error).into()); - } - Ok(result) -} - -pub fn run_script_wrapper(container: &str, script: &str) -> Result> { - let result = execute_buildah_command(&["run", container, "--", "sh", "-c", script]); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to run script in container {}: {}", container, error).into()); - } - Ok(result) -} - -pub fn mount_wrapper(container: &str) -> Result> { - let result = execute_buildah_command(&["mount", container]); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to mount container {}: {}", container, error).into()); - } - Ok(result) -} - -pub fn build(context_dir: &str, file: Option<&str>, tag: Option<&str>, format: Option<&str>, - layers: bool, pull: bool, no_cache: bool) -> Dynamic { - let mut args = vec!["build"]; - - if let Some(file_path) = file { - args.push("-f"); - args.push(file_path); - } - - if let Some(tag_name) = tag { - args.push("-t"); - args.push(tag_name); - } - - if let Some(format_str) = format { - args.push("--format"); - args.push(format_str); - } - - if layers { - args.push("--layers"); - } - - if pull { - args.push("--pull"); - } - - if no_cache { - args.push("--no-cache"); - } - - args.push(context_dir); - - execute_buildah_command(&args) -} - -pub fn containers() -> Dynamic { - execute_buildah_command(&["containers", "--format", "json"]) -} - -pub fn rm(container: &str) -> Dynamic { - execute_buildah_command(&["rm", container]) -} - -pub fn copy_wrapper(container: &str, source: &str, destination: &str) -> Result> { - let result = build_copy(container, source, destination); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to copy '{}' to '{}' in container {}: {}", source, destination, container, error).into()); - } - Ok(result) -} - -pub fn add_wrapper(container: &str, source: &str, destination: &str) -> Result> { - let result = build_add(container, source, destination); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to add '{}' to '{}' in container {}: {}", source, destination, container, error).into()); - } - Ok(result) -} - -// Configuring Containers -pub fn config_wrapper(container: &str, options: Map) -> Result> { - let result = config(container, options); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to configure container {}: {}", container, error).into()); - } - Ok(result) -} - -// Building Images -pub fn commit_wrapper(container: &str, image_name: &str) -> Result> { - let result = image_commit(container, image_name, None, false, false); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to commit container {} to image {}: {}", container, image_name, error).into()); - } - - // Extract the image ID if present - if let Some(stdout) = result_map.get("stdout") { - let image_id = stdout.to_string().trim().to_string(); - let mut result_clone = result_map.clone(); - result_clone.insert("image_id".into(), Dynamic::from(image_id)); - return Ok(Dynamic::from(result_clone)); - } - - Ok(result) -} - -pub fn commit_full_wrapper(container: &str, image_name: &str, format: &str, squash: bool, rm: bool) -> Result> { - let result = image_commit(container, image_name, Some(format), squash, rm); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to commit container {} to image {} (format: {}): {}", - container, image_name, format, error).into()); - } - - // Extract the image ID if present - if let Some(stdout) = result_map.get("stdout") { - let image_id = stdout.to_string().trim().to_string(); - let mut result_clone = result_map.clone(); - result_clone.insert("image_id".into(), Dynamic::from(image_id)); - return Ok(Dynamic::from(result_clone)); - } - - Ok(result) -} - -//TODO: don't know what this is need more info -// pub fn build_wrapper(context_dir: &str) -> Result> { -// let result = container_build(context_dir, None, None, None, false, false, false); -// if !result.get("success").as_bool().unwrap_or(false) { -// let error = result.get("error").to_string(); -// return Err(format!("Failed to build image from context {}: {}", context_dir, error).into()); -// } -// Ok(result) -// } - -// pub fn build_with_tag_wrapper(context_dir: &str, tag: &str) -> Result> { -// let result = build(context_dir, None, Some(tag), None, false, false, false); -// if !result.get("success").as_bool().unwrap_or(false) { -// let error = result.get("error").to_string(); -// return Err(format!("Failed to build image with tag {} from context {}: {}", -// tag, context_dir, error).into()); -// } -// Ok(result) -// } - -pub fn build_full_wrapper(context_dir: &str, file: &str, tag: &str, format: &str, - layers: bool, pull: bool, no_cache: bool) -> Result> { - let result = build(context_dir, Some(file), Some(tag), Some(format), layers, pull, no_cache); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to build image with tag {} from file {} in context {}: {}", - tag, file, context_dir, error).into()); - } - Ok(result) -} - -// Managing Images -pub fn images_wrapper() -> Result> { - let result = images(); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to list images: {}", error).into()); - } - Ok(result) -} - -pub fn rmi_wrapper(image: &str) -> Result> { - let result = image_remove(image); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to remove image {}: {}", image, error).into()); - } - Ok(result) -} - -pub fn push_wrapper(image: &str, destination: &str) -> Result> { - let result = image_push(image, destination, true); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to push image {} to {}: {}", image, destination, error).into()); - } - Ok(result) -} - -pub fn push_with_tls_wrapper(image: &str, destination: &str, tls_verify: bool) -> Result> { - let result = image_push(image, destination, tls_verify); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to push image {} to {}: {}", image, destination, error).into()); - } - Ok(result) -} - -pub fn tag_wrapper(image: &str, new_name: &str) -> Result> { - let result = image_tag(image, new_name); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to tag image {} as {}: {}", image, new_name, error).into()); - } - Ok(result) -} - -pub fn pull_wrapper(image: &str) -> Result> { - let result = image_pull(image, true); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to pull image {}: {}", image, error).into()); - } - Ok(result) -} - -pub fn pull_with_tls_wrapper(image: &str, tls_verify: bool) -> Result> { - let result = image_pull(image, tls_verify); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to pull image {}: {}", image, error).into()); - } - Ok(result) -} - -pub fn containers_wrapper() -> Result> { - let result = containers(); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to list containers: {}", error).into()); - } - Ok(result) -} - -pub fn rm_wrapper(container: &str) -> Result> { - let result = rm(container); - let result_map = match result.clone().try_cast::() { - Some(map) => map, - None => { - return Err("Failed to convert result to map".into()); - } - }; - - let success = match result_map.get("success") { - Some(val) => val.as_bool().unwrap_or(false), - None => false, - }; - - if !success { - let error = match result_map.get("stderr") { - Some(val) => val.to_string(), - None => "Unknown error".to_string(), - }; - return Err(format!("Failed to remove container {}: {}", container, error).into()); - } - Ok(result) -} - -/// Register buildah functions with the Rhai engine -pub fn register_buildah_functions(engine: &mut Engine) { - // Creating Containers - engine.register_fn("container_from", from_wrapper); - engine.register_fn("container_from", from_wrapper_single); - - // Working with Containers - engine.register_fn("container_run", run_wrapper); - engine.register_fn("container_run_with_args", run_with_args_wrapper); - engine.register_fn("container_run_script", run_script_wrapper); - engine.register_fn("container_copy", copy_wrapper); - engine.register_fn("container_add", add_wrapper); - engine.register_fn("container_mount", mount_wrapper); - - // Configuring Containers - engine.register_fn("container_config", config_wrapper); - - // Building Images - engine.register_fn("container_commit", commit_wrapper); - engine.register_fn("container_commit_full", commit_full_wrapper); - // Only register build_full_wrapper since the other build wrappers are commented out - engine.register_fn("container_build", build_full_wrapper); - - // Managing Images - engine.register_fn("container_images", images_wrapper); - engine.register_fn("container_rmi", rmi_wrapper); - engine.register_fn("container_push", push_wrapper); - engine.register_fn("container_push_tls", push_with_tls_wrapper); - engine.register_fn("container_tag", tag_wrapper); - engine.register_fn("container_pull", pull_wrapper); - engine.register_fn("container_pull_tls", pull_with_tls_wrapper); - engine.register_fn("container_list", containers_wrapper); - engine.register_fn("container_rm", rm_wrapper); -} diff --git a/src/virt/buildah/cmd.rs b/src/virt/buildah/cmd.rs new file mode 100644 index 0000000..0214697 --- /dev/null +++ b/src/virt/buildah/cmd.rs @@ -0,0 +1,29 @@ +// Basic buildah operations for container management +use std::process::Command; + + +/// Execute a buildah command and return the result +pub fn execute_buildah_command(args: &[&str]) -> Dynamic { + let output = Command::new("buildah") + .args(args) + .output(); + + match output { + Ok(output) => { + let stdout = String::from_utf8_lossy(&output.stdout).to_string(); + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + + let result = CommandResult { + stdout, + stderr, + success: output.status.success(), + code: output.status.code().unwrap_or(-1), + }; + + result.to_dynamic() + }, + Err(e) => { + CommandResult::error(&format!("Failed to execute buildah command: {}", e)).to_dynamic() + } + } +} diff --git a/src/virt/buildah/buildah_build.rs b/src/virt/buildah/containers.rs similarity index 88% rename from src/virt/buildah/buildah_build.rs rename to src/virt/buildah/containers.rs index 34f2342..e2aa0b5 100644 --- a/src/virt/buildah/buildah_build.rs +++ b/src/virt/buildah/containers.rs @@ -1,6 +1,5 @@ -// Main buildah integration for HeroContainer -use rhai::{Engine, Dynamic}; -use crate::herocontainer::buildah::execute_buildah_command; + +use crate::virt::buildah::execute_buildah_command; /// Create a container from an image pub fn build_from(image: &str) -> Dynamic { diff --git a/src/virt/buildah/buildah_images.rs b/src/virt/buildah/images.rs similarity index 89% rename from src/virt/buildah/buildah_images.rs rename to src/virt/buildah/images.rs index 67008d3..ddf660f 100644 --- a/src/virt/buildah/buildah_images.rs +++ b/src/virt/buildah/images.rs @@ -1,7 +1,5 @@ -use rhai::{Engine, Dynamic, Map, Array, EvalAltResult}; use std::process::Command; -use crate::herocontainer::buildah::execute_buildah_command; -use crate::herocontainer::engine::create_error_result; +use crate::virt::buildah::execute_buildah_command; /// List images in local storage /// @@ -13,12 +11,7 @@ pub fn images() -> Dynamic { let result_map = match result.clone().try_cast::() { Some(map) => map, None => { - return create_result( - "", - "Failed to convert result to map", - false, - -1 - ); + return create_result("", "Failed to convert result to map", false, -1); } }; @@ -225,12 +218,3 @@ pub fn config(container: &str, options: Map) -> Dynamic { execute_buildah_command(&args) } -/// Helper function to create a standardized result -pub fn create_result(stdout: &str, stderr: &str, success: bool, code: i32) -> Dynamic { - let mut result = Map::new(); - result.insert("stdout".into(), Dynamic::from(stdout.to_string())); - result.insert("stderr".into(), Dynamic::from(stderr.to_string())); - result.insert("success".into(), Dynamic::from(success)); - result.insert("code".into(), Dynamic::from(code)); - Dynamic::from(result) -} diff --git a/src/virt/buildah/mod.rs b/src/virt/buildah/mod.rs index c4b4810..cc84555 100644 --- a/src/virt/buildah/mod.rs +++ b/src/virt/buildah/mod.rs @@ -1,14 +1,8 @@ -// Herocontainer module provides container management capabilities via buildah -// using Rhai scripting integration +mod containers; +mod images; +mod cmd; -pub mod buildah; -pub mod buildah_build; -pub mod buildah_images; -pub mod engine; -pub mod buildah_register; - -pub use engine::*; -pub use buildah_images::*; -pub use buildah_build::*; -pub use buildah_register::*; +pub use containers::*; +pub use images::*; +pub use cmd::*;