...
This commit is contained in:
parent
78db13d738
commit
4be9445702
@ -11,6 +11,7 @@ categories = ["os", "filesystem", "api-bindings"]
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tera = "1.19.0" # Template engine for text rendering
|
||||||
# Cross-platform functionality
|
# Cross-platform functionality
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
|
66
src/examples/template_example.rs
Normal file
66
src/examples/template_example.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
use sal::text::TemplateBuilder;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
// Create a temporary template file for our examples
|
||||||
|
let temp_file = NamedTempFile::new()?;
|
||||||
|
let template_content = "Hello, {{ name }}! Welcome to {{ place }}.\n\
|
||||||
|
{% if show_greeting %}Glad to have you here!{% endif %}\n\
|
||||||
|
Your items:\n\
|
||||||
|
{% for item in items %} - {{ item }}{% if not loop.last %}\n{% endif %}{% endfor %}\n";
|
||||||
|
std::fs::write(temp_file.path(), template_content)?;
|
||||||
|
|
||||||
|
println!("Created temporary template at: {}", temp_file.path().display());
|
||||||
|
|
||||||
|
// Example 1: Simple variable replacement
|
||||||
|
println!("\n--- Example 1: Simple variable replacement ---");
|
||||||
|
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
||||||
|
builder = builder
|
||||||
|
.add_var("name", "John")
|
||||||
|
.add_var("place", "Rust")
|
||||||
|
.add_var("show_greeting", true)
|
||||||
|
.add_var("items", vec!["apple", "banana", "cherry"]);
|
||||||
|
|
||||||
|
let result = builder.render()?;
|
||||||
|
println!("Rendered template:\n{}", result);
|
||||||
|
|
||||||
|
// Example 2: Using a HashMap for variables
|
||||||
|
println!("\n--- Example 2: Using a HashMap for variables ---");
|
||||||
|
let mut vars = HashMap::new();
|
||||||
|
vars.insert("name", "Alice");
|
||||||
|
vars.insert("place", "Template World");
|
||||||
|
|
||||||
|
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
||||||
|
builder = builder
|
||||||
|
.add_vars(vars)
|
||||||
|
.add_var("show_greeting", false)
|
||||||
|
.add_var("items", vec!["laptop", "phone", "tablet"]);
|
||||||
|
|
||||||
|
let result = builder.render()?;
|
||||||
|
println!("Rendered template with HashMap:\n{}", result);
|
||||||
|
|
||||||
|
// Example 3: Rendering to a file
|
||||||
|
println!("\n--- Example 3: Rendering to a file ---");
|
||||||
|
let output_file = NamedTempFile::new()?;
|
||||||
|
|
||||||
|
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
||||||
|
builder = builder
|
||||||
|
.add_var("name", "Bob")
|
||||||
|
.add_var("place", "File Output")
|
||||||
|
.add_var("show_greeting", true)
|
||||||
|
.add_var("items", vec!["document", "spreadsheet", "presentation"]);
|
||||||
|
|
||||||
|
builder.render_to_file(output_file.path())?;
|
||||||
|
println!("Template rendered to file: {}", output_file.path().display());
|
||||||
|
|
||||||
|
// Read the output file to verify
|
||||||
|
let output_content = std::fs::read_to_string(output_file.path())?;
|
||||||
|
println!("Content of the rendered file:\n{}", output_content);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use rhai::{Engine, EvalAltResult, Array, Dynamic, Map};
|
use rhai::{Engine, EvalAltResult, Array, Dynamic, Map};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::virt::buildah::{self, BuildahError, Image, Builder};
|
use crate::virt::buildah::{self, BuildahError, Image, Builder, ContentOperations};
|
||||||
use crate::process::CommandResult;
|
use crate::process::CommandResult;
|
||||||
|
|
||||||
/// Register Buildah module functions with the Rhai engine
|
/// Register Buildah module functions with the Rhai engine
|
||||||
@ -150,12 +150,26 @@ pub fn builder_config(builder: &mut Builder, options: Map) -> Result<CommandResu
|
|||||||
|
|
||||||
/// Write content to a file in the container
|
/// Write content to a file in the container
|
||||||
pub fn builder_write_content(builder: &mut Builder, content: &str, dest_path: &str) -> Result<CommandResult, Box<EvalAltResult>> {
|
pub fn builder_write_content(builder: &mut Builder, content: &str, dest_path: &str) -> Result<CommandResult, Box<EvalAltResult>> {
|
||||||
bah_error_to_rhai_error(builder.write_content(content, dest_path))
|
if let Some(container_id) = builder.container_id() {
|
||||||
|
bah_error_to_rhai_error(ContentOperations::write_content(container_id, content, dest_path))
|
||||||
|
} else {
|
||||||
|
Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
"No container ID available".into(),
|
||||||
|
rhai::Position::NONE
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read content from a file in the container
|
/// Read content from a file in the container
|
||||||
pub fn builder_read_content(builder: &mut Builder, source_path: &str) -> Result<String, Box<EvalAltResult>> {
|
pub fn builder_read_content(builder: &mut Builder, source_path: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
bah_error_to_rhai_error(builder.read_content(source_path))
|
if let Some(container_id) = builder.container_id() {
|
||||||
|
bah_error_to_rhai_error(ContentOperations::read_content(container_id, source_path))
|
||||||
|
} else {
|
||||||
|
Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
"No container ID available".into(),
|
||||||
|
rhai::Position::NONE
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder static methods
|
// Builder static methods
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
mod dedent;
|
mod dedent;
|
||||||
mod fix;
|
mod fix;
|
||||||
mod replace;
|
mod replace;
|
||||||
|
mod template;
|
||||||
|
|
||||||
pub use dedent::*;
|
pub use dedent::*;
|
||||||
pub use fix::*;
|
pub use fix::*;
|
||||||
pub use replace::*;
|
pub use replace::*;
|
||||||
|
pub use template::*;
|
@ -210,9 +210,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_template_rendering() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_template_rendering() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Create a temporary template file
|
// Create a temporary template file
|
||||||
let mut temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
writeln!(temp_file, "Hello, {{ name }}! Welcome to {{ place }}.")?;
|
let template_content = "Hello, {{ name }}! Welcome to {{ place }}.\n";
|
||||||
temp_file.flush()?;
|
fs::write(temp_file.path(), template_content)?;
|
||||||
|
|
||||||
// Create a template builder and add variables
|
// Create a template builder and add variables
|
||||||
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
||||||
@ -230,10 +230,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_template_with_multiple_vars() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_template_with_multiple_vars() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Create a temporary template file
|
// Create a temporary template file
|
||||||
let mut temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
writeln!(temp_file, "{% if show_greeting %}Hello, {{ name }}!{% endif %}")?;
|
let template_content = "{% if show_greeting %}Hello, {{ name }}!{% endif %}\n{% for item in items %}{{ item }}{% if not loop.last %}, {% endif %}{% endfor %}\n";
|
||||||
writeln!(temp_file, "{% for item in items %}{{ item }}{% if not loop.last %}, {% endif %}{% endfor %}")?;
|
fs::write(temp_file.path(), template_content)?;
|
||||||
temp_file.flush()?;
|
|
||||||
|
|
||||||
// Create a template builder and add variables
|
// Create a template builder and add variables
|
||||||
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
let mut builder = TemplateBuilder::open(temp_file.path())?;
|
||||||
@ -273,13 +272,13 @@ mod tests {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_render_to_file() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_render_to_file() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Create a temporary template file
|
// Create a temporary template file
|
||||||
let mut temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
writeln!(temp_file, "{{ message }}")?;
|
let template_content = "{{ message }}\n";
|
||||||
temp_file.flush()?;
|
fs::write(temp_file.path(), template_content)?;
|
||||||
|
|
||||||
|
|
||||||
// Create an output file
|
// Create an output file
|
||||||
let output_file = NamedTempFile::new()?;
|
let output_file = NamedTempFile::new()?;
|
||||||
|
@ -11,6 +11,8 @@ pub struct Builder {
|
|||||||
container_id: Option<String>,
|
container_id: Option<String>,
|
||||||
/// Base image
|
/// Base image
|
||||||
image: String,
|
image: String,
|
||||||
|
/// Debug mode
|
||||||
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
@ -37,6 +39,7 @@ impl Builder {
|
|||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
container_id: Some(container_id),
|
container_id: Some(container_id),
|
||||||
image: image.to_string(),
|
image: image.to_string(),
|
||||||
|
debug: false,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Err(BuildahError::CommandFailed(error_msg)) => {
|
Err(BuildahError::CommandFailed(error_msg)) => {
|
||||||
@ -58,6 +61,7 @@ impl Builder {
|
|||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
container_id: Some(container_id),
|
container_id: Some(container_id),
|
||||||
image: image.to_string(),
|
image: image.to_string(),
|
||||||
|
debug: false,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Couldn't extract container ID
|
// Couldn't extract container ID
|
||||||
@ -85,6 +89,17 @@ impl Builder {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the debug mode
|
||||||
|
pub fn debug(&self) -> bool {
|
||||||
|
self.debug
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the debug mode
|
||||||
|
pub fn set_debug(&mut self, debug: bool) -> &mut Self {
|
||||||
|
self.debug = debug;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the base image
|
/// Get the base image
|
||||||
pub fn image(&self) -> &str {
|
pub fn image(&self) -> &str {
|
||||||
&self.image
|
&self.image
|
||||||
|
70
src/virt/buildah/content.rs
Normal file
70
src/virt/buildah/content.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use crate::process::CommandResult;
|
||||||
|
use crate::virt::buildah::{execute_buildah_command, BuildahError};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
/// Functions for working with file content in buildah containers
|
||||||
|
pub struct ContentOperations;
|
||||||
|
|
||||||
|
impl ContentOperations {
|
||||||
|
/// Write content to a file in the container
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `container_id` - The container ID
|
||||||
|
/// * `content` - The content to write
|
||||||
|
/// * `dest_path` - Destination path in the container
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<CommandResult, BuildahError>` - Command result or error
|
||||||
|
pub fn write_content(container_id: &str, content: &str, dest_path: &str) -> Result<CommandResult, BuildahError> {
|
||||||
|
// Create a temporary file
|
||||||
|
let mut temp_file = NamedTempFile::new()
|
||||||
|
.map_err(|e| BuildahError::Other(format!("Failed to create temporary file: {}", e)))?;
|
||||||
|
|
||||||
|
// Write content to the temporary file
|
||||||
|
temp_file.write_all(content.as_bytes())
|
||||||
|
.map_err(|e| BuildahError::Other(format!("Failed to write to temporary file: {}", e)))?;
|
||||||
|
|
||||||
|
// Flush the file to ensure content is written
|
||||||
|
temp_file.flush()
|
||||||
|
.map_err(|e| BuildahError::Other(format!("Failed to flush temporary file: {}", e)))?;
|
||||||
|
|
||||||
|
// Copy the temporary file to the container
|
||||||
|
let temp_path = temp_file.path().to_string_lossy().to_string();
|
||||||
|
execute_buildah_command(&["copy", container_id, &temp_path, dest_path])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read content from a file in the container
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `container_id` - The container ID
|
||||||
|
/// * `source_path` - Source path in the container
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<String, BuildahError>` - File content or error
|
||||||
|
pub fn read_content(container_id: &str, source_path: &str) -> Result<String, BuildahError> {
|
||||||
|
// Create a temporary file
|
||||||
|
let temp_file = NamedTempFile::new()
|
||||||
|
.map_err(|e| BuildahError::Other(format!("Failed to create temporary file: {}", e)))?;
|
||||||
|
|
||||||
|
let temp_path = temp_file.path().to_string_lossy().to_string();
|
||||||
|
|
||||||
|
// Copy the file from the container to the temporary file
|
||||||
|
execute_buildah_command(&["copy", container_id, source_path, &temp_path])?;
|
||||||
|
|
||||||
|
// Read the content from the temporary file
|
||||||
|
let mut file = File::open(temp_file.path())
|
||||||
|
.map_err(|e| BuildahError::Other(format!("Failed to open temporary file: {}", e)))?;
|
||||||
|
|
||||||
|
let mut content = String::new();
|
||||||
|
file.read_to_string(&mut content)
|
||||||
|
.map_err(|e| BuildahError::Other(format!("Failed to read from temporary file: {}", e)))?;
|
||||||
|
|
||||||
|
Ok(content)
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ mod containers;
|
|||||||
mod images;
|
mod images;
|
||||||
mod cmd;
|
mod cmd;
|
||||||
mod builder;
|
mod builder;
|
||||||
|
mod content;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod containers_test;
|
mod containers_test;
|
||||||
|
|
||||||
@ -52,4 +53,5 @@ pub use builder::Builder;
|
|||||||
pub use containers::*;
|
pub use containers::*;
|
||||||
#[deprecated(since = "0.2.0", note = "Use Builder methods instead")]
|
#[deprecated(since = "0.2.0", note = "Use Builder methods instead")]
|
||||||
pub use images::*;
|
pub use images::*;
|
||||||
pub use cmd::*;
|
pub use cmd::*;
|
||||||
|
pub use content::ContentOperations;
|
Loading…
Reference in New Issue
Block a user