...
This commit is contained in:
		| @@ -23,17 +23,16 @@ When you get information about a running process, you can see: | ||||
| - `cpu`: How much CPU the process is using | ||||
|  | ||||
| ## Run Functions | ||||
|  | ||||
| ### `run(command)` | ||||
|  | ||||
| Runs a command or multiline script with arguments. | ||||
|  | ||||
| **Parameters:** | ||||
| - `command` (string): The command to run | ||||
| - `command` (string): The command to run (can be a single command or a multiline script) | ||||
|  | ||||
| **Returns:** The result of the command, including output and whether it succeeded. | ||||
|  | ||||
| **Example:** | ||||
| **Example 1: Running a simple command** | ||||
| ```rhai | ||||
| // Run a simple command | ||||
| let result = run("ls -la"); | ||||
| @@ -46,6 +45,28 @@ if result.success { | ||||
| } | ||||
| ``` | ||||
|  | ||||
| **Example 2: Running a multiline script** | ||||
| ```rhai | ||||
| // Create a multiline script using backtick string literals | ||||
| let setup_script = ` | ||||
| # Create directories | ||||
| mkdir -p /tmp/test_project | ||||
| cd /tmp/test_project | ||||
|  | ||||
| # Initialize git repository | ||||
| git init | ||||
| echo 'Initial content' > README.md | ||||
| git add README.md | ||||
| git config --local user.email 'test@example.com' | ||||
| git config --local user.name 'Test User' | ||||
| git commit -m 'Initial commit' | ||||
| `; | ||||
|  | ||||
| // Execute the multiline script | ||||
| let result = run(setup_script); | ||||
|  | ||||
| ``` | ||||
|  | ||||
|  | ||||
|  | ||||
| ### `run_silent(command)` | ||||
| @@ -110,6 +131,24 @@ options.log = true;       // Log the command execution | ||||
| let result = run_with_options("npm install", options); | ||||
| ``` | ||||
|  | ||||
| ## Working with Multiline Scripts | ||||
|  | ||||
| The Process module allows you to execute multiline scripts, which is particularly useful for complex operations that require multiple commands to be executed in sequence. | ||||
|  | ||||
| ### Creating Multiline Scripts | ||||
|  | ||||
| Multiline scripts can be created using backtick (`) string literals in Rhai: | ||||
|  | ||||
| ```rhai | ||||
| let my_script = ` | ||||
| # This is a multiline bash script | ||||
| echo "Hello, World!" | ||||
| mkdir -p /tmp/my_project | ||||
| cd /tmp/my_project | ||||
| touch example.txt | ||||
| `; | ||||
| ``` | ||||
|  | ||||
| ## Process Management Functions | ||||
|  | ||||
| ### `which(cmd)` | ||||
|   | ||||
| @@ -185,7 +185,7 @@ fn handle_child_output(mut child: Child, silent: bool) -> Result<CommandResult, | ||||
|                 if let Ok(l) = line { | ||||
|                     // Print the line if not silent and flush immediately | ||||
|                     if !silent_clone { | ||||
|                         // Print stderr with error prefix | ||||
|                         // Print all stderr messages | ||||
|                         eprintln!("\x1b[31mERROR: {}\x1b[0m", l); // Red color for errors | ||||
|                         std::io::stderr().flush().unwrap_or(()); | ||||
|                     } | ||||
| @@ -288,7 +288,7 @@ fn execute_script_internal(interpreter: &str, script_path: &Path, silent: bool) | ||||
|     let command_args = vec!["/c", script_path.to_str().unwrap_or("")]; | ||||
|      | ||||
|     #[cfg(any(target_os = "macos", target_os = "linux"))] | ||||
|     let command_args = vec![script_path.to_str().unwrap_or("")]; | ||||
|     let command_args = vec!["-e", script_path.to_str().unwrap_or("")]; | ||||
|      | ||||
|     if silent { | ||||
|         // For silent execution, use output() which captures but doesn't display | ||||
| @@ -334,16 +334,28 @@ fn execute_script_internal(interpreter: &str, script_path: &Path, silent: bool) | ||||
|  | ||||
| /// Run a multiline script with optional silent mode | ||||
| fn run_script_internal(script: &str, silent: bool) -> Result<CommandResult, RunError> { | ||||
|     // Prepare the script file first to get the content with shebang | ||||
|     let (script_path, interpreter, _temp_dir) = prepare_script_file(script)?; | ||||
|      | ||||
|     // Print the script being executed if not silent | ||||
|     if !silent { | ||||
|         println!("\x1b[36mExecuting script:\x1b[0m"); | ||||
|         for (i, line) in script.lines().enumerate() { | ||||
|             println!("\x1b[36m{:3}: {}\x1b[0m", i + 1, line); | ||||
|          | ||||
|         // Read the script file to get the content with shebang | ||||
|         if let Ok(script_content) = fs::read_to_string(&script_path) { | ||||
|             for (i, line) in script_content.lines().enumerate() { | ||||
|                 println!("\x1b[36m{:3}: {}\x1b[0m", i + 1, line); | ||||
|             } | ||||
|         } else { | ||||
|             // Fallback to original script if reading fails | ||||
|             for (i, line) in script.lines().enumerate() { | ||||
|                 println!("\x1b[36m{:3}: {}\x1b[0m", i + 1, line); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         println!("\x1b[36m---\x1b[0m"); | ||||
|     } | ||||
|      | ||||
|     let (script_path, interpreter, _temp_dir) = prepare_script_file(script)?; | ||||
|     // _temp_dir is kept in scope until the end of this function to ensure | ||||
|     // it's not dropped prematurely, which would clean up the directory | ||||
|      | ||||
|   | ||||
| @@ -3,60 +3,10 @@ | ||||
| //! This module provides Rhai wrappers for the functions in the Nerdctl module. | ||||
|  | ||||
| use rhai::{Engine, EvalAltResult, Array, Dynamic, Map}; | ||||
| use crate::virt::nerdctl::{self, NerdctlError, Image}; | ||||
| use std::collections::HashMap; | ||||
| use crate::virt::nerdctl::{self, NerdctlError, Image, Container}; | ||||
| use crate::process::CommandResult; | ||||
|  | ||||
| /// Register Nerdctl module functions with the Rhai engine | ||||
| /// | ||||
| /// # Arguments | ||||
| /// | ||||
| /// * `engine` - The Rhai engine to register the functions with | ||||
| /// | ||||
| /// # Returns | ||||
| /// | ||||
| /// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise | ||||
| pub fn register_nerdctl_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> { | ||||
|     // Register types | ||||
|     register_nerdctl_types(engine)?; | ||||
|      | ||||
|     // Register container functions | ||||
|     engine.register_fn("nerdctl_run", nerdctl_run); | ||||
|     engine.register_fn("nerdctl_run_with_name", nerdctl_run_with_name); | ||||
|     engine.register_fn("nerdctl_run_with_port", nerdctl_run_with_port); | ||||
|     engine.register_fn("new_run_options", new_run_options); | ||||
|     engine.register_fn("nerdctl_exec", nerdctl_exec); | ||||
|     engine.register_fn("nerdctl_copy", nerdctl_copy); | ||||
|     engine.register_fn("nerdctl_stop", nerdctl_stop); | ||||
|     engine.register_fn("nerdctl_remove", nerdctl_remove); | ||||
|     engine.register_fn("nerdctl_list", nerdctl_list); | ||||
|      | ||||
|     // Register image functions | ||||
|     engine.register_fn("nerdctl_images", nerdctl_images); | ||||
|     engine.register_fn("nerdctl_image_remove", nerdctl_image_remove); | ||||
|     engine.register_fn("nerdctl_image_push", nerdctl_image_push); | ||||
|     engine.register_fn("nerdctl_image_tag", nerdctl_image_tag); | ||||
|     engine.register_fn("nerdctl_image_pull", nerdctl_image_pull); | ||||
|     engine.register_fn("nerdctl_image_commit", nerdctl_image_commit); | ||||
|     engine.register_fn("nerdctl_image_build", nerdctl_image_build); | ||||
|      | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| /// Register Nerdctl module types with the Rhai engine | ||||
| fn register_nerdctl_types(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> { | ||||
|     // Register Image type and methods | ||||
|     engine.register_type_with_name::<Image>("NerdctlImage"); | ||||
|      | ||||
|     // Register getters for Image properties | ||||
|     engine.register_get("id", |img: &mut Image| img.id.clone()); | ||||
|     engine.register_get("repository", |img: &mut Image| img.repository.clone()); | ||||
|     engine.register_get("tag", |img: &mut Image| img.tag.clone()); | ||||
|     engine.register_get("size", |img: &mut Image| img.size.clone()); | ||||
|     engine.register_get("created", |img: &mut Image| img.created.clone()); | ||||
|      | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| // Helper functions for error conversion | ||||
| fn nerdctl_error_to_rhai_error<T>(result: Result<T, NerdctlError>) -> Result<T, Box<EvalAltResult>> { | ||||
|     result.map_err(|e| { | ||||
| @@ -67,6 +17,100 @@ fn nerdctl_error_to_rhai_error<T>(result: Result<T, NerdctlError>) -> Result<T, | ||||
|     }) | ||||
| } | ||||
|  | ||||
| // | ||||
| // Container Builder Pattern Implementation | ||||
| // | ||||
|  | ||||
| /// Create a new Container | ||||
| pub fn container_new(name: &str) -> Result<Container, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(Container::new(name)) | ||||
| } | ||||
|  | ||||
| /// Create a Container from an image | ||||
| pub fn container_from_image(name: &str, image: &str) -> Result<Container, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(Container::from_image(name, image)) | ||||
| } | ||||
|  | ||||
| /// Add a port mapping to a Container | ||||
| pub fn container_with_port(mut container: Container, port: &str) -> Container { | ||||
|     container.with_port(port) | ||||
| } | ||||
|  | ||||
| /// Add a volume mount to a Container | ||||
| pub fn container_with_volume(mut container: Container, volume: &str) -> Container { | ||||
|     container.with_volume(volume) | ||||
| } | ||||
|  | ||||
| /// Add an environment variable to a Container | ||||
| pub fn container_with_env(mut container: Container, key: &str, value: &str) -> Container { | ||||
|     container.with_env(key, value) | ||||
| } | ||||
|  | ||||
| /// Set the network for a Container | ||||
| pub fn container_with_network(mut container: Container, network: &str) -> Container { | ||||
|     container.with_network(network) | ||||
| } | ||||
|  | ||||
| /// Add a network alias to a Container | ||||
| pub fn container_with_network_alias(mut container: Container, alias: &str) -> Container { | ||||
|     container.with_network_alias(alias) | ||||
| } | ||||
|  | ||||
| /// Set CPU limit for a Container | ||||
| pub fn container_with_cpu_limit(mut container: Container, cpus: &str) -> Container { | ||||
|     container.with_cpu_limit(cpus) | ||||
| } | ||||
|  | ||||
| /// Set memory limit for a Container | ||||
| pub fn container_with_memory_limit(mut container: Container, memory: &str) -> Container { | ||||
|     container.with_memory_limit(memory) | ||||
| } | ||||
|  | ||||
| /// Set restart policy for a Container | ||||
| pub fn container_with_restart_policy(mut container: Container, policy: &str) -> Container { | ||||
|     container.with_restart_policy(policy) | ||||
| } | ||||
|  | ||||
| /// Set health check for a Container | ||||
| pub fn container_with_health_check(mut container: Container, cmd: &str) -> Container { | ||||
|     container.with_health_check(cmd) | ||||
| } | ||||
|  | ||||
| /// Set detach mode for a Container | ||||
| pub fn container_with_detach(mut container: Container, detach: bool) -> Container { | ||||
|     container.with_detach(detach) | ||||
| } | ||||
|  | ||||
| /// Build and run the Container | ||||
| pub fn container_build(container: Container) -> Result<Container, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(container.build()) | ||||
| } | ||||
|  | ||||
| /// Start the Container | ||||
| pub fn container_start(container: &mut Container) -> Result<CommandResult, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(container.start()) | ||||
| } | ||||
|  | ||||
| /// Stop the Container | ||||
| pub fn container_stop(container: &mut Container) -> Result<CommandResult, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(container.stop()) | ||||
| } | ||||
|  | ||||
| /// Remove the Container | ||||
| pub fn container_remove(container: &mut Container) -> Result<CommandResult, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(container.remove()) | ||||
| } | ||||
|  | ||||
| /// Execute a command in the Container | ||||
| pub fn container_exec(container: &mut Container, command: &str) -> Result<CommandResult, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(container.exec(command)) | ||||
| } | ||||
|  | ||||
| /// Copy files between the Container and local filesystem | ||||
| pub fn container_copy(container: &mut Container, source: &str, dest: &str) -> Result<CommandResult, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(container.copy(source, dest)) | ||||
| } | ||||
|  | ||||
| /// Create a new Map with default run options | ||||
| pub fn new_run_options() -> Map { | ||||
|     let mut map = Map::new(); | ||||
| @@ -185,4 +229,110 @@ pub fn nerdctl_image_commit(container: &str, image_name: &str) -> Result<Command | ||||
| /// Build an image using a Dockerfile. | ||||
| pub fn nerdctl_image_build(tag: &str, context_path: &str) -> Result<CommandResult, Box<EvalAltResult>> { | ||||
|     nerdctl_error_to_rhai_error(nerdctl::image_build(tag, context_path)) | ||||
| } | ||||
|  | ||||
| /// Register Nerdctl module functions with the Rhai engine | ||||
| /// | ||||
| /// # Arguments | ||||
| /// | ||||
| /// * `engine` - The Rhai engine to register the functions with | ||||
| /// | ||||
| /// # Returns | ||||
| /// | ||||
| /// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise | ||||
| pub fn register_nerdctl_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> { | ||||
|     // Register types | ||||
|     register_nerdctl_types(engine)?; | ||||
|      | ||||
|     // Register Container constructor | ||||
|     engine.register_fn("nerdctl_container_new", container_new); | ||||
|     engine.register_fn("nerdctl_container_from_image", container_from_image); | ||||
|      | ||||
|     // Register Container instance methods | ||||
|     engine.register_fn("with_port", container_with_port); | ||||
|     engine.register_fn("with_volume", container_with_volume); | ||||
|     engine.register_fn("with_env", container_with_env); | ||||
|     engine.register_fn("with_network", container_with_network); | ||||
|     engine.register_fn("with_network_alias", container_with_network_alias); | ||||
|     engine.register_fn("with_cpu_limit", container_with_cpu_limit); | ||||
|     engine.register_fn("with_memory_limit", container_with_memory_limit); | ||||
|     engine.register_fn("with_restart_policy", container_with_restart_policy); | ||||
|     engine.register_fn("with_health_check", container_with_health_check); | ||||
|     engine.register_fn("with_detach", container_with_detach); | ||||
|     engine.register_fn("build", container_build); | ||||
|     engine.register_fn("start", container_start); | ||||
|     engine.register_fn("stop", container_stop); | ||||
|     engine.register_fn("remove", container_remove); | ||||
|     engine.register_fn("exec", container_exec); | ||||
|     engine.register_fn("copy", container_copy); | ||||
|      | ||||
|     // Register legacy container functions (for backward compatibility) | ||||
|     engine.register_fn("nerdctl_run", nerdctl_run); | ||||
|     engine.register_fn("nerdctl_run_with_name", nerdctl_run_with_name); | ||||
|     engine.register_fn("nerdctl_run_with_port", nerdctl_run_with_port); | ||||
|     engine.register_fn("new_run_options", new_run_options); | ||||
|     engine.register_fn("nerdctl_exec", nerdctl_exec); | ||||
|     engine.register_fn("nerdctl_copy", nerdctl_copy); | ||||
|     engine.register_fn("nerdctl_stop", nerdctl_stop); | ||||
|     engine.register_fn("nerdctl_remove", nerdctl_remove); | ||||
|     engine.register_fn("nerdctl_list", nerdctl_list); | ||||
|      | ||||
|     // Register image functions | ||||
|     engine.register_fn("nerdctl_images", nerdctl_images); | ||||
|     engine.register_fn("nerdctl_image_remove", nerdctl_image_remove); | ||||
|     engine.register_fn("nerdctl_image_push", nerdctl_image_push); | ||||
|     engine.register_fn("nerdctl_image_tag", nerdctl_image_tag); | ||||
|     engine.register_fn("nerdctl_image_pull", nerdctl_image_pull); | ||||
|     engine.register_fn("nerdctl_image_commit", nerdctl_image_commit); | ||||
|     engine.register_fn("nerdctl_image_build", nerdctl_image_build); | ||||
|      | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| /// Register Nerdctl module types with the Rhai engine | ||||
| fn register_nerdctl_types(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> { | ||||
|     // Register Container type | ||||
|     engine.register_type_with_name::<Container>("NerdctlContainer"); | ||||
|      | ||||
|     // Register getters for Container properties | ||||
|     engine.register_get("name", |container: &mut Container| container.name.clone()); | ||||
|     engine.register_get("container_id", |container: &mut Container| { | ||||
|         match &container.container_id { | ||||
|             Some(id) => id.clone(), | ||||
|             None => "".to_string(), | ||||
|         } | ||||
|     }); | ||||
|     engine.register_get("image", |container: &mut Container| { | ||||
|         match &container.image { | ||||
|             Some(img) => img.clone(), | ||||
|             None => "".to_string(), | ||||
|         } | ||||
|     }); | ||||
|     engine.register_get("ports", |container: &mut Container| { | ||||
|         let mut array = Array::new(); | ||||
|         for port in &container.ports { | ||||
|             array.push(Dynamic::from(port.clone())); | ||||
|         } | ||||
|         array | ||||
|     }); | ||||
|     engine.register_get("volumes", |container: &mut Container| { | ||||
|         let mut array = Array::new(); | ||||
|         for volume in &container.volumes { | ||||
|             array.push(Dynamic::from(volume.clone())); | ||||
|         } | ||||
|         array | ||||
|     }); | ||||
|     engine.register_get("detach", |container: &mut Container| container.detach); | ||||
|      | ||||
|     // Register Image type and methods | ||||
|     engine.register_type_with_name::<Image>("NerdctlImage"); | ||||
|      | ||||
|     // Register getters for Image properties | ||||
|     engine.register_get("id", |img: &mut Image| img.id.clone()); | ||||
|     engine.register_get("repository", |img: &mut Image| img.repository.clone()); | ||||
|     engine.register_get("tag", |img: &mut Image| img.tag.clone()); | ||||
|     engine.register_get("size", |img: &mut Image| img.size.clone()); | ||||
|     engine.register_get("created", |img: &mut Image| img.created.clone()); | ||||
|      | ||||
|     Ok(()) | ||||
| } | ||||
| @@ -29,7 +29,8 @@ println(`- snapshotter: ${run_options.snapshotter}`); | ||||
| // Test function availability | ||||
| println("\nTesting function availability:"); | ||||
| let functions = [ | ||||
|     "nerdctl_run",  | ||||
|     // Legacy functions | ||||
|     "nerdctl_run", | ||||
|     "nerdctl_run_with_name", | ||||
|     "nerdctl_run_with_port", | ||||
|     "nerdctl_exec", | ||||
| @@ -43,7 +44,27 @@ let functions = [ | ||||
|     "nerdctl_image_tag", | ||||
|     "nerdctl_image_pull", | ||||
|     "nerdctl_image_commit", | ||||
|     "nerdctl_image_build" | ||||
|     "nerdctl_image_build", | ||||
|      | ||||
|     // Builder pattern functions | ||||
|     "nerdctl_container_new", | ||||
|     "nerdctl_container_from_image", | ||||
|     "with_port", | ||||
|     "with_volume", | ||||
|     "with_env", | ||||
|     "with_network", | ||||
|     "with_network_alias", | ||||
|     "with_cpu_limit", | ||||
|     "with_memory_limit", | ||||
|     "with_restart_policy", | ||||
|     "with_health_check", | ||||
|     "with_detach", | ||||
|     "build", | ||||
|     "start", | ||||
|     "stop", | ||||
|     "remove", | ||||
|     "exec", | ||||
|     "copy" | ||||
| ]; | ||||
|  | ||||
| // Try to access each function (this will throw an error if the function doesn't exist) | ||||
| @@ -52,6 +73,107 @@ for func in functions { | ||||
|     println(`Function ${func} registered: ${exists}`); | ||||
| } | ||||
|  | ||||
| // Helper function to get current timestamp in seconds | ||||
| fn timestamp() { | ||||
|     // Use the current time in seconds since epoch as a unique identifier | ||||
|     return now(); | ||||
| } | ||||
|  | ||||
| // Test the builder pattern with actual container creation and execution | ||||
| println("\nTesting container builder pattern with actual container:"); | ||||
| try { | ||||
|     // Generate a unique container name based on timestamp | ||||
|     let container_name = "test-alpine-container"; | ||||
|      | ||||
|     // First, try to remove any existing container with this name | ||||
|     println(`Cleaning up any existing container named '${container_name}'...`); | ||||
|     try { | ||||
|         // Try to stop the container first (in case it's running) | ||||
|         nerdctl_stop(container_name); | ||||
|         println("Stopped existing container"); | ||||
|     } catch(e) { | ||||
|         println("No running container to stop"); | ||||
|     } | ||||
|      | ||||
|     try { | ||||
|         // Try to remove the container | ||||
|         nerdctl_remove(container_name); | ||||
|         println("Removed existing container"); | ||||
|     } catch(e) { | ||||
|         println("No container to remove"); | ||||
|     } | ||||
|      | ||||
|     // Create a container with builder pattern using Alpine image with a command that keeps it running | ||||
|     println("\nCreating new container from Alpine image..."); | ||||
|     let container = nerdctl_container_from_image(container_name, "alpine:latest"); | ||||
|     println(`Created container from image: ${container.name} (${container.image})`); | ||||
|      | ||||
|     // Configure the container | ||||
|     container = container | ||||
|         .with_port("8080:80") | ||||
|         .with_volume("/tmp:/data") | ||||
|         .with_env("TEST_ENV", "test_value") | ||||
|         .with_detach(true); | ||||
|      | ||||
|     // Print container properties before building | ||||
|     println("Container properties before building:"); | ||||
|     println(`- name: ${container.name}`); | ||||
|     println(`- image: ${container.image}`); | ||||
|     println(`- ports: ${container.ports}`); | ||||
|     println(`- volumes: ${container.volumes}`); | ||||
|     println(`- detach: ${container.detach}`); | ||||
|      | ||||
|     // Build the container | ||||
|     println("\nBuilding the container..."); | ||||
|     container = container.build(); | ||||
|      | ||||
|     // Print container ID after building | ||||
|     println(`Container built successfully with ID: ${container.container_id}`); | ||||
|      | ||||
|     // Start the container | ||||
|     println("\nStarting the container..."); | ||||
|     let start_result = container.start(); | ||||
|     println(`Start result: ${start_result.success}`); | ||||
|      | ||||
|     // Execute a command in the running container | ||||
|     println("\nExecuting command in the container..."); | ||||
|     let run_cmd = container.exec("echo 'Hello from Alpine container'"); | ||||
|     println(`Command output: ${run_cmd.stdout}`); | ||||
|      | ||||
|     // List all containers to verify it's running | ||||
|     println("\nListing all containers:"); | ||||
|     let list_result = nerdctl_list(true); | ||||
|     println(`Container list: ${list_result.stdout}`); | ||||
|      | ||||
|     // Stop and remove the container | ||||
|     println("\nStopping and removing the container..."); | ||||
|     let stop_result = container.stop(); | ||||
|     println(`Stop result: ${stop_result.success}`); | ||||
|      | ||||
|     let remove_result = container.remove(); | ||||
|     println(`Remove result: ${remove_result.success}`); | ||||
|     println("Container stopped and removed successfully"); | ||||
|      | ||||
|     // Return success message only if everything worked | ||||
|     return "Container builder pattern test completed successfully!"; | ||||
| } catch(e) { | ||||
|     // Print the error and return a failure message | ||||
|     println(`ERROR: ${e}`); | ||||
|      | ||||
|     // Try to clean up if possible | ||||
|     try { | ||||
|         println("Attempting to clean up after error..."); | ||||
|         nerdctl_stop("test-alpine-container"); | ||||
|         nerdctl_remove("test-alpine-container"); | ||||
|         println("Cleanup completed"); | ||||
|     } catch(cleanup_error) { | ||||
|         println(`Cleanup failed: ${cleanup_error}`); | ||||
|     } | ||||
|      | ||||
|     // Return failure message | ||||
|     return "Container builder pattern test FAILED!"; | ||||
| } | ||||
|  | ||||
| // Helper function to check if a function is registered | ||||
| fn is_function_registered(name) { | ||||
|     try { | ||||
| @@ -63,4 +185,4 @@ fn is_function_registered(name) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| "Nerdctl wrapper test completed successfully!" | ||||
| // The final result depends on the outcome of the container test | ||||
| @@ -2,6 +2,9 @@ | ||||
|  | ||||
| // Create a bash script to set up the test environment | ||||
| let setup_script = ` | ||||
| # Configure git to suppress the default branch name warning | ||||
| git config --global advice.initDefaultBranch false | ||||
|  | ||||
| rm -rf /tmp/code | ||||
| mkdir -p /tmp/code | ||||
| cd /tmp/code | ||||
| @@ -17,7 +20,7 @@ git config --local user.email 'test@example.com' | ||||
| git config --local user.name 'Test User' | ||||
| git commit -m 'Initial commit' | ||||
|  | ||||
| cd myserver.com/myaccount/repored | ||||
| cd /tmp/code/myserver.com/myaccount/repored | ||||
| git init | ||||
| echo 'Initial test file' > test2.txt | ||||
| git add test2.txt | ||||
| @@ -25,7 +28,7 @@ git config --local user.email 'test@example.com' | ||||
| git config --local user.name 'Test User' | ||||
| git commit -m 'Initial commit' | ||||
|  | ||||
| //now we have 2 repos | ||||
| # now we have 2 repos | ||||
|  | ||||
| `; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user