- Migrate individual modules to independent crates - Refactor dependencies for improved modularity - Update build system and testing infrastructure - Update documentation to reflect new structure
SAL nerdctl Module (sal::virt::nerdctl)
Overview
The sal::virt::nerdctl module provides a comprehensive Rust interface for interacting with nerdctl, a command-line tool for containerd.
It allows for managing container lifecycles, images, and other nerdctl functionalities programmatically from Rust and through Rhai scripts via herodo.
This module offers two primary ways to interact with nerdctl:
- A fluent
Containerbuilder pattern for defining, creating, and managing containers with detailed configurations. - Direct static functions that wrap common
nerdctlcommands for quick operations on containers and images.
Core Components
1. NerdctlError (in mod.rs)
An enum defining specific error types for nerdctl operations:
CommandExecutionFailed(io::Error):nerdctlcommand failed to start (e.g., not found).CommandFailed(String):nerdctlcommand executed but returned an error.JsonParseError(String): Failure to parse JSON output fromnerdctl.ConversionError(String): Error during data type conversions.Other(String): Generic errors.
2. execute_nerdctl_command (in cmd.rs)
The core function for executing nerdctl commands. It takes an array of string arguments, runs the command, and returns a CommandResult or NerdctlError.
// Example (internal usage)
// use sal::virt::nerdctl::execute_nerdctl_command;
// let result = execute_nerdctl_command(&["ps", "-a"]);
3. Container Struct (defined in container_types.rs, builder in container_builder.rs, operations in container_operations.rs)
Represents a nerdctl container and is the centerpiece of the builder pattern.
Fields (Configuration):
name: String: Name of the container.container_id: Option<String>: ID of the container (populated after creation).image: Option<String>: Base image for the container.ports: Vec<String>: Port mappings (e.g.,"8080:80").volumes: Vec<String>: Volume mounts (e.g.,"/host/path:/container/path").env_vars: HashMap<String, String>: Environment variables.network: Option<String>: Network to connect to.network_aliases: Vec<String>: Network aliases.cpu_limit: Option<String>,memory_limit: Option<String>,memory_swap_limit: Option<String>,cpu_shares: Option<String>: Resource limits.restart_policy: Option<String>: Restart policy (e.g.,"always").health_check: Option<HealthCheck>: Health check configuration.detach: bool: Whether to run in detached mode (default:false, but Rhaicontainer_buildimpliestrueoften).snapshotter: Option<String>: Snapshotter to use.
Builder Methods (Fluent Interface - impl Container in container_builder.rs):
These methods configure the Container object and return Self for chaining.
Container::new(name: &str, image: &str): Constructor (Note: Rhai usesnerdctl_container_new(name)andnerdctl_container_from_image(name, image)which call underlying Rust constructors).reset(): Resets configuration, stops/removes existing container with the same name.with_port(port: &str),with_ports(ports: &[&str])with_volume(volume: &str),with_volumes(volumes: &[&str])with_env(key: &str, value: &str),with_envs(env_map: &HashMap<&str, &str>)with_network(network: &str)with_network_alias(alias: &str),with_network_aliases(aliases: &[&str])with_cpu_limit(cpus: &str)with_memory_limit(memory: &str)with_memory_swap_limit(memory_swap: &str)with_cpu_shares(shares: &str)with_restart_policy(policy: &str)with_health_check(cmd: &str)with_health_check_options(cmd, interval, timeout, retries, start_period)with_snapshotter(snapshotter: &str)with_detach(detach: bool)
**Action Methods (on Container instances):
build()(incontainer_builder.rs): Assembles and executesnerdctl runwith all configured options. Populatescontainer_idon success.start()(incontainer_operations.rs): Starts the container. If not yet built, it attempts to pull the image and build the container first. Verifies the container is running and provides detailed logs/status on failure.stop()(incontainer_operations.rs): Stops the container.remove()(incontainer_operations.rs): Removes the container.exec(command: &str)(incontainer_operations.rs): Executes a command in the container.copy(source: &str, dest: &str)(incontainer_operations.rs): Copies files/folders.source/destmust be formatted likecontainer_name_or_id:/pathor/local/path.status()(incontainer_operations.rs): ReturnsContainerStatusby parsingnerdctl inspect.health_status()(incontainer_operations.rs): Returns the health status string fromnerdctl inspect.logs()(incontainer_operations.rs): Fetches container logs.resources()(incontainer_operations.rs): ReturnsResourceUsageby parsingnerdctl stats.commit(image_name: &str)(incontainer_operations.rs): Commits the container to a new image.export(path: &str)(incontainer_operations.rs): Exports the container's filesystem as a tarball.
4. HealthCheck Struct (in container_types.rs)
Defines health check parameters:
cmd: String: Command to execute.interval: Option<String>timeout: Option<String>retries: Option<u32>start_period: Option<String>
5. prepare_health_check_command (in health_check_script.rs)
A helper function that takes a health check command string. If it's multi-line, it attempts to save it as an executable script in /root/hero/var/containers/healthcheck_<container_name>.sh and returns the script path. Otherwise, returns the command as is. The path /root/hero/var/containers implies this script needs to be accessible from within the target container at that specific location if a multi-line script is used.
6. Image Struct (in images.rs)
Represents a nerdctl image, typically from nerdctl images output.
id: Stringrepository: Stringtag: Stringsize: Stringcreated: String
7. Static Image Functions (in images.rs)
These functions operate on images:
images() -> Result<CommandResult, NerdctlError>: Lists images (nerdctl images).image_remove(image: &str): Removes an image (nerdctl rmi).image_push(image: &str, destination: &str): Pushes an image (nerdctl push).image_tag(image: &str, new_name: &str): Tags an image (nerdctl tag).image_pull(image: &str): Pulls an image (nerdctl pull).image_commit(container: &str, image_name: &str): Commits a container to an image (nerdctl commit).image_build(tag: &str, context_path: &str): Builds an image from a Dockerfile (nerdctl build -t <tag> <context_path>).
8. Static Container Functions (in container_functions.rs)
Direct wrappers for nerdctl commands, an alternative to the builder pattern:
run(image: &str, name: Option<&str>, detach: bool, ports: Option<&[&str]>, snapshotter: Option<&str>): Runs a container.exec(container: &str, command: &str): Executes a command in a running container.copy(source: &str, dest: &str): Copies files.stop(container: &str): Stops a container.remove(container: &str): Removes a container.list(all: bool): Lists containers (nerdctl ps).logs(container: &str): Fetches logs for a container.
9. ContainerStatus and ResourceUsage Structs (in container_types.rs)
ContainerStatus: Holds parsed data fromnerdctl inspect(state, status, created, started, health info).ResourceUsage: Holds parsed data fromnerdctl stats(CPU, memory, network, block I/O, PIDs).
Usage Examples
Rust Example (Builder Pattern)
use sal::virt::nerdctl::{Container, NerdctlError};
use std::collections::HashMap;
fn main() -> Result<(), NerdctlError> {
let mut envs = HashMap::new();
envs.insert("MY_VAR", "my_value");
let container_config = Container::new("my_nginx_container", "nginx:latest") // Assuming a constructor like this exists or is adapted
.with_port("8080:80")
.with_envs(&envs)
.with_detach(true)
.with_restart_policy("always");
// Build (create and run) the container
let built_container = container_config.build()?;
println!("Container {} created with ID: {:?}", built_container.name, built_container.container_id);
// Perform operations
let status = built_container.status()?;
println!("Status: {}, State: {}", status.status, status.state);
// Stop and remove
built_container.stop()?;
built_container.remove()?;
println!("Container stopped and removed.");
Ok(())
}
Note: The direct Container::new(name, image) constructor isn't explicitly shown in the provided Rust code snippets for Container itself, but the Rhai bindings nerdctl_container_new and nerdctl_container_from_image imply underlying Rust constructors that initialize a Container struct. The build() method is the primary way to run it after configuration.
Rhai Script Example (using herodo)
// Create and configure a container using the builder pattern
let c = nerdctl_container_from_image("my_redis", "redis:alpine")
.with_port("6379:6379")
.with_restart_policy("unless-stopped");
// Build and run the container
let running_container = c.build();
if running_container.is_ok() {
print(`Container ${running_container.name} ID: ${running_container.container_id}`);
// Get status
let status = running_container.status();
if status.is_ok() {
print(`Status: ${status.state}, Health: ${status.health_status}`);
}
// Stop the container (example, might need a mutable borrow or re-fetch)
// running_container.stop(); // Assuming stop is available and works on the result
// running_container.remove();
} else {
print(`Error building container: ${running_container.error()}`);
}
// Direct command example
let images = nerdctl_images();
print(images.stdout);
nerdctl_image_pull("alpine:latest");
Key Design Points
- Fluent Builder: The
Containerstruct uses a builder pattern, allowing for clear and chainable configuration of container parameters before execution. - Comprehensive Operations: Covers most common
nerdctlfunctionalities for containers and images. - Error Handling:
NerdctlErrorprovides typed errors. The Rhai layer adds more descriptive error messages for common scenarios. - Dual API: Offers both a detailed builder pattern and simpler static functions for flexibility.
- Health Check Scripting: Supports multi-line shell scripts for health checks by saving them to a file, though care must be taken regarding the script's accessibility from within the target container.
- Resource Parsing: Includes parsing for
nerdctl inspect(JSON) andnerdctl stats(tabular text) to provide structured information.
File Structure
src/virt/nerdctl/mod.rs: Main module file, error definitions, sub-module declarations.src/virt/nerdctl/cmd.rs: Coreexecute_nerdctl_commandfunction.src/virt/nerdctl/container_types.rs: Definitions forContainer,HealthCheck,ContainerStatus,ResourceUsage.src/virt/nerdctl/container_builder.rs: Implements the builder pattern methods for theContainerstruct.src/virt/nerdctl/container_operations.rs: Implements instance methods onContainer(start, stop, status, etc.).src/virt/nerdctl/images.rs:Imagestruct and static functions for image management.src/virt/nerdctl/container_functions.rs: Static functions for direct container commands.src/virt/nerdctl/health_check_script.rs: Logic forprepare_health_check_command.src/rhai/nerdctl.rs: Rhai script bindings forherodo.