223 lines
12 KiB
Markdown
223 lines
12 KiB
Markdown
# 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`:
|
|
1. A fluent **`Container` builder pattern** for defining, creating, and managing containers with detailed configurations.
|
|
2. **Direct static functions** that wrap common `nerdctl` commands 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)`: `nerdctl` command failed to start (e.g., not found).
|
|
- `CommandFailed(String)`: `nerdctl` command executed but returned an error.
|
|
- `JsonParseError(String)`: Failure to parse JSON output from `nerdctl`.
|
|
- `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`.
|
|
|
|
```rust
|
|
// 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 Rhai `container_build` implies `true` often).
|
|
- `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 uses `nerdctl_container_new(name)` and `nerdctl_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()` (in `container_builder.rs`): Assembles and executes `nerdctl run` with all configured options. Populates `container_id` on success.
|
|
- `start()` (in `container_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()` (in `container_operations.rs`): Stops the container.
|
|
- `remove()` (in `container_operations.rs`): Removes the container.
|
|
- `exec(command: &str)` (in `container_operations.rs`): Executes a command in the container.
|
|
- `copy(source: &str, dest: &str)` (in `container_operations.rs`): Copies files/folders. `source`/`dest` must be formatted like `container_name_or_id:/path` or `/local/path`.
|
|
- `status()` (in `container_operations.rs`): Returns `ContainerStatus` by parsing `nerdctl inspect`.
|
|
- `health_status()` (in `container_operations.rs`): Returns the health status string from `nerdctl inspect`.
|
|
- `logs()` (in `container_operations.rs`): Fetches container logs.
|
|
- `resources()` (in `container_operations.rs`): Returns `ResourceUsage` by parsing `nerdctl stats`.
|
|
- `commit(image_name: &str)` (in `container_operations.rs`): Commits the container to a new image.
|
|
- `export(path: &str)` (in `container_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: String`
|
|
- `repository: String`
|
|
- `tag: String`
|
|
- `size: String`
|
|
- `created: 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 from `nerdctl inspect` (state, status, created, started, health info).
|
|
- `ResourceUsage`: Holds parsed data from `nerdctl stats` (CPU, memory, network, block I/O, PIDs).
|
|
|
|
## Usage Examples
|
|
|
|
### Rust Example (Builder Pattern)
|
|
|
|
```rust
|
|
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`)
|
|
|
|
```rhai
|
|
// 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 `Container` struct uses a builder pattern, allowing for clear and chainable configuration of container parameters before execution.
|
|
- **Comprehensive Operations**: Covers most common `nerdctl` functionalities for containers and images.
|
|
- **Error Handling**: `NerdctlError` provides 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) and `nerdctl 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`: Core `execute_nerdctl_command` function.
|
|
- `src/virt/nerdctl/container_types.rs`: Definitions for `Container`, `HealthCheck`, `ContainerStatus`, `ResourceUsage`.
|
|
- `src/virt/nerdctl/container_builder.rs`: Implements the builder pattern methods for the `Container` struct.
|
|
- `src/virt/nerdctl/container_operations.rs`: Implements instance methods on `Container` (start, stop, status, etc.).
|
|
- `src/virt/nerdctl/images.rs`: `Image` struct 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 for `prepare_health_check_command`.
|
|
- `src/rhai/nerdctl.rs`: Rhai script bindings for `herodo`. |