...
This commit is contained in:
parent
6cc05ad2eb
commit
a32cfb788b
@ -1,9 +1,11 @@
|
|||||||
// Basic buildah operations for container management
|
// Basic buildah operations for container management
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use crate::process::CommandResult;
|
||||||
|
use super::BuildahError;
|
||||||
|
|
||||||
|
|
||||||
/// Execute a buildah command and return the result
|
/// Execute a buildah command and return the result
|
||||||
pub fn execute_buildah_command(args: &[&str]) -> Dynamic {
|
pub fn execute_buildah_command(args: &[&str]) -> Result<CommandResult, BuildahError> {
|
||||||
let output = Command::new("buildah")
|
let output = Command::new("buildah")
|
||||||
.args(args)
|
.args(args)
|
||||||
.output();
|
.output();
|
||||||
@ -20,10 +22,15 @@ pub fn execute_buildah_command(args: &[&str]) -> Dynamic {
|
|||||||
code: output.status.code().unwrap_or(-1),
|
code: output.status.code().unwrap_or(-1),
|
||||||
};
|
};
|
||||||
|
|
||||||
result.to_dynamic()
|
if result.success {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(BuildahError::CommandFailed(format!("Command failed with code {}: {}",
|
||||||
|
result.code, result.stderr.trim())))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
CommandResult::error(&format!("Failed to execute buildah command: {}", e)).to_dynamic()
|
Err(BuildahError::CommandExecutionFailed(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,38 @@
|
|||||||
|
|
||||||
use crate::virt::buildah::execute_buildah_command;
|
use crate::virt::buildah::execute_buildah_command;
|
||||||
|
use crate::process::CommandResult;
|
||||||
|
use super::BuildahError;
|
||||||
|
|
||||||
/// Create a container from an image
|
/// Create a container from an image
|
||||||
pub fn build_from(image: &str) -> Dynamic {
|
pub fn from(image: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["from", image])
|
execute_buildah_command(&["from", image])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a command in a container
|
/// Run a command in a container
|
||||||
pub fn build_run(container: &str, command: &str) -> Dynamic {
|
pub fn run(container: &str, command: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["run", container, "sh", "-c", command])
|
execute_buildah_command(&["run", container, "sh", "-c", command])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy files into a container
|
/// Copy files into a container
|
||||||
pub fn build_copy(container: &str, source: &str, dest: &str) -> Dynamic {
|
pub fn copy(container: &str, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["copy", container, source, dest])
|
execute_buildah_command(&["copy", container, source, dest])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_add(container: &str, source: &str, dest: &str) -> Dynamic {
|
pub fn add(container: &str, source: &str, dest: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["add", container, source, dest])
|
execute_buildah_command(&["add", container, source, dest])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commit a container to an image
|
/// Commit a container to an image
|
||||||
pub fn build_commit(container: &str, image_name: &str) -> Dynamic {
|
pub fn commit(container: &str, image_name: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["commit", container, image_name])
|
execute_buildah_command(&["commit", container, image_name])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Remove a container
|
/// Remove a container
|
||||||
pub fn build_remove(container: &str) -> Dynamic {
|
pub fn remove(container: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["rm", container])
|
execute_buildah_command(&["rm", container])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List containers
|
/// List containers
|
||||||
pub fn build_list() -> Dynamic {
|
pub fn list() -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["containers"])
|
execute_buildah_command(&["containers"])
|
||||||
}
|
}
|
||||||
|
@ -1,103 +1,98 @@
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::collections::HashMap;
|
||||||
use crate::virt::buildah::execute_buildah_command;
|
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
|
/// List images in local storage
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Array of image details on success or error details
|
/// * Result with array of Image objects on success or error details
|
||||||
pub fn images() -> Dynamic {
|
pub fn images() -> Result<Vec<Image>, BuildahError> {
|
||||||
let result = execute_buildah_command(&["images", "--format", "json"]);
|
let result = execute_buildah_command(&["images", "--format", "json"])?;
|
||||||
|
|
||||||
let result_map = match result.clone().try_cast::<Map>() {
|
// Try to parse the JSON output
|
||||||
Some(map) => map,
|
match serde_json::from_str::<serde_json::Value>(&result.stdout) {
|
||||||
None => {
|
Ok(json) => {
|
||||||
return create_result("", "Failed to convert result to map", false, -1);
|
if let Value::Array(images_json) = json {
|
||||||
}
|
let mut images = Vec::new();
|
||||||
};
|
|
||||||
|
for image_json in images_json {
|
||||||
let success = match result_map.get("success") {
|
// Extract image ID
|
||||||
Some(val) => val.as_bool().unwrap_or(false),
|
let id = match image_json.get("id").and_then(|v| v.as_str()) {
|
||||||
None => false,
|
Some(id) => id.to_string(),
|
||||||
};
|
None => return Err(BuildahError::ConversionError("Missing image ID".to_string())),
|
||||||
|
};
|
||||||
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 {
|
// Extract image names
|
||||||
let mut image_map = Map::new();
|
let names = match image_json.get("names").and_then(|v| v.as_array()) {
|
||||||
|
Some(names_array) => {
|
||||||
if let Some(id) = image.get("id").and_then(|v| v.as_str()) {
|
let mut names_vec = Vec::new();
|
||||||
image_map.insert("id".into(), Dynamic::from(id.to_string()));
|
for name_value in names_array {
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
if let Some(name_str) = name_value.as_str() {
|
||||||
names_array.push(Dynamic::from(name_str.to_string()));
|
names_vec.push(name_str.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
image_map.insert("names".into(), Dynamic::from(names_array));
|
names_vec
|
||||||
}
|
},
|
||||||
|
None => Vec::new(), // Empty vector if no names found
|
||||||
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)
|
// Extract image size
|
||||||
} else {
|
let size = match image_json.get("size").and_then(|v| v.as_str()) {
|
||||||
create_result(
|
Some(size) => size.to_string(),
|
||||||
"",
|
None => "Unknown".to_string(), // Default value if size not found
|
||||||
"Failed to parse image list: Expected JSON array",
|
};
|
||||||
false,
|
|
||||||
-1
|
// 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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
Err(e) => {
|
Ok(images)
|
||||||
create_result(
|
} else {
|
||||||
"",
|
Err(BuildahError::JsonParseError("Expected JSON array".to_string()))
|
||||||
&format!("Failed to parse image list JSON: {}", e),
|
|
||||||
false,
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
Err(BuildahError::JsonParseError(format!("Failed to parse image list JSON: {}", e)))
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Remove one or more images
|
/// Remove one or more images
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `image` - Image ID or name
|
/// * `image` - Image ID or name
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Success or error details
|
/// * Result with command output or error
|
||||||
pub fn image_remove(image: &str) -> Dynamic {
|
pub fn image_remove(image: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["rmi", image])
|
execute_buildah_command(&["rmi", image])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,8 +104,8 @@ pub fn image_remove(image: &str) -> Dynamic {
|
|||||||
/// * `tls_verify` - Whether to verify TLS (default: true)
|
/// * `tls_verify` - Whether to verify TLS (default: true)
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Success or error details
|
/// * Result with command output or error
|
||||||
pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Dynamic {
|
pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
||||||
let mut args = vec!["push"];
|
let mut args = vec!["push"];
|
||||||
|
|
||||||
if !tls_verify {
|
if !tls_verify {
|
||||||
@ -130,8 +125,8 @@ pub fn image_push(image: &str, destination: &str, tls_verify: bool) -> Dynamic {
|
|||||||
/// * `new_name` - New name for the image
|
/// * `new_name` - New name for the image
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Success or error details
|
/// * Result with command output or error
|
||||||
pub fn image_tag(image: &str, new_name: &str) -> Dynamic {
|
pub fn image_tag(image: &str, new_name: &str) -> Result<CommandResult, BuildahError> {
|
||||||
execute_buildah_command(&["tag", image, new_name])
|
execute_buildah_command(&["tag", image, new_name])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +137,8 @@ pub fn image_tag(image: &str, new_name: &str) -> Dynamic {
|
|||||||
/// * `tls_verify` - Whether to verify TLS (default: true)
|
/// * `tls_verify` - Whether to verify TLS (default: true)
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Success or error details
|
/// * Result with command output or error
|
||||||
pub fn image_pull(image: &str, tls_verify: bool) -> Dynamic {
|
pub fn image_pull(image: &str, tls_verify: bool) -> Result<CommandResult, BuildahError> {
|
||||||
let mut args = vec!["pull"];
|
let mut args = vec!["pull"];
|
||||||
|
|
||||||
if !tls_verify {
|
if !tls_verify {
|
||||||
@ -165,8 +160,8 @@ pub fn image_pull(image: &str, tls_verify: bool) -> Dynamic {
|
|||||||
/// * `rm` - Whether to remove the container after commit
|
/// * `rm` - Whether to remove the container after commit
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Success or error details
|
/// * Result with command output or error
|
||||||
pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool) -> Dynamic {
|
pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squash: bool, rm: bool) -> Result<CommandResult, BuildahError> {
|
||||||
let mut args = vec!["commit"];
|
let mut args = vec!["commit"];
|
||||||
|
|
||||||
if let Some(format_str) = format {
|
if let Some(format_str) = format {
|
||||||
@ -195,8 +190,8 @@ pub fn image_commit(container: &str, image_name: &str, format: Option<&str>, squ
|
|||||||
/// * `options` - Map of configuration options
|
/// * `options` - Map of configuration options
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * Success or error details
|
/// * Result with command output or error
|
||||||
pub fn config(container: &str, options: Map) -> Dynamic {
|
pub fn config(container: &str, options: HashMap<String, String>) -> Result<CommandResult, BuildahError> {
|
||||||
let mut args_owned: Vec<String> = Vec::new();
|
let mut args_owned: Vec<String> = Vec::new();
|
||||||
args_owned.push("config".to_string());
|
args_owned.push("config".to_string());
|
||||||
|
|
||||||
@ -204,10 +199,7 @@ pub fn config(container: &str, options: Map) -> Dynamic {
|
|||||||
for (key, value) in options.iter() {
|
for (key, value) in options.iter() {
|
||||||
let option_name = format!("--{}", key);
|
let option_name = format!("--{}", key);
|
||||||
args_owned.push(option_name);
|
args_owned.push(option_name);
|
||||||
|
args_owned.push(value.clone());
|
||||||
if !value.is_unit() {
|
|
||||||
args_owned.push(value.to_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args_owned.push(container.to_string());
|
args_owned.push(container.to_string());
|
||||||
@ -217,4 +209,3 @@ pub fn config(container: &str, options: Map) -> Dynamic {
|
|||||||
|
|
||||||
execute_buildah_command(&args)
|
execute_buildah_command(&args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,46 @@ mod containers;
|
|||||||
mod images;
|
mod images;
|
||||||
mod cmd;
|
mod cmd;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
/// 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 containers::*;
|
||||||
pub use images::*;
|
pub use images::*;
|
||||||
pub use cmd::*;
|
pub use cmd::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user