Compare commits
2 Commits
c7908cb6e4
...
a32cfb788b
Author | SHA1 | Date | |
---|---|---|---|
a32cfb788b | |||
6cc05ad2eb |
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Main buildah integration for HeroContainer
|
||||
use rhai::{Engine, Dynamic};
|
||||
use crate::herocontainer::buildah::execute_buildah_command;
|
||||
|
||||
/// Create a container from an image
|
||||
pub fn build_from(image: &str) -> Dynamic {
|
||||
execute_buildah_command(&["from", image])
|
||||
}
|
||||
|
||||
/// Run a command in a container
|
||||
pub fn build_run(container: &str, command: &str) -> Dynamic {
|
||||
execute_buildah_command(&["run", container, "sh", "-c", command])
|
||||
}
|
||||
|
||||
/// Copy files into a container
|
||||
pub fn build_copy(container: &str, source: &str, dest: &str) -> Dynamic {
|
||||
execute_buildah_command(&["copy", container, source, dest])
|
||||
}
|
||||
|
||||
pub fn build_add(container: &str, source: &str, dest: &str) -> Dynamic {
|
||||
execute_buildah_command(&["add", container, source, dest])
|
||||
}
|
||||
|
||||
/// Commit a container to an image
|
||||
pub fn build_commit(container: &str, image_name: &str) -> Dynamic {
|
||||
execute_buildah_command(&["commit", container, image_name])
|
||||
}
|
||||
|
||||
|
||||
/// Remove a container
|
||||
pub fn build_remove(container: &str) -> Dynamic {
|
||||
execute_buildah_command(&["rm", container])
|
||||
}
|
||||
|
||||
/// List containers
|
||||
pub fn build_list() -> Dynamic {
|
||||
execute_buildah_command(&["containers"])
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
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;
|
||||
|
||||
/// List images in local storage
|
||||
///
|
||||
/// # Returns
|
||||
/// * Array of image details on success or error details
|
||||
pub fn images() -> Dynamic {
|
||||
let result = execute_buildah_command(&["images", "--format", "json"]);
|
||||
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
Some(map) => map,
|
||||
None => {
|
||||
return create_result(
|
||||
"",
|
||||
"Failed to convert result to map",
|
||||
false,
|
||||
-1
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let success = match result_map.get("success") {
|
||||
Some(val) => val.as_bool().unwrap_or(false),
|
||||
None => false,
|
||||
};
|
||||
|
||||
if success {
|
||||
let output = match result_map.get("stdout") {
|
||||
Some(val) => val.to_string(),
|
||||
None => "".to_string(),
|
||||
};
|
||||
|
||||
// Try to parse the JSON output
|
||||
match serde_json::from_str::<serde_json::Value>(&output) {
|
||||
Ok(json) => {
|
||||
if let serde_json::Value::Array(images) = json {
|
||||
let mut image_array = Array::new();
|
||||
|
||||
for image in images {
|
||||
let mut image_map = Map::new();
|
||||
|
||||
if let Some(id) = image.get("id").and_then(|v| v.as_str()) {
|
||||
image_map.insert("id".into(), Dynamic::from(id.to_string()));
|
||||
}
|
||||
|
||||
if let Some(name) = image.get("names").and_then(|v| v.as_array()) {
|
||||
let mut names_array = Array::new();
|
||||
for name_value in name {
|
||||
if let Some(name_str) = name_value.as_str() {
|
||||
names_array.push(Dynamic::from(name_str.to_string()));
|
||||
}
|
||||
}
|
||||
image_map.insert("names".into(), Dynamic::from(names_array));
|
||||
}
|
||||
|
||||
if let Some(size) = image.get("size").and_then(|v| v.as_str()) {
|
||||
image_map.insert("size".into(), Dynamic::from(size.to_string()));
|
||||
}
|
||||
|
||||
if let Some(created) = image.get("created").and_then(|v| v.as_str()) {
|
||||
image_map.insert("created".into(), Dynamic::from(created.to_string()));
|
||||
}
|
||||
|
||||
image_array.push(Dynamic::from(image_map));
|
||||
}
|
||||
|
||||
let mut result_map = match result.clone().try_cast::<Map>() {
|
||||
Some(map) => map,
|
||||
None => Map::new(),
|
||||
};
|
||||
result_map.insert("images".into(), Dynamic::from(image_array));
|
||||
Dynamic::from(result_map)
|
||||
} else {
|
||||
create_result(
|
||||
"",
|
||||
"Failed to parse image list: Expected JSON array",
|
||||
false,
|
||||
-1
|
||||
)
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
create_result(
|
||||
"",
|
||||
&format!("Failed to parse image list JSON: {}", e),
|
||||
false,
|
||||
-1
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Remove one or more images
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image ID or name
|
||||
///
|
||||
/// # Returns
|
||||
/// * Success or error details
|
||||
pub fn image_remove(image: &str) -> Dynamic {
|
||||
execute_buildah_command(&["rmi", image])
|
||||
}
|
||||
|
||||
/// Push an image to a registry
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image name
|
||||
/// * `destination` - Destination (e.g., "docker://registry.example.com/myimage:latest")
|
||||
/// * `tls_verify` - Whether to verify TLS (default: true)
|
||||
///
|
||||
/// # Returns
|
||||
/// * Success or error details
|
||||
pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Dynamic {
|
||||
let mut args = vec!["push"];
|
||||
|
||||
if !tls_verify {
|
||||
args.push("--tls-verify=false");
|
||||
}
|
||||
|
||||
args.push(image);
|
||||
args.push(destination);
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
||||
|
||||
/// Add an additional name to a local image
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image ID or name
|
||||
/// * `new_name` - New name for the image
|
||||
///
|
||||
/// # Returns
|
||||
/// * Success or error details
|
||||
pub fn image_tag(image: &str, new_name: &str) -> Dynamic {
|
||||
execute_buildah_command(&["tag", image, new_name])
|
||||
}
|
||||
|
||||
/// Pull an image from a registry
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image name
|
||||
/// * `tls_verify` - Whether to verify TLS (default: true)
|
||||
///
|
||||
/// # Returns
|
||||
/// * Success or error details
|
||||
pub fn image_pull(image: &str, tls_verify: bool) -> Dynamic {
|
||||
let mut args = vec!["pull"];
|
||||
|
||||
if !tls_verify {
|
||||
args.push("--tls-verify=false");
|
||||
}
|
||||
|
||||
args.push(image);
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
||||
|
||||
/// Commit a container to an image
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `container` - Container ID or name
|
||||
/// * `image_name` - New name for the image
|
||||
/// * `format` - Optional, format to use for the image (oci or docker)
|
||||
/// * `squash` - Whether to squash layers
|
||||
/// * `rm` - Whether to remove the container after commit
|
||||
///
|
||||
/// # Returns
|
||||
/// * Success or error details
|
||||
pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool) -> Dynamic {
|
||||
let mut args = vec!["commit"];
|
||||
|
||||
if let Some(format_str) = format {
|
||||
args.push("--format");
|
||||
args.push(format_str);
|
||||
}
|
||||
|
||||
if squash {
|
||||
args.push("--squash");
|
||||
}
|
||||
|
||||
if rm {
|
||||
args.push("--rm");
|
||||
}
|
||||
|
||||
args.push(container);
|
||||
args.push(image_name);
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
||||
|
||||
/// Container configuration options
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `container` - Container ID or name
|
||||
/// * `options` - Map of configuration options
|
||||
///
|
||||
/// # Returns
|
||||
/// * Success or error details
|
||||
pub fn config(container: &str, options: Map) -> Dynamic {
|
||||
let mut args_owned: Vec<String> = Vec::new();
|
||||
args_owned.push("config".to_string());
|
||||
|
||||
// Process options map
|
||||
for (key, value) in options.iter() {
|
||||
let option_name = format!("--{}", key);
|
||||
args_owned.push(option_name);
|
||||
|
||||
if !value.is_unit() {
|
||||
args_owned.push(value.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
args_owned.push(container.to_string());
|
||||
|
||||
// Convert Vec<String> to Vec<&str> for execute_buildah_command
|
||||
let args: Vec<&str> = args_owned.iter().map(|s| s.as_str()).collect();
|
||||
|
||||
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)
|
||||
}
|
@ -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<Dynamic, Box<EvalAltResult>> {
|
||||
// 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::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
// 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::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = execute_buildah_command(&["run", container, "--", "sh", "-c", command]);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
// Create owned strings to avoid lifetime issues
|
||||
let mut cmd_args_owned: Vec<String> = 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::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = execute_buildah_command(&["run", container, "--", "sh", "-c", script]);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = execute_buildah_command(&["mount", container]);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = build_copy(container, source, destination);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = build_add(container, source, destination);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = config(container, options);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_commit(container, image_name, None, false, false);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_commit(container, image_name, Some(format), squash, rm);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
// 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<Dynamic, Box<EvalAltResult>> {
|
||||
// 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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = build(context_dir, Some(file), Some(tag), Some(format), layers, pull, no_cache);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = images();
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_remove(image);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_push(image, destination, true);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_push(image, destination, tls_verify);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_tag(image, new_name);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_pull(image, true);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = image_pull(image, tls_verify);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = containers();
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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<Dynamic, Box<EvalAltResult>> {
|
||||
let result = rm(container);
|
||||
let result_map = match result.clone().try_cast::<Map>() {
|
||||
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);
|
||||
}
|
36
src/virt/buildah/cmd.rs
Normal file
36
src/virt/buildah/cmd.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// Basic buildah operations for container management
|
||||
use std::process::Command;
|
||||
use crate::process::CommandResult;
|
||||
use super::BuildahError;
|
||||
|
||||
|
||||
/// Execute a buildah command and return the result
|
||||
pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
|
||||
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),
|
||||
};
|
||||
|
||||
if result.success {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(BuildahError::CommandFailed(format!("Command failed with code {}: {}",
|
||||
result.code, result.stderr.trim())))
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
Err(BuildahError::CommandExecutionFailed(e))
|
||||
}
|
||||
}
|
||||
}
|
38
src/virt/buildah/containers.rs
Normal file
38
src/virt/buildah/containers.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use crate::virt::buildah::execute_buildah_command;
|
||||
use crate::process::CommandResult;
|
||||
use super::BuildahError;
|
||||
|
||||
/// Create a container from an image
|
||||
pub fn from(image: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["from", image])
|
||||
}
|
||||
|
||||
/// Run a command in a container
|
||||
pub fn run(container: &str, command: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["run", container, "sh", "-c", command])
|
||||
}
|
||||
|
||||
/// Copy files into a container
|
||||
pub fn copy(container: &str, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["copy", container, source, dest])
|
||||
}
|
||||
|
||||
pub fn add(container: &str, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["add", container, source, dest])
|
||||
}
|
||||
|
||||
/// Commit a container to an image
|
||||
pub fn commit(container: &str, image_name: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["commit", container, image_name])
|
||||
}
|
||||
|
||||
|
||||
/// Remove a container
|
||||
pub fn remove(container: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["rm", container])
|
||||
}
|
||||
|
||||
/// List containers
|
||||
pub fn list() -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["containers"])
|
||||
}
|
211
src/virt/buildah/images.rs
Normal file
211
src/virt/buildah/images.rs
Normal file
@ -0,0 +1,211 @@
|
||||
use std::process::Command;
|
||||
use std::collections::HashMap;
|
||||
use crate::virt::buildah::execute_buildah_command;
|
||||
use crate::process::CommandResult;
|
||||
use super::BuildahError;
|
||||
use serde_json::{self, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Represents a container image
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Image {
|
||||
/// Image ID
|
||||
pub id: String,
|
||||
/// Image names/tags
|
||||
pub names: Vec<String>,
|
||||
/// Image size
|
||||
pub size: String,
|
||||
/// Creation timestamp
|
||||
pub created: String,
|
||||
}
|
||||
|
||||
/// List images in local storage
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with array of Image objects on success or error details
|
||||
pub fn images() -> Result<Vec<Image>, BuildahError> {
|
||||
let result = execute_buildah_command(&["images", "--format", "json"])?;
|
||||
|
||||
// Try to parse the JSON output
|
||||
match serde_json::from_str::<serde_json::Value>(&result.stdout) {
|
||||
Ok(json) => {
|
||||
if let Value::Array(images_json) = json {
|
||||
let mut images = Vec::new();
|
||||
|
||||
for image_json in images_json {
|
||||
// Extract image ID
|
||||
let id = match image_json.get("id").and_then(|v| v.as_str()) {
|
||||
Some(id) => id.to_string(),
|
||||
None => return Err(BuildahError::ConversionError("Missing image ID".to_string())),
|
||||
};
|
||||
|
||||
// Extract image names
|
||||
let names = match image_json.get("names").and_then(|v| v.as_array()) {
|
||||
Some(names_array) => {
|
||||
let mut names_vec = Vec::new();
|
||||
for name_value in names_array {
|
||||
if let Some(name_str) = name_value.as_str() {
|
||||
names_vec.push(name_str.to_string());
|
||||
}
|
||||
}
|
||||
names_vec
|
||||
},
|
||||
None => Vec::new(), // Empty vector if no names found
|
||||
};
|
||||
|
||||
// Extract image size
|
||||
let size = match image_json.get("size").and_then(|v| v.as_str()) {
|
||||
Some(size) => size.to_string(),
|
||||
None => "Unknown".to_string(), // Default value if size not found
|
||||
};
|
||||
|
||||
// Extract creation timestamp
|
||||
let created = match image_json.get("created").and_then(|v| v.as_str()) {
|
||||
Some(created) => created.to_string(),
|
||||
None => "Unknown".to_string(), // Default value if created not found
|
||||
};
|
||||
|
||||
// Create Image struct and add to vector
|
||||
images.push(Image {
|
||||
id,
|
||||
names,
|
||||
size,
|
||||
created,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(images)
|
||||
} else {
|
||||
Err(BuildahError::JsonParseError("Expected JSON array".to_string()))
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
Err(BuildahError::JsonParseError(format!("Failed to parse image list JSON: {}", e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove one or more images
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image ID or name
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with command output or error
|
||||
pub fn image_remove(image: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["rmi", image])
|
||||
}
|
||||
|
||||
/// Push an image to a registry
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image name
|
||||
/// * `destination` - Destination (e.g., "docker://registry.example.com/myimage:latest")
|
||||
/// * `tls_verify` - Whether to verify TLS (default: true)
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with command output or error
|
||||
pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
||||
let mut args = vec!["push"];
|
||||
|
||||
if !tls_verify {
|
||||
args.push("--tls-verify=false");
|
||||
}
|
||||
|
||||
args.push(image);
|
||||
args.push(destination);
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
||||
|
||||
/// Add an additional name to a local image
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image ID or name
|
||||
/// * `new_name` - New name for the image
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with command output or error
|
||||
pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, BuildahError> {
|
||||
execute_buildah_command(&["tag", image, new_name])
|
||||
}
|
||||
|
||||
/// Pull an image from a registry
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `image` - Image name
|
||||
/// * `tls_verify` - Whether to verify TLS (default: true)
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with command output or error
|
||||
pub fn image_pull(image: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
||||
let mut args = vec!["pull"];
|
||||
|
||||
if !tls_verify {
|
||||
args.push("--tls-verify=false");
|
||||
}
|
||||
|
||||
args.push(image);
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
||||
|
||||
/// Commit a container to an image
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `container` - Container ID or name
|
||||
/// * `image_name` - New name for the image
|
||||
/// * `format` - Optional, format to use for the image (oci or docker)
|
||||
/// * `squash` - Whether to squash layers
|
||||
/// * `rm` - Whether to remove the container after commit
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with command output or error
|
||||
pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool) -> Result<CommandResult, BuildahError> {
|
||||
let mut args = vec!["commit"];
|
||||
|
||||
if let Some(format_str) = format {
|
||||
args.push("--format");
|
||||
args.push(format_str);
|
||||
}
|
||||
|
||||
if squash {
|
||||
args.push("--squash");
|
||||
}
|
||||
|
||||
if rm {
|
||||
args.push("--rm");
|
||||
}
|
||||
|
||||
args.push(container);
|
||||
args.push(image_name);
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
||||
|
||||
/// Container configuration options
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `container` - Container ID or name
|
||||
/// * `options` - Map of configuration options
|
||||
///
|
||||
/// # Returns
|
||||
/// * Result with command output or error
|
||||
pub fn config(container: &str, options: HashMap<String, String>) -> Result<CommandResult, BuildahError> {
|
||||
let mut args_owned: Vec<String> = Vec::new();
|
||||
args_owned.push("config".to_string());
|
||||
|
||||
// Process options map
|
||||
for (key, value) in options.iter() {
|
||||
let option_name = format!("--{}", key);
|
||||
args_owned.push(option_name);
|
||||
args_owned.push(value.clone());
|
||||
}
|
||||
|
||||
args_owned.push(container.to_string());
|
||||
|
||||
// Convert Vec<String> to Vec<&str> for execute_buildah_command
|
||||
let args: Vec<&str> = args_owned.iter().map(|s| s.as_str()).collect();
|
||||
|
||||
execute_buildah_command(&args)
|
||||
}
|
@ -1,14 +1,48 @@
|
||||
// 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;
|
||||
use std::fmt;
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
|
||||
pub use engine::*;
|
||||
pub use buildah_images::*;
|
||||
pub use buildah_build::*;
|
||||
pub use buildah_register::*;
|
||||
/// Error type for buildah operations
|
||||
#[derive(Debug)]
|
||||
pub enum BuildahError {
|
||||
/// The buildah command failed to execute
|
||||
CommandExecutionFailed(io::Error),
|
||||
/// The buildah command executed but returned an error
|
||||
CommandFailed(String),
|
||||
/// Failed to parse JSON output
|
||||
JsonParseError(String),
|
||||
/// Failed to convert data
|
||||
ConversionError(String),
|
||||
/// Generic error
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for BuildahError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
BuildahError::CommandExecutionFailed(e) => write!(f, "Failed to execute buildah command: {}", e),
|
||||
BuildahError::CommandFailed(e) => write!(f, "Buildah command failed: {}", e),
|
||||
BuildahError::JsonParseError(e) => write!(f, "Failed to parse JSON: {}", e),
|
||||
BuildahError::ConversionError(e) => write!(f, "Conversion error: {}", e),
|
||||
BuildahError::Other(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for BuildahError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
BuildahError::CommandExecutionFailed(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use containers::*;
|
||||
pub use images::*;
|
||||
pub use cmd::*;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user